2006-02-16 Martin Baulig <martin@ximian.com>
authorMartin Baulig <martin@novell.com>
Thu, 16 Feb 2006 13:26:41 +0000 (13:26 -0000)
committerMartin Baulig <martin@novell.com>
Thu, 16 Feb 2006 13:26:41 +0000 (13:26 -0000)
* C5/: New directory containing all the source code.

svn path=/trunk/mcs/; revision=56920

44 files changed:
mcs/class/Mono.C5/AssemblyInfo.cs [deleted file]
mcs/class/Mono.C5/Builder.cs [deleted file]
mcs/class/Mono.C5/C5.csproj [deleted file]
mcs/class/Mono.C5/C5.csproj.user [deleted file]
mcs/class/Mono.C5/C5/AssemblyInfo.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Builder.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/C5.csproj [new file with mode: 0644]
mcs/class/Mono.C5/C5/C5.csproj.user [new file with mode: 0644]
mcs/class/Mono.C5/C5/Collections.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Dictionaries.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Interfaces.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Wrappers.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/arrays/ArrayList.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/arrays/HashedArray.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/arrays/SortedArray.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/hashing/HashBag.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/hashing/HashDictionary.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/hashing/HashTable.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/heaps/IntervalHeap.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/linkedlists/HashedLinkedLIst.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/linkedlists/LinkedList.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/trees/RedBlackTree.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/trees/RedBlackTreeBag.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/trees/TreeDictionary.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/trees/set2bag.pl [new file with mode: 0644]
mcs/class/Mono.C5/ChangeLog
mcs/class/Mono.C5/Collections.cs [deleted file]
mcs/class/Mono.C5/Dictionaries.cs [deleted file]
mcs/class/Mono.C5/Interfaces.cs [deleted file]
mcs/class/Mono.C5/Mono.C5.dll.sources
mcs/class/Mono.C5/Wrappers.cs [deleted file]
mcs/class/Mono.C5/arrays/ArrayList.cs [deleted file]
mcs/class/Mono.C5/arrays/HashedArray.cs [deleted file]
mcs/class/Mono.C5/arrays/SortedArray.cs [deleted file]
mcs/class/Mono.C5/hashing/HashBag.cs [deleted file]
mcs/class/Mono.C5/hashing/HashDictionary.cs [deleted file]
mcs/class/Mono.C5/hashing/HashTable.cs [deleted file]
mcs/class/Mono.C5/heaps/IntervalHeap.cs [deleted file]
mcs/class/Mono.C5/linkedlists/HashedLinkedLIst.cs [deleted file]
mcs/class/Mono.C5/linkedlists/LinkedList.cs [deleted file]
mcs/class/Mono.C5/trees/RedBlackTree.cs [deleted file]
mcs/class/Mono.C5/trees/RedBlackTreeBag.cs [deleted file]
mcs/class/Mono.C5/trees/TreeDictionary.cs [deleted file]
mcs/class/Mono.C5/trees/set2bag.pl [deleted file]

diff --git a/mcs/class/Mono.C5/AssemblyInfo.cs b/mcs/class/Mono.C5/AssemblyInfo.cs
deleted file mode 100644 (file)
index b4de16b..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System.Reflection;\r
-using System.Runtime.CompilerServices;\r
-\r
-//\r
-// General Information about an assembly is controlled through the following \r
-// set of attributes. Change these attribute values to modify the information\r
-// associated with an assembly.\r
-//\r
-[assembly: AssemblyTitle("C5: Copenhagen Comprehensive Collection Classes for CLI")]\r
-[assembly: AssemblyDescription("This is a debug build of prerelease 0.5")]\r
-[assembly: AssemblyConfiguration("")]\r
-[assembly: AssemblyCompany("")]\r
-[assembly: AssemblyProduct("")]\r
-[assembly: AssemblyCopyright("(c) 2003-2004 Niels Kokholm <kokholm@itu.dk>, Peter Sestoft <sestoft@dina.kvl.dk>")]\r
-[assembly: AssemblyTrademark("")]\r
-[assembly: AssemblyCulture("")]\r
-\r
-//\r
-// Version information for an assembly consists of the following four values:\r
-//\r
-//      Major Version\r
-//      Minor Version \r
-//      Build Number\r
-//      Revision\r
-//\r
-// You can specify all the values or you can default the Revision and Build Numbers \r
-// by using the '*' as shown below:\r
-\r
-[assembly: AssemblyVersion("0.5.1.1")]\r
-\r
-//\r
-// In order to sign your assembly you must specify a key to use. Refer to the \r
-// Microsoft .NET Framework documentation for more information on assembly signing.\r
-//\r
-// Use the attributes below to control which key is used for signing. \r
-//\r
-// Notes: \r
-//   (*) If no key is specified, the assembly is not signed.\r
-//   (*) KeyName refers to a key that has been installed in the Crypto Service\r
-//       Provider (CSP) on your machine. KeyFile refers to a file which contains\r
-//       a key.\r
-//   (*) If the KeyFile and the KeyName values are both specified, the \r
-//       following processing occurs:\r
-//       (1) If the KeyName can be found in the CSP, that key is used.\r
-//       (2) If the KeyName does not exist and the KeyFile does exist, the key \r
-//           in the KeyFile is installed into the CSP and used.\r
-//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.\r
-//       When specifying the KeyFile, the location of the KeyFile should be\r
-//       relative to the project output directory which is\r
-//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is\r
-//       located in the project directory, you would specify the AssemblyKeyFile \r
-//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]\r
-//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework\r
-//       documentation for more information on this.\r
-//\r
-[assembly: AssemblyDelaySign (true)]\r
-[assembly: AssemblyKeyFile ("c5.pub")]\r
diff --git a/mcs/class/Mono.C5/Builder.cs b/mcs/class/Mono.C5/Builder.cs
deleted file mode 100644 (file)
index feb2981..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using C5;\r
-using System;\r
-using System.Reflection;\r
-using System.Reflection.Emit;\r
-using System.Diagnostics;\r
-namespace C5.ComparerBuilder\r
-{\r
-    /// <summary>\r
-    /// A default item comparer for an item type that is either generic (IComparable&lt;T&gt;)\r
-    /// or ordinarily (System.IComparable) comparable.\r
-    /// </summary>\r
-    public class FromComparable<T>\r
-    {\r
-        static Type naturalComparerO = typeof(NaturalComparerO<>);\r
-\r
-        static Type naturalComparer = typeof(NaturalComparer<>);\r
-\r
-\r
-        /// <summary>\r
-        /// Create a default comparer\r
-        /// <exception cref="ArgumentException"/> if T is not comparable. \r
-        /// </summary>\r
-        /// <returns>The comparer</returns>\r
-        [Tested]\r
-        public static IComparer<T> Examine()\r
-        {\r
-            Type t = typeof(T);\r
-\r
-            if (t.Equals(typeof(int)))\r
-                return (IComparer<T>)(new IC());\r
-\r
-            if (typeof(IComparable<T>).IsAssignableFrom(t))\r
-            {\r
-                Type c = naturalComparer.MakeGenericType (t);\r
-\r
-                return (IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
-            }\r
-\r
-            if (t.GetInterface("System.IComparable") != null)\r
-            {\r
-                Type c = naturalComparerO.MakeGenericType (t);\r
-\r
-                return (IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
-            }\r
-\r
-            throw new ArgumentException(String.Format("Cannot make IComparer<{0}>", t));\r
-        }\r
-    }\r
-}\r
-namespace C5.HasherBuilder\r
-{\r
-    /// <summary>\r
-    /// Prototype for an sequenced hasher for IIndexed[W]\r
-    /// This will use the IIndexed[W] specific operations\r
-    /// </summary>\r
-    public class SequencedHasher<S, W> : IHasher<S>\r
-        where S : ISequenced<W>\r
-    {\r
-        /// <summary>\r
-        /// Get the hash code with respect to this sequenced hasher\r
-        /// </summary>\r
-        /// <param name="item">The item</param>\r
-        /// <returns>The hash code</returns>\r
-        [Tested]\r
-        public int GetHashCode(S item) { return item.GetHashCode(); }\r
-\r
-\r
-        /// <summary>\r
-        /// Check if two items are equal with respect to this sequenced hasher\r
-        /// </summary>\r
-        /// <param name="i1">first item</param>\r
-        /// <param name="i2">second item</param>\r
-        /// <returns>True if equal</returns>\r
-        [Tested]\r
-        public bool Equals(S i1, S i2) { return i1 == null ? i2 == null : i1.Equals(i2); }\r
-    }\r
-\r
-\r
-\r
-    /// <summary>\r
-    /// Prototype for an unsequenced hasher for ICollection[W]\r
-    /// This will use the ICollection[W] specific operations\r
-    /// </summary>\r
-    public class UnsequencedHasher<S, W> : IHasher<S>\r
-        where S : ICollection<W>\r
-    {\r
-        /// <summary>\r
-        /// Get the hash code with respect to this unsequenced hasher\r
-        /// </summary>\r
-        /// <param name="item">The item</param>\r
-        /// <returns>The hash code</returns>\r
-        [Tested]\r
-        public int GetHashCode(S item) { return item.GetHashCode(); }\r
-\r
-\r
-        /// <summary>\r
-        /// Check if two items are equal with respect to this unsequenced hasher\r
-        /// </summary>\r
-        /// <param name="i1">first item</param>\r
-        /// <param name="i2">second item</param>\r
-        /// <returns>True if equal</returns>\r
-        [Tested]\r
-        public bool Equals(S i1, S i2) { return i1 == null ? i2 == null : i1.Equals(i2); }\r
-    }\r
-\r
-\r
-\r
-    /// <summary>\r
-    /// Create a hasher for T that is DefaultValueTypeHasher[T] \r
-    /// or DefaultReferenceTypeHasher[T] unless T has been \r
-    /// instatiated to a type of the exact form IIndexed[W] or ICollection[W]\r
-    /// in which case Examine will return Sequenced- repectively UnsequencedHasher.\r
-    /// </summary>\r
-    public class ByPrototype<T>\r
-    {\r
-        static Type isequenced = typeof(ISequenced<>);\r
-\r
-        static Type ieditable = typeof(ICollection<>);\r
-\r
-        static Type orderedhasher = typeof(HasherBuilder.SequencedHasher<,>);\r
-\r
-        static Type unorderedhasher = typeof(HasherBuilder.UnsequencedHasher<,>);\r
-/*\r
-        static Type isequenced = Type.GetType("C5.ISequenced");\r
-\r
-        static Type ieditable = Type.GetType("C5.ICollection");\r
-\r
-        static Type orderedhasher = Type.GetType("C5.HasherBuilder.SequencedHasher");\r
-\r
-        static Type unorderedhasher = Type.GetType("C5.HasherBuilder.UnsequencedHasher");\r
-*/\r
-\r
-        /// <summary>\r
-        /// See class description\r
-        /// </summary>\r
-        /// <returns>The hasher</returns>\r
-        [Tested]\r
-        public static IHasher<T> Examine()\r
-        {\r
-            Type t = typeof(T);\r
-\r
-            if (!t.IsGenericType)\r
-            {\r
-                if (t.Equals(typeof(int)))\r
-                    return (IHasher<T>)(new IntHasher());\r
-                else if (t.IsValueType)\r
-                    return new DefaultValueTypeHasher<T>();\r
-                else\r
-                    return new DefaultReferenceTypeHasher<T>();\r
-            }\r
-\r
-            Type s = t.GetGenericTypeDefinition();\r
-            Type[] v = t.GetGenericArguments();\r
-            Type b;\r
-\r
-            if (s.Equals(isequenced))\r
-                b = orderedhasher;\r
-            else if (s.Equals(ieditable))\r
-                b = unorderedhasher;\r
-            else if (t.IsValueType)\r
-                return new DefaultValueTypeHasher<T>();\r
-            else\r
-                return new DefaultReferenceTypeHasher<T>();\r
-\r
-            Type c = b.MakeGenericType ( t, v[0] );\r
-\r
-            return (IHasher<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
-        }\r
-    }\r
-\r
-\r
-#if !EXPERIMENTAL\r
-\r
-    /// <summary>\r
-    /// IHasher factory class: examines at instatiation time if T is an\r
-    /// interface implementing "int GetHashCode()" and "bool Equals(T)".\r
-    /// If those are not present, MakeHasher will return a default hasher,\r
-    /// else this class will implement Ihasher[T] via Invoke() on the\r
-    /// reflected method infos.\r
-    /// </summary>\r
-    public class ByInvoke<T> : IHasher<T>\r
-    {\r
-        internal static readonly System.Reflection.MethodInfo hinfo, einfo;\r
-\r
-\r
-        static ByInvoke()\r
-        {\r
-            Type t = typeof(T);\r
-\r
-            if (!t.IsInterface) return;\r
-\r
-            BindingFlags f = BindingFlags.Public | BindingFlags.Instance;\r
-\r
-            hinfo = t.GetMethod("GetHashCode", f, null, new Type[0], null);\r
-            einfo = t.GetMethod("Equals", f, null, new Type[1] { t }, null);\r
-        }\r
-\r
-\r
-        private ByInvoke() { }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <returns></returns>\r
-        public static IHasher<T> MakeHasher()\r
-        {\r
-            if (hinfo != null && einfo != null)\r
-                return new ByInvoke<T>();\r
-            else\r
-                return new DefaultReferenceTypeHasher<T>();\r
-        }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <param name="item"></param>\r
-/// <returns></returns>\r
-        public int GetHashCode(T item)\r
-        {\r
-            return (int)(hinfo.Invoke(item, null));\r
-        }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <param name="i1"></param>\r
-/// <param name="i2"></param>\r
-/// <returns></returns>\r
-        public bool Equals(T i1, T i2)\r
-        {\r
-            return (bool)(einfo.Invoke(i1, new object[1] { i2 }));\r
-        }\r
-    }\r
-\r
-\r
-\r
-    /// <summary>\r
-    /// Like ByInvoke, but tries to build a hasher by RTCG to\r
-    /// avoid the Invoke() overhead. Does not work as intended \r
-    /// because of a Whidbey RTCG bug.\r
-    /// </summary>\r
-    public class ByRTCG\r
-    {\r
-        private static ModuleBuilder moduleBuilder;\r
-\r
-        private static AssemblyBuilder assemblyBuilder;\r
-\r
-        private static int uid = 0;\r
-\r
-\r
-        /// <summary>\r
-        /// \r
-        /// </summary>\r
-        /// <param name="hinfo"></param>\r
-        /// <param name="einfo"></param>\r
-        /// <returns></returns>\r
-        public static /*ObjectHasher */ IHasher<T> CreateHasher<T>(MethodInfo hinfo, MethodInfo einfo)\r
-        {\r
-            if (moduleBuilder == null)\r
-            {\r
-                string assmname = "LeFake";\r
-                string filename = assmname + ".dll";\r
-                AssemblyName assemblyName = new AssemblyName("LeFake");\r
-                AppDomain appdomain = AppDomain.CurrentDomain;\r
-                AssemblyBuilderAccess acc = AssemblyBuilderAccess.RunAndSave;\r
-\r
-                assemblyBuilder = appdomain.DefineDynamicAssembly(assemblyName, acc);\r
-                moduleBuilder = assemblyBuilder.DefineDynamicModule(assmname, filename);\r
-            }\r
-\r
-            Type t = typeof(/*object*/ T);\r
-            Type o_t = typeof(object);\r
-            Type h_t = typeof(/*ObjectHasher*/ IHasher<T>);\r
-            Type i_t = typeof(int);\r
-            //TODO: protect uid for thread safety!\r
-            string name = "C5.Dynamic.Hasher_" + uid++;\r
-            TypeAttributes tatt = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;\r
-            TypeBuilder tb = moduleBuilder.DefineType(name, tatt, o_t, new Type[1] { h_t });\r
-            MethodAttributes matt = MethodAttributes.Public | MethodAttributes.Virtual;\r
-            MethodBuilder mb = tb.DefineMethod("GetHashCode", matt, i_t, new Type[1] { t });\r
-            ILGenerator ilg = mb.GetILGenerator();\r
-\r
-            ilg.Emit(OpCodes.Ldarg_1);\r
-            ilg.Emit(OpCodes.Callvirt, hinfo);\r
-            ilg.Emit(OpCodes.Ret);\r
-            mb = tb.DefineMethod("Equals", matt, typeof(bool), new Type[2] { t, t });\r
-            ilg = mb.GetILGenerator();\r
-            ilg.Emit(OpCodes.Ldarg_1);\r
-            ilg.Emit(OpCodes.Ldarg_2);\r
-            ilg.Emit(OpCodes.Callvirt, einfo);\r
-            ilg.Emit(OpCodes.Ret);\r
-\r
-            Type hasher_t = tb.CreateType();\r
-            object hasher = hasher_t.GetConstructor(new Type[0]).Invoke(null);\r
-\r
-            return (IHasher<T>)hasher;\r
-        }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-/// <typeparam name="T"></typeparam>\r
-/// <returns></returns>\r
-        public static IHasher<T> build<T>()\r
-        {\r
-            MethodInfo hinfo = ByInvoke<T>.hinfo, einfo = ByInvoke<T>.einfo;\r
-\r
-            if (hinfo != null && einfo != null)\r
-                return CreateHasher<T>(hinfo, einfo);\r
-            else\r
-                return ByPrototype<T>.Examine();\r
-        }\r
-\r
-/// <summary>\r
-/// \r
-/// </summary>\r
-        public void dump()\r
-        {\r
-            assemblyBuilder.Save("LeFake.dll");\r
-        }\r
-    }\r
-#endif\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/C5.csproj b/mcs/class/Mono.C5/C5.csproj
deleted file mode 100644 (file)
index 2142ae8..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <PropertyGroup>\r
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
-    <ProductVersion>8.0.40607</ProductVersion>\r
-    <SchemaVersion>2.0</SchemaVersion>\r
-    <ProjectGuid>{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}</ProjectGuid>\r
-    <OutputType>Library</OutputType>\r
-    <StartupObject>\r
-    </StartupObject>\r
-    <RootNamespace>C5</RootNamespace>\r
-    <NoStandardLibraries>false</NoStandardLibraries>\r
-    <AssemblyName>C5</AssemblyName>\r
-    <FileUpgradeFlags>\r
-    </FileUpgradeFlags>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">\r
-    <DebugSymbols>true</DebugSymbols>\r
-    <Optimize>false</Optimize>\r
-    <OutputPath>.\bin\Debug\</OutputPath>\r
-    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
-    <DefineConstants>DEBUG;TRACE</DefineConstants>\r
-    <WarningLevel>4</WarningLevel>\r
-    <IncrementalBuild>false</IncrementalBuild>\r
-    <DocumentationFile>c5.xml</DocumentationFile>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">\r
-    <DebugSymbols>false</DebugSymbols>\r
-    <Optimize>true</Optimize>\r
-    <OutputPath>.\bin\Release\</OutputPath>\r
-    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
-    <DefineConstants>TRACE</DefineConstants>\r
-    <WarningLevel>4</WarningLevel>\r
-    <IncrementalBuild>false</IncrementalBuild>\r
-    <DocumentationFile>\r
-    </DocumentationFile>\r
-  </PropertyGroup>\r
-  <ItemGroup>\r
-    <Reference Include="System">\r
-      <HintPath>..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.2.30703\System.dll</HintPath>\r
-      <Name>System</Name>\r
-    </Reference>\r
-    <Reference Include="System.Data">\r
-      <HintPath>..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.2.30703\System.Data.dll</HintPath>\r
-      <Name>System.Data</Name>\r
-    </Reference>\r
-    <Reference Include="System.Xml">\r
-      <HintPath>..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.2.30703\System.XML.dll</HintPath>\r
-      <Name>System.XML</Name>\r
-    </Reference>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <Compile Include="AssemblyInfo.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="Builder.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="Collections.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="Dictionaries.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="Interfaces.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="Wrappers.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="arrays\ArrayList.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="arrays\HashedArray.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="arrays\SortedArray.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="hashing\HashBag.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="hashing\HashDictionary.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="hashing\HashTable.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="heaps\IntervalHeap.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="linkedlists\HashedLinkedList.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="linkedlists\LinkedList.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="trees\RedBlackTree.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="trees\RedBlackTreeBag.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-    <Compile Include="trees\TreeDictionary.cs">\r
-      <SubType>Code</SubType>\r
-    </Compile>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <AppDesigner Include="Project\" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <Folder Include="Project\" />\r
-  </ItemGroup>\r
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />\r
-  <PropertyGroup>\r
-    <PreBuildEvent>\r
-    </PreBuildEvent>\r
-    <PostBuildEvent>\r
-    </PostBuildEvent>\r
-  </PropertyGroup>\r
-  <ProjectExtensions>\r
-    <VisualStudio>\r
-    </VisualStudio>\r
-  </ProjectExtensions>\r
-</Project>
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5.csproj.user b/mcs/class/Mono.C5/C5.csproj.user
deleted file mode 100644 (file)
index 57bad3e..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <PropertyGroup>\r
-    <LastOpenVersion>8.0.40607</LastOpenVersion>\r
-    <ReferencePath>\r
-    </ReferencePath>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">\r
-    <DebugSecurityZoneURL>\r
-    </DebugSecurityZoneURL>\r
-    <DebugSecurityZone>NoZone</DebugSecurityZone>\r
-    <EnableASPDebugging>false</EnableASPDebugging>\r
-    <EnableASPXDebugging>false</EnableASPXDebugging>\r
-    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
-    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>\r
-    <RemoteDebugEnabled>false</RemoteDebugEnabled>\r
-    <RemoteDebugMachine>\r
-    </RemoteDebugMachine>\r
-    <StartAction>Project</StartAction>\r
-    <StartArguments>\r
-    </StartArguments>\r
-    <StartPage>\r
-    </StartPage>\r
-    <StartProgram>\r
-    </StartProgram>\r
-    <StartURL>\r
-    </StartURL>\r
-    <StartWorkingDirectory>\r
-    </StartWorkingDirectory>\r
-    <StartWithIE>false</StartWithIE>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">\r
-    <DebugSecurityZoneURL>\r
-    </DebugSecurityZoneURL>\r
-    <DebugSecurityZone>NoZone</DebugSecurityZone>\r
-    <EnableASPDebugging>false</EnableASPDebugging>\r
-    <EnableASPXDebugging>false</EnableASPXDebugging>\r
-    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
-    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>\r
-    <RemoteDebugEnabled>false</RemoteDebugEnabled>\r
-    <RemoteDebugMachine>\r
-    </RemoteDebugMachine>\r
-    <StartAction>Project</StartAction>\r
-    <StartArguments>\r
-    </StartArguments>\r
-    <StartPage>\r
-    </StartPage>\r
-    <StartProgram>\r
-    </StartProgram>\r
-    <StartURL>\r
-    </StartURL>\r
-    <StartWorkingDirectory>\r
-    </StartWorkingDirectory>\r
-    <StartWithIE>false</StartWithIE>\r
-  </PropertyGroup>\r
-  <PropertyGroup>\r
-    <ProjectView>ProjectFiles</ProjectView>\r
-    <ProjectTrust>0</ProjectTrust>\r
-  </PropertyGroup>\r
-</Project>
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/AssemblyInfo.cs b/mcs/class/Mono.C5/C5/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..b4de16b
--- /dev/null
@@ -0,0 +1,78 @@
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System.Reflection;\r
+using System.Runtime.CompilerServices;\r
+\r
+//\r
+// General Information about an assembly is controlled through the following \r
+// set of attributes. Change these attribute values to modify the information\r
+// associated with an assembly.\r
+//\r
+[assembly: AssemblyTitle("C5: Copenhagen Comprehensive Collection Classes for CLI")]\r
+[assembly: AssemblyDescription("This is a debug build of prerelease 0.5")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("")]\r
+[assembly: AssemblyCopyright("(c) 2003-2004 Niels Kokholm <kokholm@itu.dk>, Peter Sestoft <sestoft@dina.kvl.dk>")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+//\r
+// Version information for an assembly consists of the following four values:\r
+//\r
+//      Major Version\r
+//      Minor Version \r
+//      Build Number\r
+//      Revision\r
+//\r
+// You can specify all the values or you can default the Revision and Build Numbers \r
+// by using the '*' as shown below:\r
+\r
+[assembly: AssemblyVersion("0.5.1.1")]\r
+\r
+//\r
+// In order to sign your assembly you must specify a key to use. Refer to the \r
+// Microsoft .NET Framework documentation for more information on assembly signing.\r
+//\r
+// Use the attributes below to control which key is used for signing. \r
+//\r
+// Notes: \r
+//   (*) If no key is specified, the assembly is not signed.\r
+//   (*) KeyName refers to a key that has been installed in the Crypto Service\r
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains\r
+//       a key.\r
+//   (*) If the KeyFile and the KeyName values are both specified, the \r
+//       following processing occurs:\r
+//       (1) If the KeyName can be found in the CSP, that key is used.\r
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key \r
+//           in the KeyFile is installed into the CSP and used.\r
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.\r
+//       When specifying the KeyFile, the location of the KeyFile should be\r
+//       relative to the project output directory which is\r
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is\r
+//       located in the project directory, you would specify the AssemblyKeyFile \r
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]\r
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework\r
+//       documentation for more information on this.\r
+//\r
+[assembly: AssemblyDelaySign (true)]\r
+[assembly: AssemblyKeyFile ("c5.pub")]\r
diff --git a/mcs/class/Mono.C5/C5/Builder.cs b/mcs/class/Mono.C5/C5/Builder.cs
new file mode 100644 (file)
index 0000000..feb2981
--- /dev/null
@@ -0,0 +1,346 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using C5;\r
+using System;\r
+using System.Reflection;\r
+using System.Reflection.Emit;\r
+using System.Diagnostics;\r
+namespace C5.ComparerBuilder\r
+{\r
+    /// <summary>\r
+    /// A default item comparer for an item type that is either generic (IComparable&lt;T&gt;)\r
+    /// or ordinarily (System.IComparable) comparable.\r
+    /// </summary>\r
+    public class FromComparable<T>\r
+    {\r
+        static Type naturalComparerO = typeof(NaturalComparerO<>);\r
+\r
+        static Type naturalComparer = typeof(NaturalComparer<>);\r
+\r
+\r
+        /// <summary>\r
+        /// Create a default comparer\r
+        /// <exception cref="ArgumentException"/> if T is not comparable. \r
+        /// </summary>\r
+        /// <returns>The comparer</returns>\r
+        [Tested]\r
+        public static IComparer<T> Examine()\r
+        {\r
+            Type t = typeof(T);\r
+\r
+            if (t.Equals(typeof(int)))\r
+                return (IComparer<T>)(new IC());\r
+\r
+            if (typeof(IComparable<T>).IsAssignableFrom(t))\r
+            {\r
+                Type c = naturalComparer.MakeGenericType (t);\r
+\r
+                return (IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
+            }\r
+\r
+            if (t.GetInterface("System.IComparable") != null)\r
+            {\r
+                Type c = naturalComparerO.MakeGenericType (t);\r
+\r
+                return (IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
+            }\r
+\r
+            throw new ArgumentException(String.Format("Cannot make IComparer<{0}>", t));\r
+        }\r
+    }\r
+}\r
+namespace C5.HasherBuilder\r
+{\r
+    /// <summary>\r
+    /// Prototype for an sequenced hasher for IIndexed[W]\r
+    /// This will use the IIndexed[W] specific operations\r
+    /// </summary>\r
+    public class SequencedHasher<S, W> : IHasher<S>\r
+        where S : ISequenced<W>\r
+    {\r
+        /// <summary>\r
+        /// Get the hash code with respect to this sequenced hasher\r
+        /// </summary>\r
+        /// <param name="item">The item</param>\r
+        /// <returns>The hash code</returns>\r
+        [Tested]\r
+        public int GetHashCode(S item) { return item.GetHashCode(); }\r
+\r
+\r
+        /// <summary>\r
+        /// Check if two items are equal with respect to this sequenced hasher\r
+        /// </summary>\r
+        /// <param name="i1">first item</param>\r
+        /// <param name="i2">second item</param>\r
+        /// <returns>True if equal</returns>\r
+        [Tested]\r
+        public bool Equals(S i1, S i2) { return i1 == null ? i2 == null : i1.Equals(i2); }\r
+    }\r
+\r
+\r
+\r
+    /// <summary>\r
+    /// Prototype for an unsequenced hasher for ICollection[W]\r
+    /// This will use the ICollection[W] specific operations\r
+    /// </summary>\r
+    public class UnsequencedHasher<S, W> : IHasher<S>\r
+        where S : ICollection<W>\r
+    {\r
+        /// <summary>\r
+        /// Get the hash code with respect to this unsequenced hasher\r
+        /// </summary>\r
+        /// <param name="item">The item</param>\r
+        /// <returns>The hash code</returns>\r
+        [Tested]\r
+        public int GetHashCode(S item) { return item.GetHashCode(); }\r
+\r
+\r
+        /// <summary>\r
+        /// Check if two items are equal with respect to this unsequenced hasher\r
+        /// </summary>\r
+        /// <param name="i1">first item</param>\r
+        /// <param name="i2">second item</param>\r
+        /// <returns>True if equal</returns>\r
+        [Tested]\r
+        public bool Equals(S i1, S i2) { return i1 == null ? i2 == null : i1.Equals(i2); }\r
+    }\r
+\r
+\r
+\r
+    /// <summary>\r
+    /// Create a hasher for T that is DefaultValueTypeHasher[T] \r
+    /// or DefaultReferenceTypeHasher[T] unless T has been \r
+    /// instatiated to a type of the exact form IIndexed[W] or ICollection[W]\r
+    /// in which case Examine will return Sequenced- repectively UnsequencedHasher.\r
+    /// </summary>\r
+    public class ByPrototype<T>\r
+    {\r
+        static Type isequenced = typeof(ISequenced<>);\r
+\r
+        static Type ieditable = typeof(ICollection<>);\r
+\r
+        static Type orderedhasher = typeof(HasherBuilder.SequencedHasher<,>);\r
+\r
+        static Type unorderedhasher = typeof(HasherBuilder.UnsequencedHasher<,>);\r
+/*\r
+        static Type isequenced = Type.GetType("C5.ISequenced");\r
+\r
+        static Type ieditable = Type.GetType("C5.ICollection");\r
+\r
+        static Type orderedhasher = Type.GetType("C5.HasherBuilder.SequencedHasher");\r
+\r
+        static Type unorderedhasher = Type.GetType("C5.HasherBuilder.UnsequencedHasher");\r
+*/\r
+\r
+        /// <summary>\r
+        /// See class description\r
+        /// </summary>\r
+        /// <returns>The hasher</returns>\r
+        [Tested]\r
+        public static IHasher<T> Examine()\r
+        {\r
+            Type t = typeof(T);\r
+\r
+            if (!t.IsGenericType)\r
+            {\r
+                if (t.Equals(typeof(int)))\r
+                    return (IHasher<T>)(new IntHasher());\r
+                else if (t.IsValueType)\r
+                    return new DefaultValueTypeHasher<T>();\r
+                else\r
+                    return new DefaultReferenceTypeHasher<T>();\r
+            }\r
+\r
+            Type s = t.GetGenericTypeDefinition();\r
+            Type[] v = t.GetGenericArguments();\r
+            Type b;\r
+\r
+            if (s.Equals(isequenced))\r
+                b = orderedhasher;\r
+            else if (s.Equals(ieditable))\r
+                b = unorderedhasher;\r
+            else if (t.IsValueType)\r
+                return new DefaultValueTypeHasher<T>();\r
+            else\r
+                return new DefaultReferenceTypeHasher<T>();\r
+\r
+            Type c = b.MakeGenericType ( t, v[0] );\r
+\r
+            return (IHasher<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
+        }\r
+    }\r
+\r
+\r
+#if !EXPERIMENTAL\r
+\r
+    /// <summary>\r
+    /// IHasher factory class: examines at instatiation time if T is an\r
+    /// interface implementing "int GetHashCode()" and "bool Equals(T)".\r
+    /// If those are not present, MakeHasher will return a default hasher,\r
+    /// else this class will implement Ihasher[T] via Invoke() on the\r
+    /// reflected method infos.\r
+    /// </summary>\r
+    public class ByInvoke<T> : IHasher<T>\r
+    {\r
+        internal static readonly System.Reflection.MethodInfo hinfo, einfo;\r
+\r
+\r
+        static ByInvoke()\r
+        {\r
+            Type t = typeof(T);\r
+\r
+            if (!t.IsInterface) return;\r
+\r
+            BindingFlags f = BindingFlags.Public | BindingFlags.Instance;\r
+\r
+            hinfo = t.GetMethod("GetHashCode", f, null, new Type[0], null);\r
+            einfo = t.GetMethod("Equals", f, null, new Type[1] { t }, null);\r
+        }\r
+\r
+\r
+        private ByInvoke() { }\r
+\r
+/// <summary>\r
+/// \r
+/// </summary>\r
+/// <returns></returns>\r
+        public static IHasher<T> MakeHasher()\r
+        {\r
+            if (hinfo != null && einfo != null)\r
+                return new ByInvoke<T>();\r
+            else\r
+                return new DefaultReferenceTypeHasher<T>();\r
+        }\r
+\r
+/// <summary>\r
+/// \r
+/// </summary>\r
+/// <param name="item"></param>\r
+/// <returns></returns>\r
+        public int GetHashCode(T item)\r
+        {\r
+            return (int)(hinfo.Invoke(item, null));\r
+        }\r
+\r
+/// <summary>\r
+/// \r
+/// </summary>\r
+/// <param name="i1"></param>\r
+/// <param name="i2"></param>\r
+/// <returns></returns>\r
+        public bool Equals(T i1, T i2)\r
+        {\r
+            return (bool)(einfo.Invoke(i1, new object[1] { i2 }));\r
+        }\r
+    }\r
+\r
+\r
+\r
+    /// <summary>\r
+    /// Like ByInvoke, but tries to build a hasher by RTCG to\r
+    /// avoid the Invoke() overhead. Does not work as intended \r
+    /// because of a Whidbey RTCG bug.\r
+    /// </summary>\r
+    public class ByRTCG\r
+    {\r
+        private static ModuleBuilder moduleBuilder;\r
+\r
+        private static AssemblyBuilder assemblyBuilder;\r
+\r
+        private static int uid = 0;\r
+\r
+\r
+        /// <summary>\r
+        /// \r
+        /// </summary>\r
+        /// <param name="hinfo"></param>\r
+        /// <param name="einfo"></param>\r
+        /// <returns></returns>\r
+        public static /*ObjectHasher */ IHasher<T> CreateHasher<T>(MethodInfo hinfo, MethodInfo einfo)\r
+        {\r
+            if (moduleBuilder == null)\r
+            {\r
+                string assmname = "LeFake";\r
+                string filename = assmname + ".dll";\r
+                AssemblyName assemblyName = new AssemblyName("LeFake");\r
+                AppDomain appdomain = AppDomain.CurrentDomain;\r
+                AssemblyBuilderAccess acc = AssemblyBuilderAccess.RunAndSave;\r
+\r
+                assemblyBuilder = appdomain.DefineDynamicAssembly(assemblyName, acc);\r
+                moduleBuilder = assemblyBuilder.DefineDynamicModule(assmname, filename);\r
+            }\r
+\r
+            Type t = typeof(/*object*/ T);\r
+            Type o_t = typeof(object);\r
+            Type h_t = typeof(/*ObjectHasher*/ IHasher<T>);\r
+            Type i_t = typeof(int);\r
+            //TODO: protect uid for thread safety!\r
+            string name = "C5.Dynamic.Hasher_" + uid++;\r
+            TypeAttributes tatt = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;\r
+            TypeBuilder tb = moduleBuilder.DefineType(name, tatt, o_t, new Type[1] { h_t });\r
+            MethodAttributes matt = MethodAttributes.Public | MethodAttributes.Virtual;\r
+            MethodBuilder mb = tb.DefineMethod("GetHashCode", matt, i_t, new Type[1] { t });\r
+            ILGenerator ilg = mb.GetILGenerator();\r
+\r
+            ilg.Emit(OpCodes.Ldarg_1);\r
+            ilg.Emit(OpCodes.Callvirt, hinfo);\r
+            ilg.Emit(OpCodes.Ret);\r
+            mb = tb.DefineMethod("Equals", matt, typeof(bool), new Type[2] { t, t });\r
+            ilg = mb.GetILGenerator();\r
+            ilg.Emit(OpCodes.Ldarg_1);\r
+            ilg.Emit(OpCodes.Ldarg_2);\r
+            ilg.Emit(OpCodes.Callvirt, einfo);\r
+            ilg.Emit(OpCodes.Ret);\r
+\r
+            Type hasher_t = tb.CreateType();\r
+            object hasher = hasher_t.GetConstructor(new Type[0]).Invoke(null);\r
+\r
+            return (IHasher<T>)hasher;\r
+        }\r
+\r
+/// <summary>\r
+/// \r
+/// </summary>\r
+/// <typeparam name="T"></typeparam>\r
+/// <returns></returns>\r
+        public static IHasher<T> build<T>()\r
+        {\r
+            MethodInfo hinfo = ByInvoke<T>.hinfo, einfo = ByInvoke<T>.einfo;\r
+\r
+            if (hinfo != null && einfo != null)\r
+                return CreateHasher<T>(hinfo, einfo);\r
+            else\r
+                return ByPrototype<T>.Examine();\r
+        }\r
+\r
+/// <summary>\r
+/// \r
+/// </summary>\r
+        public void dump()\r
+        {\r
+            assemblyBuilder.Save("LeFake.dll");\r
+        }\r
+    }\r
+#endif\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/C5.csproj b/mcs/class/Mono.C5/C5/C5.csproj
new file mode 100644 (file)
index 0000000..2142ae8
--- /dev/null
@@ -0,0 +1,124 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+    <ProductVersion>8.0.40607</ProductVersion>\r
+    <SchemaVersion>2.0</SchemaVersion>\r
+    <ProjectGuid>{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}</ProjectGuid>\r
+    <OutputType>Library</OutputType>\r
+    <StartupObject>\r
+    </StartupObject>\r
+    <RootNamespace>C5</RootNamespace>\r
+    <NoStandardLibraries>false</NoStandardLibraries>\r
+    <AssemblyName>C5</AssemblyName>\r
+    <FileUpgradeFlags>\r
+    </FileUpgradeFlags>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">\r
+    <DebugSymbols>true</DebugSymbols>\r
+    <Optimize>false</Optimize>\r
+    <OutputPath>.\bin\Debug\</OutputPath>\r
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
+    <DefineConstants>DEBUG;TRACE</DefineConstants>\r
+    <WarningLevel>4</WarningLevel>\r
+    <IncrementalBuild>false</IncrementalBuild>\r
+    <DocumentationFile>c5.xml</DocumentationFile>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">\r
+    <DebugSymbols>false</DebugSymbols>\r
+    <Optimize>true</Optimize>\r
+    <OutputPath>.\bin\Release\</OutputPath>\r
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
+    <DefineConstants>TRACE</DefineConstants>\r
+    <WarningLevel>4</WarningLevel>\r
+    <IncrementalBuild>false</IncrementalBuild>\r
+    <DocumentationFile>\r
+    </DocumentationFile>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Reference Include="System">\r
+      <HintPath>..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.2.30703\System.dll</HintPath>\r
+      <Name>System</Name>\r
+    </Reference>\r
+    <Reference Include="System.Data">\r
+      <HintPath>..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.2.30703\System.Data.dll</HintPath>\r
+      <Name>System.Data</Name>\r
+    </Reference>\r
+    <Reference Include="System.Xml">\r
+      <HintPath>..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.2.30703\System.XML.dll</HintPath>\r
+      <Name>System.XML</Name>\r
+    </Reference>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="AssemblyInfo.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Builder.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Collections.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Dictionaries.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Interfaces.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Wrappers.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="arrays\ArrayList.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="arrays\HashedArray.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="arrays\SortedArray.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="hashing\HashBag.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="hashing\HashDictionary.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="hashing\HashTable.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="heaps\IntervalHeap.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="linkedlists\HashedLinkedList.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="linkedlists\LinkedList.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="trees\RedBlackTree.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="trees\RedBlackTreeBag.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="trees\TreeDictionary.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <AppDesigner Include="Project\" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Folder Include="Project\" />\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />\r
+  <PropertyGroup>\r
+    <PreBuildEvent>\r
+    </PreBuildEvent>\r
+    <PostBuildEvent>\r
+    </PostBuildEvent>\r
+  </PropertyGroup>\r
+  <ProjectExtensions>\r
+    <VisualStudio>\r
+    </VisualStudio>\r
+  </ProjectExtensions>\r
+</Project>
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/C5.csproj.user b/mcs/class/Mono.C5/C5/C5.csproj.user
new file mode 100644 (file)
index 0000000..57bad3e
--- /dev/null
@@ -0,0 +1,59 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <LastOpenVersion>8.0.40607</LastOpenVersion>\r
+    <ReferencePath>\r
+    </ReferencePath>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">\r
+    <DebugSecurityZoneURL>\r
+    </DebugSecurityZoneURL>\r
+    <DebugSecurityZone>NoZone</DebugSecurityZone>\r
+    <EnableASPDebugging>false</EnableASPDebugging>\r
+    <EnableASPXDebugging>false</EnableASPXDebugging>\r
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
+    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>\r
+    <RemoteDebugEnabled>false</RemoteDebugEnabled>\r
+    <RemoteDebugMachine>\r
+    </RemoteDebugMachine>\r
+    <StartAction>Project</StartAction>\r
+    <StartArguments>\r
+    </StartArguments>\r
+    <StartPage>\r
+    </StartPage>\r
+    <StartProgram>\r
+    </StartProgram>\r
+    <StartURL>\r
+    </StartURL>\r
+    <StartWorkingDirectory>\r
+    </StartWorkingDirectory>\r
+    <StartWithIE>false</StartWithIE>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">\r
+    <DebugSecurityZoneURL>\r
+    </DebugSecurityZoneURL>\r
+    <DebugSecurityZone>NoZone</DebugSecurityZone>\r
+    <EnableASPDebugging>false</EnableASPDebugging>\r
+    <EnableASPXDebugging>false</EnableASPXDebugging>\r
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>\r
+    <EnableSQLServerDebugging>false</EnableSQLServerDebugging>\r
+    <RemoteDebugEnabled>false</RemoteDebugEnabled>\r
+    <RemoteDebugMachine>\r
+    </RemoteDebugMachine>\r
+    <StartAction>Project</StartAction>\r
+    <StartArguments>\r
+    </StartArguments>\r
+    <StartPage>\r
+    </StartPage>\r
+    <StartProgram>\r
+    </StartProgram>\r
+    <StartURL>\r
+    </StartURL>\r
+    <StartWorkingDirectory>\r
+    </StartWorkingDirectory>\r
+    <StartWithIE>false</StartWithIE>\r
+  </PropertyGroup>\r
+  <PropertyGroup>\r
+    <ProjectView>ProjectFiles</ProjectView>\r
+    <ProjectTrust>0</ProjectTrust>\r
+  </PropertyGroup>\r
+</Project>
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Collections.cs b/mcs/class/Mono.C5/C5/Collections.cs
new file mode 100644 (file)
index 0000000..d85f621
--- /dev/null
@@ -0,0 +1,1351 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// Direction of enumeration order relative to original collection.\r
+       /// </summary>\r
+       public enum EnumerationDirection { \r
+               /// <summary>\r
+               /// Same direction\r
+               /// </summary>\r
+               Forwards, \r
+               /// <summary>\r
+               /// Opposite direction\r
+               /// </summary>\r
+               Backwards \r
+       }\r
+\r
+       #region int stuff\r
+       class IC: IComparer<int>\r
+       {\r
+               [Tested]\r
+               public int Compare(int a, int b) { return a > b ? 1 : a < b ? -1 : 0; }\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A hasher for int32\r
+       /// </summary>\r
+       public class IntHasher: IHasher<int>\r
+       {\r
+               /// <summary>\r
+               /// Get the hash code of this integer, i.e. itself\r
+               /// </summary>\r
+               /// <param name="item">The integer</param>\r
+               /// <returns>The same</returns>\r
+               [Tested]\r
+               public int GetHashCode(int item) { return item; }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if two integers are equal\r
+               /// </summary>\r
+               /// <param name="i1">first integer</param>\r
+               /// <param name="i2">second integer</param>\r
+               /// <returns>True if equal</returns>\r
+               [Tested]\r
+               public bool Equals(int i1, int i2) { return i1 == i2; }\r
+       }\r
+\r
+\r
+       #endregion\r
+\r
+       #region Natural Comparers\r
+\r
+\r
+       /// <summary>\r
+       /// A natural generic IComparer for an IComparable&lt;T&gt; item type\r
+       /// </summary>\r
+       public class NaturalComparer<T>: IComparer<T>\r
+               where T: IComparable<T>\r
+       {\r
+               /// <summary>\r
+               /// Compare two items\r
+               /// </summary>\r
+               /// <param name="a">First item</param>\r
+               /// <param name="b">Second item</param>\r
+               /// <returns>a &lt;=&gt; b</returns>\r
+               [Tested]\r
+               public int Compare(T a, T b) { return a.CompareTo(b); }\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A natural generic IComparer for a System.IComparable item type\r
+       /// </summary>\r
+       public class NaturalComparerO<T>: IComparer<T>\r
+               where T: System.IComparable\r
+       {\r
+               /// <summary>\r
+               /// Compare two items\r
+               /// </summary>\r
+               /// <param name="a">First item</param>\r
+               /// <param name="b">Second item</param>\r
+               /// <returns>a &lt;=&gt; b</returns>\r
+               [Tested]\r
+               public int Compare(T a, T b) { return a.CompareTo(b); }\r
+       }\r
+\r
+\r
+\r
+       #endregion\r
+\r
+       #region Hashers\r
+       /// <summary>\r
+       /// The default item hasher for a reference type. A trivial wrapper for calling \r
+       /// the GetHashCode and Equals methods inherited from object.\r
+       ///\r
+       /// <p>Should only be instantiated with a reference type as generic type parameter. \r
+       /// This is asserted at instatiation time in Debug builds.</p>\r
+       /// </summary>\r
+       public sealed class DefaultReferenceTypeHasher<T>: IHasher<T>\r
+       {\r
+               static DefaultReferenceTypeHasher()\r
+               {\r
+                       Debug.Assert(!typeof(T).IsValueType, "DefaultReferenceTypeHasher instantiated with value type: " + typeof(T));\r
+               }\r
+               \r
+               /// <summary>\r
+               /// Get the hash code with respect to this item hasher\r
+               /// </summary>\r
+               /// <param name="item">The item</param>\r
+               /// <returns>The hash code</returns>\r
+               [Tested]\r
+               public int GetHashCode(T item) { return item.GetHashCode(); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if two items are equal with respect to this item hasher\r
+               /// </summary>\r
+               /// <param name="i1">first item</param>\r
+               /// <param name="i2">second item</param>\r
+               /// <returns>True if equal</returns>\r
+               [Tested]\r
+               public bool Equals(T i1, T i2)\r
+               {\r
+                       //For reference types, the (object) cast should be jitted as a noop. \r
+                       return (object)i1 == null ? (object)i2 == null : i1.Equals(i2);\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       /// The default item hasher for a value type. A trivial wrapper for calling \r
+       /// the GetHashCode and Equals methods inherited from object.\r
+       ///\r
+       /// <p>Should only be instantiated with a value type as generic type parameter. \r
+       /// This is asserted at instatiation time in Debug builds.</p>\r
+       /// <p>We cannot add the constraint "where T : struct" to get a compile time check\r
+       /// because we need to instantiate this class in C5.HasherBuilder.ByPrototype[T].Examine()\r
+       /// with a T that is only known at runtime to be a value type!</p>\r
+       /// </summary>\r
+       \r
+    //Note: we could (now) add a constraint "where T : struct" to get a compile time check,\r
+    //but \r
+       public sealed class DefaultValueTypeHasher<T>: IHasher<T>\r
+       {\r
+               static DefaultValueTypeHasher()\r
+               {\r
+                       Debug.Assert(typeof(T).IsValueType, "DefaultValueTypeHasher instantiated with reference type: " + typeof(T));\r
+               }\r
+               /// <summary>\r
+               /// Get the hash code with respect to this item hasher\r
+               /// </summary>\r
+               /// <param name="item">The item</param>\r
+               /// <returns>The hash code</returns>\r
+               [Tested]\r
+               public int GetHashCode(T item) { return item.GetHashCode(); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if two items are equal with respect to this item hasher\r
+               /// </summary>\r
+               /// <param name="i1">first item</param>\r
+               /// <param name="i2">second item</param>\r
+               /// <returns>True if equal</returns>\r
+               [Tested]\r
+               public bool Equals(T i1, T i2) { return i1.Equals(i2); }\r
+       }\r
+\r
+       #endregion\r
+\r
+       #region Bases\r
+\r
+       /// <summary>\r
+       /// A base class for implementing an IEnumerable&lt;T&gt;\r
+       /// </summary>\r
+       public abstract class EnumerableBase<T>: MSG.IEnumerable<T>\r
+       {\r
+               /// <summary>\r
+               /// Create an enumerator for this collection.\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               public abstract MSG.IEnumerator<T> GetEnumerator();\r
+\r
+               System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()\r
+               {\r
+                       return GetEnumerator ();\r
+               }\r
+\r
+               /// <summary>\r
+               /// Count the number of items in an enumerable by enumeration\r
+               /// </summary>\r
+               /// <param name="items">The enumerable to count</param>\r
+               /// <returns>The size of the enumerable</returns>\r
+               protected static int countItems(MSG.IEnumerable<T> items)\r
+               {\r
+                       ICollectionValue<T> jtems = items as ICollectionValue<T>;\r
+\r
+                       if (jtems != null)\r
+                               return jtems.Count;\r
+\r
+                       int count = 0;\r
+\r
+                       using (MSG.IEnumerator<T> e = items.GetEnumerator())\r
+                               while (e.MoveNext()) count++;\r
+\r
+                       return count;\r
+               }\r
+       }\r
+\r
+\r
+       /// <summary>\r
+       /// Base class for classes implementing ICollectionValue[T]\r
+       /// </summary>\r
+       public abstract class CollectionValueBase<T>: EnumerableBase<T>, ICollectionValue<T>\r
+       {\r
+               //This forces our subclasses to make Count virtual!\r
+               /// <summary>\r
+               /// The number of items in this collection.\r
+               /// </summary>\r
+               /// <value></value>\r
+               public abstract int Count { get;}\r
+\r
+        /// <summary>\r
+        /// The value is symbolic indicating the type of asymptotic complexity\r
+        /// in terms of the size of this collection (worst-case or amortized as\r
+        /// relevant).\r
+        /// </summary>\r
+        /// <value>A characterization of the speed of the \r
+        /// <code>Count</code> property in this collection.</value>\r
+        public abstract Speed CountSpeed { get; }\r
+\r
+\r
+        /// <summary>\r
+               /// Copy the items of this collection to part of an array.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if i is negative.\r
+               /// <exception cref="ArgumentException"/> if the array does not have room for the items.\r
+               /// </summary>\r
+               /// <param name="a">The array to copy to</param>\r
+               /// <param name="i">The starting index.</param>\r
+               [Tested]\r
+               public virtual void CopyTo(T[] a, int i)\r
+               {\r
+                       if (i < 0)\r
+                               throw new ArgumentOutOfRangeException();\r
+\r
+                       if (i + Count > a.Length)\r
+                               throw new ArgumentException();\r
+\r
+                       foreach (T item in this) a[i++] = item;\r
+               }\r
+\r
+        /// <summary>\r
+        /// Create an array with the items of this collection (in the same order as an\r
+        /// enumerator would output them).\r
+        /// </summary>\r
+        /// <returns>The array</returns>\r
+        //[Tested]\r
+        public virtual T[] ToArray()\r
+        {\r
+            T[] res = new T[Count];\r
+            int i = 0;\r
+\r
+            foreach (T item in this) res[i++] = item;\r
+\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Apply an Applier&lt;T&gt; to this enumerable\r
+        /// </summary>\r
+        /// <param name="a">The applier delegate</param>\r
+        [Tested]\r
+        public void Apply(Applier<T> a)\r
+        {\r
+            foreach (T item in this)\r
+                a(item);\r
+        }\r
+\r
+\r
+        /// <summary>\r
+        /// Check if there exists an item  that satisfies a\r
+        /// specific predicate in this collection.\r
+        /// </summary>\r
+        /// <param name="filter">A filter delegate \r
+        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
+        /// <returns>True is such an item exists</returns>\r
+        [Tested]\r
+        public bool Exists(Filter<T> filter)\r
+        {\r
+            foreach (T item in this)\r
+                if (filter(item))\r
+                    return true;\r
+\r
+            return false;\r
+        }\r
+\r
+\r
+        /// <summary>\r
+        /// Check if all items in this collection satisfies a specific predicate.\r
+        /// </summary>\r
+        /// <param name="filter">A filter delegate \r
+        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
+        /// <returns>True if all items satisfies the predicate</returns>\r
+        [Tested]\r
+        public bool All(Filter<T> filter)\r
+        {\r
+            foreach (T item in this)\r
+                if (!filter(item))\r
+                    return false;\r
+\r
+            return true;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Create an enumerator for this collection.\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               public override abstract MSG.IEnumerator<T> GetEnumerator();\r
+       }\r
+\r
+\r
+       /// <summary>\r
+       /// Base class (abstract) for ICollection implementations.\r
+       /// </summary>\r
+       public abstract class CollectionBase<T>: CollectionValueBase<T>\r
+       {\r
+               #region Fields\r
+\r
+               object syncroot = new object();\r
+\r
+               /// <summary>\r
+               /// The underlying field of the ReadOnly property\r
+               /// </summary>\r
+               protected bool isReadOnly = false;\r
+\r
+               /// <summary>\r
+               /// The current stamp value\r
+               /// </summary>\r
+               protected int stamp;\r
+\r
+               /// <summary>\r
+               /// The number of items in the collection\r
+               /// </summary>\r
+               protected int size;\r
+\r
+               /// <summary>\r
+               /// The item hasher of the collection\r
+               /// </summary>\r
+               protected IHasher<T> itemhasher;\r
+\r
+               int iUnSequencedHashCode, iUnSequencedHashCodeStamp = -1;\r
+\r
+               #endregion\r
+               \r
+               #region Util\r
+\r
+               //protected bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }\r
+               /// <summary>\r
+               /// Utility method for range checking.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the start or count is negative\r
+               /// <exception cref="ArgumentException"/> if the range does not fit within collection size.\r
+               /// </summary>\r
+               /// <param name="start">start of range</param>\r
+               /// <param name="count">size of range</param>\r
+               [Tested]\r
+               protected void checkRange(int start, int count)\r
+               {\r
+                       if (start < 0 || count < 0)\r
+                               throw new ArgumentOutOfRangeException();\r
+\r
+                       if (start + count > size)\r
+                               throw new ArgumentException();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Compute the unsequenced hash code of a collection\r
+               /// </summary>\r
+               /// <param name="items">The collection to compute hash code for</param>\r
+               /// <param name="itemhasher">The item hasher</param>\r
+               /// <returns>The hash code</returns>\r
+               [Tested]\r
+               public static int ComputeHashCode(ICollectionValue<T> items, IHasher<T> itemhasher)\r
+               {\r
+                       int h = 0;\r
+\r
+                       foreach (T item in items)\r
+                               h ^= itemhasher.GetHashCode(item);\r
+\r
+                       return (items.Count << 16) + h;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Examine if tit and tat are equal as unsequenced collections\r
+               /// using the specified item hasher (assumed compatible with the two collections).\r
+               /// </summary>\r
+               /// <param name="tit">The first collection</param>\r
+               /// <param name="tat">The second collection</param>\r
+               /// <param name="itemhasher">The item hasher to use for comparison</param>\r
+               /// <returns>True if equal</returns>\r
+               [Tested]\r
+               public static bool StaticEquals(ICollection<T> tit, ICollection<T> tat, IHasher<T> itemhasher)\r
+               {\r
+                       if (tat == null)\r
+                               return tit == null;\r
+\r
+                       if (tit.Count != tat.Count)\r
+                               return false;\r
+\r
+                       //This way we might run through both enumerations twice, but\r
+                       //probably not (if the hash codes are good)\r
+                       if (tit.GetHashCode() != tat.GetHashCode())\r
+                               return false;\r
+\r
+            if (!tit.AllowsDuplicates && (tat.AllowsDuplicates || tat.ContainsSpeed >= tit.ContainsSpeed))\r
+            {\r
+                //TODO: use foreach construction\r
+                               using (MSG.IEnumerator<T> dit = tit.GetEnumerator())\r
+                               {\r
+                                       while (dit.MoveNext())\r
+                                               if (!tat.Contains(dit.Current))\r
+                                                       return false;\r
+                               }\r
+                       }\r
+            else if (!tat.AllowsDuplicates)\r
+            {\r
+                               using (MSG.IEnumerator<T> dat = tat.GetEnumerator())\r
+                               {\r
+                                       while (dat.MoveNext())\r
+                                               if (!tit.Contains(dat.Current))\r
+                                                       return false;\r
+                               }\r
+                       }\r
+                       else\r
+                       {//both are bags, we only have a slow one\r
+                               //unless the bags are based on a fast T->int dictinary (tree or hash) \r
+                               using (MSG.IEnumerator<T> dat = tat.GetEnumerator())\r
+                               {\r
+                                       while (dat.MoveNext())\r
+                                       {\r
+                                               T item = dat.Current;\r
+\r
+                                               if (tit.ContainsCount(item) != tat.ContainsCount(item))\r
+                                                       return false;\r
+                                       }\r
+                               }\r
+                               //That was O(n^3) - completely unacceptable.\r
+                               //If we use an auxiliary bool[] we can do the comparison in O(n^2)\r
+                       }\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get the unsequenced collection hash code of this collection: from the cached \r
+               /// value if present and up to date, else (re)compute.\r
+               /// </summary>\r
+               /// <returns>The hash code</returns>\r
+               protected int unsequencedhashcode()\r
+               {\r
+                       if (iUnSequencedHashCodeStamp == stamp)\r
+                               return iUnSequencedHashCode;\r
+\r
+                       iUnSequencedHashCode = ComputeHashCode(this, itemhasher);\r
+                       iUnSequencedHashCodeStamp = stamp;\r
+                       return iUnSequencedHashCode;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if the contents of that is equal to the contents of this\r
+               /// in the unsequenced sense. Using the item hasher of this collection.\r
+               /// </summary>\r
+               /// <param name="that">The collection to compare to.</param>\r
+               /// <returns>True if  equal</returns>\r
+               protected bool unsequencedequals(ICollection<T> that)\r
+               {\r
+                       return StaticEquals((ICollection<T>)this, that, itemhasher);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="InvalidOperationException"/> if this collection has been updated \r
+               /// since a target time\r
+               /// </summary>\r
+               /// <param name="thestamp">The stamp identifying the target time</param>\r
+               protected virtual void modifycheck(int thestamp)\r
+               {\r
+                       if (this.stamp != thestamp)\r
+                               throw new InvalidOperationException("Collection was modified");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if it is valid to perform update operations, and if so increment stamp\r
+               /// </summary>\r
+               protected virtual void updatecheck()\r
+               {\r
+                       if (isReadOnly)\r
+                               throw new InvalidOperationException("Collection cannot be modified through this guard object");\r
+\r
+                       stamp++;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IEditableCollection<T> members\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True if this collection is read only</value>\r
+               [Tested]\r
+               public bool IsReadOnly { [Tested]get { return isReadOnly; } }\r
+\r
+               #endregion\r
+\r
+               #region ICollection<T> members\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>The size of this collection</value>\r
+               [Tested]\r
+               public override int Count { [Tested]get { return size; } }\r
+\r
+        /// <summary>\r
+        /// The value is symbolic indicating the type of asymptotic complexity\r
+        /// in terms of the size of this collection (worst-case or amortized as\r
+        /// relevant).\r
+        /// </summary>\r
+        /// <value>A characterization of the speed of the \r
+        /// <code>Count</code> property in this collection.</value>\r
+        public override Speed CountSpeed { get { return Speed.Constant; } }\r
+\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> members\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>A distinguished object to use for locking to synchronize multithreaded access</value>\r
+               [Tested]\r
+               public object SyncRoot { get { return syncroot; } }\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True is this collection is empty</value>\r
+               [Tested]\r
+               public bool IsEmpty { [Tested]get { return size == 0; } }\r
+               #endregion\r
+\r
+               #region IEnumerable<T> Members\r
+               /// <summary>\r
+               /// Create an enumerator for this collection.\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               public override abstract MSG.IEnumerator<T> GetEnumerator();\r
+               #endregion\r
+       }\r
+\r
+\r
+       /// <summary>\r
+       /// Base class (abstract) for sequenced collection implementations.\r
+       /// </summary>\r
+       public abstract class SequencedBase<T>: CollectionBase<T>\r
+       {\r
+               #region Fields\r
+\r
+               int iSequencedHashCode, iSequencedHashCodeStamp = -1;\r
+\r
+               #endregion\r
+\r
+               #region Util\r
+\r
+               /// <summary>\r
+               /// Compute the unsequenced hash code of a collection\r
+               /// </summary>\r
+               /// <param name="items">The collection to compute hash code for</param>\r
+               /// <param name="itemhasher">The item hasher</param>\r
+               /// <returns>The hash code</returns>\r
+               [Tested]\r
+               public static int ComputeHashCode(ISequenced<T> items, IHasher<T> itemhasher)\r
+               {\r
+                       //NOTE: It must be possible to devise a much stronger combined hashcode, \r
+                       //but unfortunately, it has to be universal. OR we could use a (strong)\r
+                       //family and initialise its parameter randomly at load time of this class!\r
+                       //(We would not want to have yet a flag to check for invalidation?!)\r
+                       int iIndexedHashCode = 0;\r
+\r
+                       foreach (T item in items)\r
+                               iIndexedHashCode = iIndexedHashCode * 31 + itemhasher.GetHashCode(item);\r
+\r
+                       return iIndexedHashCode;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Examine if tit and tat are equal as sequenced collections\r
+               /// using the specified item hasher (assumed compatible with the two collections).\r
+               /// </summary>\r
+               /// <param name="tit">The first collection</param>\r
+               /// <param name="tat">The second collection</param>\r
+               /// <param name="itemhasher">The item hasher to use for comparison</param>\r
+               /// <returns>True if equal</returns>\r
+               [Tested]\r
+               public static bool StaticEquals(ISequenced<T> tit, ISequenced<T> tat, IHasher<T> itemhasher)\r
+               {\r
+                       if (tat == null)\r
+                               return tit == null;\r
+\r
+                       if (tit.Count != tat.Count)\r
+                               return false;\r
+\r
+                       //This way we might run through both enumerations twice, but\r
+                       //probably not (if the hash codes are good)\r
+                       if (tit.GetHashCode() != tat.GetHashCode())\r
+                               return false;\r
+\r
+                       using (MSG.IEnumerator<T> dat = tat.GetEnumerator(), dit = tit.GetEnumerator())\r
+                       {\r
+                               while (dit.MoveNext())\r
+                               {\r
+                                       dat.MoveNext();\r
+                                       if (!itemhasher.Equals(dit.Current, dat.Current))\r
+                                               return false;\r
+                               }\r
+                       }\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get the sequenced collection hash code of this collection: from the cached \r
+               /// value if present and up to date, else (re)compute.\r
+               /// </summary>\r
+               /// <returns>The hash code</returns>\r
+               protected int sequencedhashcode()\r
+               {\r
+                       if (iSequencedHashCodeStamp == stamp)\r
+                               return iSequencedHashCode;\r
+\r
+                       iSequencedHashCode = ComputeHashCode((ISequenced<T>)this, itemhasher);\r
+                       iSequencedHashCodeStamp = stamp;\r
+                       return iSequencedHashCode;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if the contents of that is equal to the contents of this\r
+               /// in the sequenced sense. Using the item hasher of this collection.\r
+               /// </summary>\r
+               /// <param name="that">The collection to compare to.</param>\r
+               /// <returns>True if  equal</returns>\r
+               protected bool sequencedequals(ISequenced<T> that)\r
+               {\r
+                       return StaticEquals((ISequenced<T>)this, that, itemhasher);\r
+               }\r
+\r
+\r
+               #endregion\r
+\r
+               /// <summary>\r
+               /// Create an enumerator for this collection.\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               public override abstract MSG.IEnumerator<T> GetEnumerator();\r
+\r
+\r
+               /// <summary>\r
+               /// <code>Forwards</code> if same, else <code>Backwards</code>\r
+               /// </summary>\r
+               /// <value>The enumeration direction relative to the original collection.</value>\r
+               [Tested]\r
+               public EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }\r
+       }\r
+\r
+\r
+       /// <summary>\r
+       /// Base class for collection classes of dynamic array type implementations.\r
+       /// </summary>\r
+       public class ArrayBase<T>: SequencedBase<T>\r
+       {\r
+               #region Fields\r
+               /// <summary>\r
+               /// The actual internal array container. Will be extended on demand.\r
+               /// </summary>\r
+               protected T[] array;\r
+\r
+               /// <summary>\r
+               /// The offset into the internal array container of the first item. The offset is 0 for a \r
+               /// base dynamic array and may be positive for an updatable view into a base dynamic array.\r
+               /// </summary>\r
+               protected int offset;\r
+               #endregion\r
+\r
+               #region Util\r
+               /// <summary>\r
+               /// Double the size of the internal array.\r
+               /// </summary>\r
+               protected virtual void expand()\r
+               {\r
+                       expand(2 * array.Length, size);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Expand the internal array container.\r
+               /// </summary>\r
+               /// <param name="newcapacity">The new size of the internal array - \r
+               /// will be rounded upwards to a power of 2.</param>\r
+               /// <param name="newsize">The (new) size of the (base) collection.</param>\r
+               protected virtual void expand(int newcapacity, int newsize)\r
+               {\r
+                       Debug.Assert(newcapacity >= newsize);\r
+\r
+                       int newlength = array.Length;\r
+\r
+                       while (newlength < newcapacity) newlength *= 2;\r
+\r
+                       T[] newarray = new T[newlength];\r
+\r
+                       Array.Copy(array, newarray, newsize);\r
+                       array = newarray;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at a specific index, moving items to the right\r
+               /// upwards and expanding the array if necessary.\r
+               /// </summary>\r
+               /// <param name="i">The index at which to insert.</param>\r
+               /// <param name="item">The item to insert.</param>\r
+               protected virtual void insert(int i, T item)\r
+               {\r
+                       if (size == array.Length)\r
+                               expand();\r
+\r
+                       if (i < size)\r
+                               Array.Copy(array, i, array, i + 1, size - i);\r
+\r
+                       array[i] = item;\r
+                       size++;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+\r
+               /// <summary>\r
+               /// Create an empty ArrayBase object.\r
+               /// </summary>\r
+               /// <param name="capacity">The initial capacity of the internal array container.\r
+               /// Will be rounded upwards to the nearest power of 2 greater than or equal to 8.</param>\r
+               /// <param name="hasher">The item hasher to use, primarily for item equality</param>\r
+               public ArrayBase(int capacity, IHasher<T> hasher)\r
+               {\r
+                       int newlength = 8;\r
+\r
+                       while (newlength < capacity) newlength *= 2;\r
+\r
+                       array = new T[newlength];\r
+                       itemhasher = hasher;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IIndexed members\r
+\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/>.\r
+               /// </summary>\r
+               /// <value>The directed collection of items in a specific index interval.</value>\r
+               /// <param name="start">The low index of the interval (inclusive).</param>\r
+        /// <param name="count">The size of the range.</param>\r
+        [Tested]\r
+        public IDirectedCollectionValue<T> this[int start, int count]\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+                               checkRange(start, count);\r
+                               return new Range(this, start, count, true);\r
+                       }\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IEditableCollection members\r
+               /// <summary>\r
+               /// Remove all items and reset size of internal array container.\r
+               /// </summary>\r
+               [Tested]\r
+               public virtual void Clear()\r
+               {\r
+                       updatecheck();\r
+                       array = new T[8];\r
+                       size = 0;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an array containing (copies) of the items of this collection in enumeration order.\r
+               /// </summary>\r
+               /// <returns>The new array</returns>\r
+               [Tested]\r
+               public override T[] ToArray()\r
+               {\r
+                       T[] res = new T[size];\r
+\r
+                       Array.Copy(array, res, size);\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Perform an internal consistency (invariant) test on the array base.\r
+               /// </summary>\r
+               /// <returns>True if test succeeds.</returns>\r
+               [Tested]\r
+               public virtual bool Check()\r
+               {\r
+                       bool retval = true;\r
+\r
+                       if (size > array.Length)\r
+                       {\r
+                               Console.WriteLine("Bad size ({0}) > array.Length ({1})", size, array.Length);\r
+                               return false;\r
+                       }\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                       {\r
+                               if ((object)(array[i]) == null)\r
+                               {\r
+                                       Console.WriteLine("Bad element: null at index {0}", i);\r
+                                       return false;\r
+                               }\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IDirectedCollection<T> Members\r
+\r
+               /// <summary>\r
+               /// Create a directed collection with the same contents as this one, but \r
+               /// opposite enumeration sequence.\r
+               /// </summary>\r
+               /// <returns>The mirrored collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> Backwards() { return this[0, size].Backwards(); }\r
+\r
+               #endregion\r
+\r
+               #region IEnumerable<T> Members\r
+               /// <summary>\r
+               /// Create an enumerator for this array based collection.\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               [Tested]\r
+               public override MSG.IEnumerator<T> GetEnumerator()\r
+               {\r
+                       int thestamp = stamp, theend = size + offset, thestart = offset;\r
+\r
+                       for (int i = thestart; i < theend; i++)\r
+                       {\r
+                               modifycheck(thestamp);\r
+                               yield return array[i];\r
+                       }\r
+               }\r
+               #endregion\r
+\r
+               #region Range nested class\r
+               /// <summary>\r
+               /// A helper class for defining results of interval queries on array based collections.\r
+               /// </summary>\r
+               protected class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
+               {\r
+                       int start, count, delta, stamp;\r
+\r
+                       ArrayBase<T> thebase;\r
+\r
+\r
+                       internal Range(ArrayBase<T> thebase, int start, int count, bool forwards)\r
+                       {\r
+                               this.thebase = thebase;  stamp = thebase.stamp;\r
+                               delta = forwards ? 1 : -1;\r
+                               this.start = start + thebase.offset; this.count = count;\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// \r
+                       /// </summary>\r
+                       /// <value>The number of items in the range</value>\r
+                       [Tested]\r
+                       public override int Count { [Tested]get { thebase.modifycheck(stamp); return count; } }\r
+\r
+            /// <summary>\r
+            /// The value is symbolic indicating the type of asymptotic complexity\r
+            /// in terms of the size of this collection (worst-case or amortized as\r
+            /// relevant).\r
+            /// </summary>\r
+            /// <value>A characterization of the speed of the \r
+            /// <code>Count</code> property in this collection.</value>\r
+            public override Speed CountSpeed { get { thebase.modifycheck(stamp); return Speed.Constant; } }\r
+\r
+            /// <summary>\r
+                       /// Create an enumerator for this range of an array based collection.\r
+                       /// </summary>\r
+                       /// <returns>The enumerator</returns>\r
+                       [Tested]\r
+                       public override MSG.IEnumerator<T> GetEnumerator()\r
+                       {\r
+                               for (int i = 0; i < count; i++)\r
+                               {\r
+                                       thebase.modifycheck(stamp);\r
+                                       yield return thebase.array[start + delta * i];\r
+                               }\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Create a araay collection range with the same contents as this one, but \r
+                       /// opposite enumeration sequence.\r
+                       /// </summary>\r
+                       /// <returns>The mirrored collection.</returns>\r
+                       [Tested]\r
+                       public IDirectedCollectionValue<T> Backwards()\r
+                       {\r
+                               thebase.modifycheck(stamp);\r
+\r
+                               Range res = (Range)MemberwiseClone();\r
+\r
+                               res.delta = -delta;\r
+                               res.start = start + (count - 1) * delta;\r
+                               return res;\r
+                       }\r
+\r
+\r
+                       IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()\r
+                       {\r
+                               return Backwards();\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// <code>Forwards</code> if same, else <code>Backwards</code>\r
+                       /// </summary>\r
+                       /// <value>The enumeration direction relative to the original collection.</value>\r
+                       [Tested]\r
+                       public EnumerationDirection Direction\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       thebase.modifycheck(stamp);\r
+                                       return delta > 0 ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;\r
+                               }\r
+                       }\r
+               }\r
+               #endregion\r
+       }\r
+\r
+       #endregion\r
+\r
+       #region Sorting\r
+       /// <summary>\r
+       /// A utility class with functions for sorting arrays with respect to an IComparer&lt;T&gt;\r
+       /// </summary>\r
+       public class Sorting\r
+       {\r
+               /// <summary>\r
+               /// Sort part of array in place using IntroSort\r
+               /// </summary>\r
+               /// <param name="a">Array to sort</param>\r
+               /// <param name="f">Index of first position to sort</param>\r
+               /// <param name="b">Index of first position beyond the part to sort</param>\r
+               /// <param name="c">IComparer&lt;T&gt; to sort by</param>\r
+               [Tested]\r
+               public static void IntroSort<T>(T[] a, int f, int b, IComparer<T> c)\r
+               {\r
+                       new Sorter<T>(a, c).IntroSort(f, b);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Sort part of array in place using Insertion Sort\r
+               /// </summary>\r
+               /// <param name="a">Array to sort</param>\r
+               /// <param name="f">Index of first position to sort</param>\r
+               /// <param name="b">Index of first position beyond the part to sort</param>\r
+               /// <param name="c">IComparer&lt;T&gt; to sort by</param>\r
+               [Tested]\r
+               public static void InsertionSort<T>(T[] a, int f, int b, IComparer<T> c)\r
+               {\r
+                       new Sorter<T>(a, c).InsertionSort(f, b);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Sort part of array in place using Heap Sort\r
+               /// </summary>\r
+               /// <param name="a">Array to sort</param>\r
+               /// <param name="f">Index of first position to sort</param>\r
+               /// <param name="b">Index of first position beyond the part to sort</param>\r
+               /// <param name="c">IComparer&lt;T&gt; to sort by</param>\r
+               [Tested]\r
+               public static void HeapSort<T>(T[] a, int f, int b, IComparer<T> c)\r
+               {\r
+                       new Sorter<T>(a, c).HeapSort(f, b);\r
+               }\r
+\r
+\r
+               class Sorter<T>\r
+               {\r
+                       T[] a;\r
+\r
+                       IComparer<T> c;\r
+\r
+\r
+                       internal Sorter(T[] a, IComparer<T> c) { this.a = a; this.c = c; }\r
+\r
+\r
+                       internal void IntroSort(int f, int b)\r
+                       {\r
+                               if (b - f > 31)\r
+                               {\r
+                                       int depth_limit = (int)Math.Floor(2.5 * Math.Log(b - f, 2));\r
+\r
+                                       introSort(f, b, depth_limit);\r
+                               }\r
+                               else\r
+                                       InsertionSort(f, b);\r
+                       }\r
+\r
+\r
+                       private void introSort(int f, int b, int depth_limit)\r
+                       {\r
+                               const int size_threshold = 14;//24;\r
+\r
+                               if (depth_limit-- == 0)\r
+                                       HeapSort(f, b);\r
+                               else if (b - f <= size_threshold)\r
+                                       InsertionSort(f, b);\r
+                               else\r
+                               {\r
+                                       int p = partition(f, b);\r
+\r
+                                       introSort(f, p, depth_limit);\r
+                                       introSort(p, b, depth_limit);\r
+                               }\r
+                       }\r
+\r
+\r
+                       private int compare(T i1, T i2) { return c.Compare(i1, i2); }\r
+\r
+\r
+                       private int partition(int f, int b)\r
+                       {\r
+                               int bot = f, mid = (b + f) / 2, top = b - 1;\r
+                               T abot = a[bot], amid = a[mid], atop = a[top];\r
+\r
+                               if (compare(abot, amid) < 0)\r
+                               {\r
+                                       if (compare(atop, abot) < 0)//atop<abot<amid\r
+                                               { a[top] = amid; amid = a[mid] = abot; a[bot] = atop; }\r
+                                       else if (compare(atop, amid) < 0) //abot<=atop<amid\r
+                                               { a[top] = amid; amid = a[mid] = atop; }\r
+                                       //else abot<amid<=atop\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (compare(amid, atop) > 0) //atop<amid<=abot\r
+                                               { a[bot] = atop; a[top] = abot; }\r
+                                       else if (compare(abot, atop) > 0) //amid<=atop<abot\r
+                                               { a[bot] = amid; amid = a[mid] = atop; a[top] = abot; }\r
+                                       else //amid<=abot<=atop\r
+                                               { a[bot] = amid; amid = a[mid] = abot; }\r
+                               }\r
+\r
+                               int i = bot, j = top;\r
+\r
+                               while (true)\r
+                               {\r
+                                       while (compare(a[++i], amid) < 0);\r
+\r
+                                       while (compare(amid, a[--j]) < 0);\r
+\r
+                                       if (i < j)\r
+                                       {\r
+                                               T tmp = a[i]; a[i] = a[j]; a[j] = tmp;\r
+                                       }\r
+                                       else\r
+                                               return i;\r
+                               }\r
+                       }\r
+\r
+\r
+                       internal void InsertionSort(int f, int b)\r
+                       {\r
+                               for (int j = f + 1; j < b; j++)\r
+                               {\r
+                                       T key = a[j], other;\r
+                                       int i = j - 1;\r
+\r
+                                       if (c.Compare(other = a[i], key) > 0)\r
+                                       {\r
+                                               a[j] = other;\r
+                                               while (i > f && c.Compare(other = a[i - 1], key) > 0) { a[i--] = other; }\r
+\r
+                                               a[i] = key;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+\r
+                       internal void HeapSort(int f, int b)\r
+                       {\r
+                               for (int i = (b + f) / 2; i >= f; i--) heapify(f, b, i);\r
+\r
+                               for (int i = b - 1; i > f; i--)\r
+                               {\r
+                                       T tmp = a[f]; a[f] = a[i]; a[i] = tmp;\r
+                                       heapify(f, i, f);\r
+                               }\r
+                       }\r
+\r
+\r
+                       private void heapify(int f, int b, int i)\r
+                       {\r
+                               T pv = a[i], lv, rv, max = pv;\r
+                               int j = i, maxpt = j;\r
+\r
+                               while (true)\r
+                               {\r
+                                       int l = 2 * j - f + 1, r = l + 1;\r
+\r
+                                       if (l < b && compare(lv = a[l], max) > 0) { maxpt = l; max = lv; }\r
+\r
+                                       if (r < b && compare(rv = a[r], max) > 0) { maxpt = r; max = rv; }\r
+\r
+                                       if (maxpt == j)\r
+                                               break;\r
+\r
+                                       a[j] = max;\r
+                                       max = pv;\r
+                                       j = maxpt;\r
+                               }\r
+\r
+                               if (j > i)\r
+                                       a[j] = pv;\r
+                       }\r
+               }\r
+       }\r
+\r
+       #endregion\r
+\r
+       #region Random\r
+       /// <summary>\r
+       /// A modern random number generator based on (whatever)\r
+       /// </summary>\r
+       public class C5Random : Random\r
+       {\r
+               private uint[] Q = new uint[16];\r
+\r
+               private uint c = 362436, i = 15;\r
+\r
+\r
+               private uint Cmwc()\r
+               {\r
+                       ulong t, a = 487198574UL;\r
+                       uint x, r = 0xfffffffe;\r
+\r
+                       i = (i + 1) & 15;\r
+                       t = a * Q[i] + c;\r
+                       c = (uint)(t >> 32);\r
+                       x = (uint)(t + c);\r
+                       if (x < c)\r
+                       {\r
+                               x++;\r
+                               c++;\r
+                       }\r
+\r
+                       return Q[i] = r - x;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get a new random System.Double value\r
+               /// </summary>\r
+               /// <returns>The random double</returns>\r
+               public override double NextDouble()\r
+               {\r
+                       return Cmwc() / 4294967296.0;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get a new random System.Double value\r
+               /// </summary>\r
+               /// <returns>The random double</returns>\r
+               protected override double Sample()\r
+               {\r
+                       return NextDouble();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get a new random System.Int32 value\r
+               /// </summary>\r
+               /// <returns>The random int</returns>\r
+               public override int Next()\r
+               {\r
+                       return (int)Cmwc();\r
+               }\r
+               \r
+\r
+               /// <summary>\r
+               /// Get a random non-negative integer less than a given upper bound\r
+               /// </summary>\r
+               /// <param name="max">The upper bound (exclusive)</param>\r
+               /// <returns></returns>\r
+               public override int Next(int max)\r
+               {\r
+                       if (max < 0)\r
+                               throw new ApplicationException("max must be non-negative");\r
+\r
+                       return (int)(Cmwc() / 4294967296.0 * max);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get a random integer between two given bounds\r
+               /// </summary>\r
+               /// <param name="min">The lower bound (inclusive)</param>\r
+               /// <param name="max">The upper bound (exclusive)</param>\r
+               /// <returns></returns>\r
+               public override int Next(int min, int max)\r
+               {\r
+                       if (min > max)\r
+                               throw new ApplicationException("min must be less than or equal to max");\r
+\r
+                       return min + (int)(Cmwc() / 4294967296.0 * max);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Fill a array of byte with random bytes\r
+               /// </summary>\r
+               /// <param name="buffer">The array to fill</param>\r
+               public override void NextBytes(byte[] buffer)\r
+               {\r
+                       for (int i = 0, length = buffer.Length; i < length; i++)\r
+                               buffer[i] = (byte)Cmwc();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a random number generator seed by system time.\r
+               /// </summary>\r
+               public C5Random() : this(DateTime.Now.Ticks)\r
+               {\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a random number generator with a given seed\r
+               /// </summary>\r
+               /// <param name="seed">The seed</param>\r
+               public C5Random(long seed)\r
+               {\r
+                       if (seed == 0)\r
+                               throw new ApplicationException("Seed must be non-zero");\r
+\r
+                       uint j = (uint)(seed & 0xFFFFFFFF);\r
+\r
+                       for (int i = 0; i < 16; i++)\r
+                       {\r
+                               j ^= j << 13;\r
+                               j ^= j >>17;\r
+                               j ^= j << 5;\r
+                               Q[i] = j;\r
+                       }\r
+\r
+                       Q[15] = (uint)(seed ^ (seed >> 32));\r
+               }\r
+       }\r
+\r
+       #endregion\r
+\r
+       #region Custom code attributes\r
+\r
+       /// <summary>\r
+       /// A custom attribute to mark methods and properties as being tested \r
+       /// sufficiently in the regression test suite.\r
+       /// </summary>\r
+       [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]\r
+       public class TestedAttribute: Attribute\r
+       {\r
+\r
+               /// <summary>\r
+               /// Optional reference to test case\r
+               /// </summary>\r
+               [Tested]\r
+               public string via;\r
+\r
+\r
+               /// <summary>\r
+               /// Pretty print attribute value\r
+               /// </summary>\r
+               /// <returns>"Tested via " + via</returns>\r
+               [Tested]\r
+               public override string ToString() { return "Tested via " + via; }\r
+       }\r
+\r
+       #endregion\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/Dictionaries.cs b/mcs/class/Mono.C5/C5/Dictionaries.cs
new file mode 100644 (file)
index 0000000..6d6d498
--- /dev/null
@@ -0,0 +1,471 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// An entry in a dictionary from K to V.\r
+       /// </summary>\r
+       public struct KeyValuePair<K,V>\r
+       {\r
+               /// <summary>\r
+               /// The key field of the entry\r
+               /// </summary>\r
+               public K key;\r
+\r
+               /// <summary>\r
+               /// The value field of the entry\r
+               /// </summary>\r
+               public V value;\r
+\r
+\r
+               /// <summary>\r
+               /// Create an entry with specified key and value\r
+               /// </summary>\r
+               /// <param name="k">The key</param>\r
+               /// <param name="v">The value</param>\r
+               public KeyValuePair(K k, V v) { key = k; value = v; }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an entry with a specified key. The value is undefined.\r
+               /// </summary>\r
+               /// <param name="k">The key</param>\r
+               public KeyValuePair(K k) { key = k; value = default(V); }\r
+\r
+\r
+               /// <summary>\r
+               /// Pretty print an entry\r
+               /// </summary>\r
+               /// <returns>(key, value)</returns>\r
+               [Tested]\r
+               public override string ToString() { return "(" + key + ", " + value + ")"; }\r
+\r
+\r
+               /// <summary>\r
+               /// Check equality of entries\r
+               /// </summary>\r
+               /// <param name="obj">The other object</param>\r
+               /// <returns>True if obj is an entry of the same type and has the same key</returns>\r
+               [Tested]\r
+               public override bool Equals(object obj)\r
+               { return obj is KeyValuePair<K,V> && key.Equals(((KeyValuePair<K,V>)obj).key); }\r
+\r
+\r
+               /// <summary>\r
+               /// Get the hash code of the key.\r
+               /// </summary>\r
+               /// <returns>The hash code</returns>\r
+               [Tested]\r
+               public override int GetHashCode() { return key.GetHashCode(); }\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// Default comparer for dictionary entries in a sorted dictionary.\r
+       /// Entry comparisons only look at keys.\r
+       /// </summary>\r
+       public class KeyValuePairComparer<K,V>: IComparer<KeyValuePair<K,V>>\r
+       {\r
+               IComparer<K> myc;\r
+\r
+\r
+               /// <summary>\r
+               /// Create an entry comparer for a item comparer of the keys\r
+               /// </summary>\r
+               /// <param name="c">Comparer of keys</param>\r
+               public KeyValuePairComparer(IComparer<K> c) { myc = c; }\r
+\r
+\r
+               /// <summary>\r
+               /// Compare two entries\r
+               /// </summary>\r
+               /// <param name="a">First entry</param>\r
+               /// <param name="b">Second entry</param>\r
+               /// <returns>The result of comparing the keys</returns>\r
+               [Tested]\r
+               public int Compare(KeyValuePair<K,V> a, KeyValuePair<K,V> b)\r
+               { return myc.Compare(a.key, b.key); }\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// Default hasher for dictionary entries.\r
+       /// Operations only look at keys.\r
+       /// </summary>\r
+       public sealed class KeyValuePairHasher<K,V>: IHasher<KeyValuePair<K,V>>\r
+       {\r
+               IHasher<K> myh;\r
+\r
+\r
+               /// <summary>\r
+               /// Create an entry hasher using the default hasher for keys\r
+               /// </summary>\r
+               public KeyValuePairHasher() { myh = HasherBuilder.ByPrototype<K>.Examine(); }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an entry hasher from a specified item hasher for the keys\r
+               /// </summary>\r
+               /// <param name="c">The key hasher</param>\r
+               public KeyValuePairHasher(IHasher<K> c) { myh = c; }\r
+\r
+\r
+               /// <summary>\r
+               /// Get the hash code of the entry\r
+               /// </summary>\r
+               /// <param name="item">The entry</param>\r
+               /// <returns>The hash code of the key</returns>\r
+               [Tested]\r
+               public int GetHashCode(KeyValuePair<K,V> item) { return myh.GetHashCode(item.key); }\r
+\r
+\r
+               /// <summary>\r
+               /// Test two entries for equality\r
+               /// </summary>\r
+               /// <param name="i1">First entry</param>\r
+               /// <param name="i2">Second entry</param>\r
+               /// <returns>True if keys are equal</returns>\r
+               [Tested]\r
+               public bool Equals(KeyValuePair<K,V> i1, KeyValuePair<K,V> i2)\r
+               { return myh.Equals(i1.key, i2.key); }\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A base class for implementing a dictionary based on a set collection implementation.\r
+       /// <p>See the source code for <see cref="T:C5.HashDictionary!2"/> for an example</p>\r
+       /// \r
+       /// </summary>\r
+       public abstract class DictionaryBase<K,V>: EnumerableBase<KeyValuePair<K,V>>, IDictionary<K,V>\r
+       {\r
+               /// <summary>\r
+               /// The set collection of entries underlying this dictionary implementation\r
+               /// </summary>\r
+               protected ICollection<KeyValuePair<K,V>> pairs;\r
+\r
+\r
+               #region IDictionary<K,V> Members\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>The number of entrues in the dictionary</value>\r
+               [Tested]\r
+               public int Count { [Tested]get { return pairs.Count; } }\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>A distinguished object to use for locking to synchronize multithreaded access</value>\r
+               [Tested]\r
+               public object SyncRoot { [Tested]get { return pairs.SyncRoot; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Add a new (key, value) pair (a mapping) to the dictionary.\r
+               /// <exception cref="InvalidOperationException"/> if there already is an entry with the same key. \r
+               /// </summary>\r
+               /// <param name="key">Key to add</param>\r
+               /// <param name="val">Value to add</param>\r
+               [Tested]\r
+               public void Add(K key, V val)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key, val);\r
+\r
+                       if (!pairs.Add(p))\r
+                               throw new System.ArgumentException("Item has already been added.  Key in dictionary: '" + key + "'  Key being added: '" + key + "'");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove an entry with a given key from the dictionary\r
+               /// </summary>\r
+               /// <param name="key">The key of the entry to remove</param>\r
+               /// <returns>True if an entry was found (and removed)</returns>\r
+               [Tested]\r
+               public bool Remove(K key)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       return pairs.Remove(p);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove an entry with a given key from the dictionary and report its value.\r
+               /// </summary>\r
+               /// <param name="key">The key of the entry to remove</param>\r
+               /// <param name="val">On exit, the value of the removed entry</param>\r
+               /// <returns>True if an entry was found (and removed)</returns>\r
+               [Tested]\r
+               public bool Remove(K key, out V val)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       if (pairs.RemoveWithReturn(ref p))\r
+                       {\r
+                               val = p.value;\r
+                               return true;\r
+                       }\r
+                       else\r
+                       {\r
+                               val = default(V);\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all entries from the dictionary\r
+               /// </summary>\r
+               [Tested]\r
+               public void Clear() { pairs.Clear(); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if there is an entry with a specified key\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <returns>True if key was found</returns>\r
+               [Tested]\r
+               public bool Contains(K key)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       return pairs.Contains(p);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if there is an entry with a specified key and report the corresponding\r
+               /// value if found. This can be seen as a safe form of "val = this[key]".\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">On exit, the value of the entry</param>\r
+               /// <returns>True if key was found</returns>\r
+               [Tested]\r
+               public bool Find(K key, out V val)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       if (pairs.Find(ref p))\r
+                       {\r
+                               val = p.value;\r
+                               return true;\r
+                       }\r
+                       else\r
+                       {\r
+                               val = default(V);\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Look for a specific key in the dictionary and if found replace the value with a new one.\r
+               /// This can be seen as a non-adding version of "this[key] = val".\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">The new value</param>\r
+               /// <returns>True if key was found</returns>\r
+               [Tested]\r
+               public bool Update(K key, V val)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key, val);\r
+\r
+                       return pairs.Update(p);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Look for a specific key in the dictionary. If found, report the corresponding value,\r
+               /// else add an entry with the key and the supplied value.\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">On entry the value to add if the key is not found.\r
+               /// On exit the value found if any.</param>\r
+               /// <returns>True if key was found</returns>\r
+               [Tested]\r
+               public bool FindOrAdd(K key, ref V val)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key, val);\r
+\r
+                       if (!pairs.FindOrAdd(ref p))\r
+                               return false;\r
+                       else\r
+                       {\r
+                               val = p.value;\r
+                               return true;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Update value in dictionary corresponding to key if found, else add new entry.\r
+               /// More general than "this[key] = val;" by reporting if key was found.\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">The value to add or replace with.</param>\r
+               /// <returns>True if entry was updated.</returns>\r
+               [Tested]\r
+               public bool UpdateOrAdd(K key, V val)\r
+               {\r
+                       return pairs.UpdateOrAdd(new KeyValuePair<K,V>(key, val));\r
+               }\r
+\r
+\r
+\r
+               #region Keys,Values support classes\r
+                       \r
+               internal class ValuesCollection: CollectionValueBase<V>, ICollectionValue<V>\r
+               {\r
+                       ICollection<KeyValuePair<K,V>> pairs;\r
+\r
+\r
+                       internal ValuesCollection(ICollection<KeyValuePair<K,V>> pairs)\r
+                       { this.pairs = pairs; }\r
+\r
+\r
+                       [Tested]\r
+                       public override MSG.IEnumerator<V> GetEnumerator()\r
+                       {\r
+                               //Updatecheck is performed by the pairs enumerator\r
+                               foreach (KeyValuePair<K,V> p in pairs)\r
+                                       yield return p.value;\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+            public override int Count { [Tested]get { return pairs.Count; } }\r
+\r
+            public override Speed CountSpeed { get { return Speed.Constant; } }\r
+        }\r
+\r
+\r
+\r
+        internal class KeysCollection: CollectionValueBase<K>, ICollectionValue<K>\r
+               {\r
+                       ICollection<KeyValuePair<K,V>> pairs;\r
+\r
+\r
+                       internal KeysCollection(ICollection<KeyValuePair<K,V>> pairs)\r
+                       { this.pairs = pairs; }\r
+\r
+\r
+                       [Tested]\r
+                       public override MSG.IEnumerator<K> GetEnumerator()\r
+                       {\r
+                               foreach (KeyValuePair<K,V> p in pairs)\r
+                                       yield return p.key;\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       public override int Count { [Tested]get { return pairs.Count; } }\r
+\r
+            public override Speed CountSpeed { get { return pairs.CountSpeed; } }\r
+        }\r
+               #endregion\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>A collection containg the all the keys of the dictionary</value>\r
+               [Tested]\r
+               public ICollectionValue<K> Keys { [Tested]get { return new KeysCollection(pairs); } }\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>A collection containing all the values of the dictionary</value>\r
+               [Tested]\r
+               public ICollectionValue<V> Values { [Tested]get { return new ValuesCollection(pairs); } }\r
+\r
+\r
+               /// <summary>\r
+               /// Indexer for dictionary.\r
+               /// <exception cref="InvalidOperationException"/> if no entry is found. \r
+               /// </summary>\r
+               /// <value>The value corresponding to the key</value>\r
+               [Tested]\r
+               public V this[K key]\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+                               KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                               if (pairs.Find(ref p))\r
+                                       return p.value;\r
+                               else\r
+                                       throw new System.ArgumentException("Key not present in Dictionary");\r
+                       }\r
+                       [Tested]\r
+                       set\r
+                       { pairs.UpdateOrAdd(new KeyValuePair<K,V>(key, value)); }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True if dictionary is read  only</value>\r
+               [Tested]\r
+               public bool IsReadOnly { [Tested]get { return pairs.IsReadOnly; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this dictionary.\r
+               /// Only avaliable in DEBUG builds???\r
+               /// </summary>\r
+               /// <returns>True if check does not fail.</returns>\r
+               [Tested]\r
+               public bool Check() { return pairs.Check(); }\r
+\r
+               #endregion\r
+\r
+               #region IEnumerable<KeyValuePair<K,V>> Members\r
+\r
+\r
+               /// <summary>\r
+               /// Create an enumerator for the collection of entries of the dictionary\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               [Tested]\r
+               public override MSG.IEnumerator<KeyValuePair<K,V>> GetEnumerator()\r
+               {\r
+                       return pairs.GetEnumerator();;\r
+               }\r
+\r
+               #endregion\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/Interfaces.cs b/mcs/class/Mono.C5/C5/Interfaces.cs
new file mode 100644 (file)
index 0000000..c999dc2
--- /dev/null
@@ -0,0 +1,1378 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using MSG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+       /*************************************************************************/\r
+    //TODO: use the MS defs fro m MSG if any?\r
+       /// <summary>\r
+       /// A generic delegate that when invoked performs some operation\r
+       /// on it T argument.\r
+       /// </summary>\r
+       public delegate void Applier<T>(T t);\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A generic delegate whose invocation constitutes a map from T to V.\r
+       /// </summary>\r
+       public delegate V Mapper<T,V>(T item);\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A generic delegate that when invoked on a T item returns a boolean\r
+       /// value -- i.e. a T predicate.\r
+       /// </summary> \r
+       public delegate bool Filter<T>(T item);\r
+\r
+\r
+\r
+       /************************************************************************\r
+       /// <summary>\r
+       /// A generic collection that may be enumerated. This is the coarsest interface\r
+       /// for main stream generic collection classes (as opposed to priority queues).\r
+       /// It can also be the result of a query operation on another collection \r
+       /// (where the result size is not easily computable, in which case the result\r
+       /// could have been an <code>ICollectionValue&lt;T&gt;</code>).\r
+       /// </summary>\r
+       public interface noIEnumerable<T>\r
+       {\r
+               /// <summary>\r
+               /// Create an enumerator for the collection\r
+               /// </summary>\r
+               /// <returns>The enumerator(SIC)</returns>\r
+               MSG.IEnumerator<T> GetEnumerator();\r
+       }\r
+    */\r
+\r
+\r
+       /// <summary>\r
+       /// A generic collection, that can be enumerated backwards.\r
+       /// </summary>\r
+       public interface IDirectedEnumerable<T>: MSG.IEnumerable<T>\r
+       {\r
+               /// <summary>\r
+               /// Create a collection containing the same items as this collection, but\r
+               /// whose enumerator will enumerate the items backwards. The new collection\r
+               /// will become invalid if the original is modified. Method typicaly used as in\r
+               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
+               /// </summary>\r
+               /// <returns>The backwards collection.</returns>\r
+               IDirectedEnumerable<T> Backwards();\r
+\r
+\r
+               /// <summary>\r
+               /// <code>Forwards</code> if same, else <code>Backwards</code>\r
+               /// </summary>\r
+               /// <value>The enumeration direction relative to the original collection.</value>\r
+               EnumerationDirection Direction { get;}\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A generic collection that may be enumerated and can answer\r
+       /// efficiently how many items it contains. Like <code>IEnumerable&lt;T&gt;</code>,\r
+       /// this interface does not prescribe any operations to initialize or update the \r
+       /// collection. The main usage for this interface is to be the return type of \r
+       /// query operations on generic collection.\r
+       /// </summary>\r
+       public interface ICollectionValue<T>: MSG.IEnumerable<T>\r
+       {\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>The number of items in this collection</value>\r
+               int Count { get;}\r
+\r
+        /// <summary>\r
+        /// The value is symbolic indicating the type of asymptotic complexity\r
+        /// in terms of the size of this collection (worst-case or amortized as\r
+        /// relevant).\r
+        /// </summary>\r
+        /// <value>A characterization of the speed of the \r
+        /// <code>Count</code> property in this collection.</value>\r
+        Speed CountSpeed { get;}\r
+\r
+        /// <summary>\r
+               /// Copy the items of this collection to a contiguous part of an array.\r
+               /// </summary>\r
+               /// <param name="a">The array to copy to</param>\r
+               /// <param name="i">The index at which to copy the first item</param>\r
+               void CopyTo(T[] a, int i);\r
+\r
+        /// <summary>\r
+        /// Create an array with the items of this collection (in the same order as an\r
+        /// enumerator would output them).\r
+        /// </summary>\r
+        /// <returns>The array</returns>\r
+        T[] ToArray();\r
+\r
+        /// <summary>\r
+        /// Apply a delegate to all items of this collection.\r
+        /// </summary>\r
+        /// <param name="a">The delegate to apply</param>\r
+        void Apply(Applier<T> a);\r
+\r
+\r
+        /// <summary>\r
+        /// Check if there exists an item  that satisfies a\r
+        /// specific predicate in this collection.\r
+        /// </summary>\r
+        /// <param name="filter">A filter delegate \r
+        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
+        /// <returns>True is such an item exists</returns>\r
+        bool Exists(Filter<T> filter);\r
+\r
+\r
+        /// <summary>\r
+        /// Check if all items in this collection satisfies a specific predicate.\r
+        /// </summary>\r
+        /// <param name="filter">A filter delegate \r
+        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
+        /// <returns>True if all items satisfies the predicate</returns>\r
+        bool All(Filter<T> filter);\r
+    }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A sized generic collection, that can be enumerated backwards.\r
+       /// </summary>\r
+       public interface IDirectedCollectionValue<T>: ICollectionValue<T>, IDirectedEnumerable<T>\r
+       {\r
+               /// <summary>\r
+               /// Create a collection containing the same items as this collection, but\r
+               /// whose enumerator will enumerate the items backwards. The new collection\r
+               /// will become invalid if the original is modified. Method typicaly used as in\r
+               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
+               /// </summary>\r
+               /// <returns>The backwards collection.</returns>\r
+               new IDirectedCollectionValue<T> Backwards();\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A generic collection to which one may add items. This is just the intersection\r
+       /// of the main stream generic collection interfaces and the priority queue interface,\r
+       /// <see cref="T:C5.ICollection!1"/> and <see cref="T:C5.IPriorityQueue!1"/>.\r
+       /// </summary>\r
+       public interface IExtensible<T> : ICollectionValue<T>\r
+       {\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>False if this collection has set semantics, true if bag semantics.</value>\r
+               bool AllowsDuplicates { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>An object to be used for locking to enable multi threaded code\r
+               /// to acces this collection safely.</value>\r
+               object SyncRoot { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True if this collection is empty.</value>\r
+               bool IsEmpty { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to this collection if possible. If this collection has set\r
+               /// semantics, the item will be added if not already in the collection. If\r
+               /// bag semantics, the item will always be added.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True if item was added.</returns>\r
+               bool Add(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Add the elements from another collection to this collection. If this\r
+               /// collection has set semantics, only items not already in the collection\r
+               /// will be added.\r
+               /// </summary>\r
+               /// <param name="items">The items to add.</param>\r
+               void AddAll(MSG.IEnumerable<T> items);\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. If this\r
+        /// collection has set semantics, only items not already in the collection\r
+        /// will be added.\r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        void AddAll<U>(MSG.IEnumerable<U> items) where U : T;\r
+\r
+               //void Clear(); // for priority queue\r
+               //int Count why not?\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this collection.\r
+               /// <p>This is only relevant for developers of the library</p>\r
+               /// </summary>\r
+               /// <returns>True if check was passed.</returns>\r
+               bool Check();\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// The symbolic characterization of the speed of lookups for a collection.\r
+       /// The values may refer to worst-case, amortized and/or expected asymtotic \r
+       /// complexity wrt. the collection size.\r
+       /// </summary>\r
+       public enum Speed: short\r
+       {\r
+        /// <summary>\r
+        /// Counting the collection with the <code>Count property</code> may not return\r
+        /// (for a synthetic and potentially infinite collection).\r
+        /// </summary>\r
+        PotentiallyInfinite = 1,\r
+        /// <summary>\r
+        /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>\r
+        /// property may take time O(n),\r
+        /// where n is the size of the collection.\r
+        /// </summary>\r
+        Linear = 2,\r
+        /// <summary>\r
+        /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>\r
+        /// property  takes time O(log n),\r
+        /// where n is the size of the collection.\r
+               /// </summary>\r
+               Log = 3,\r
+               /// <summary>\r
+        /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>\r
+        /// property  takes time O(1),\r
+        /// where n is the size of the collection.\r
+               /// </summary>\r
+               Constant = 4\r
+       }\r
+\r
+\r
+\r
+       //TODO: add ItemHasher to interface by making it an IHasher<T>? No, add Comparer property!\r
+       /// <summary>\r
+       /// The simplest interface of a main stream generic collection\r
+       /// with lookup, insertion and removal operations. \r
+       /// </summary>\r
+       public interface ICollection<T>: IExtensible<T>\r
+       {\r
+               /// <summary>\r
+               /// If true any call of an updating operation will throw an\r
+               /// <code>InvalidOperationException</code>\r
+               /// </summary>\r
+               /// <value>True if this collection is read only.</value>\r
+               bool IsReadOnly { get;}\r
+\r
+\r
+               //This is somewhat similar to the RandomAccess marker itf in java\r
+               /// <summary>\r
+               /// The value is symbolic indicating the type of asymptotic complexity\r
+               /// in terms of the size of this collection (worst-case or amortized as\r
+               /// relevant).\r
+               /// </summary>\r
+               /// <value>A characterization of the speed of lookup operations\r
+               /// (<code>Contains()</code> etc.) of the implementation of this list.</value>\r
+               Speed ContainsSpeed { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// The hashcode is defined as the sum of <code>h(item)</code> over the items\r
+               /// of the collection, where the function <code>h</code> is??? \r
+               /// </summary>\r
+               /// <returns>The unordered hashcode of this collection.</returns>\r
+               int GetHashCode();\r
+\r
+\r
+               /// <summary>\r
+               /// Compare the contents of this collection to another one without regards to\r
+               /// the sequence order. The comparison will use this collection's itemhasher\r
+               /// to compare individual items.\r
+               /// </summary>\r
+               /// <param name="that">The collection to compare to.</param>\r
+               /// <returns>True if this collection and that contains the same items.</returns>\r
+               bool Equals(ICollection<T> that);\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains (an item equivalent to according to the\r
+               /// itemhasher) a particular value.\r
+               /// </summary>\r
+               /// <param name="item">The value to check for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               bool Contains(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Count the number of items of the collection equal to a particular value.\r
+               /// Returns 0 if and only if the value is not in the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to count.</param>\r
+               /// <returns>The number of copies found.</returns>\r
+               int ContainsCount(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains all the values in another collection.\r
+               /// If this collection has bag semantics (<code>NoDuplicates==false</code>)\r
+               /// the check is made with respect to multiplicities, else multiplicities\r
+               /// are not taken into account.\r
+               /// </summary>\r
+               /// <param name="items">The </param>\r
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+               bool ContainsAll(MSG.IEnumerable<T> items);\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               bool Find(ref T item);\r
+\r
+\r
+               //This should probably just be bool Add(ref T item); !!!\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found. Else, add the item to the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the item was found (hence not added).</returns>\r
+               bool FindOrAdd(ref T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
+               /// it is implementation dependent if this updates all equivalent copies in\r
+               /// the collection or just one.\r
+               /// </summary>\r
+               /// <param name="item">Value to update.</param>\r
+               /// <returns>True if the item was found and hence updated.</returns>\r
+               bool Update(T item);\r
+\r
+\r
+               //Better to call this AddOrUpdate since the return value fits that better\r
+               //OTOH for a bag the update would be better be the default!!!\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value; else add the value to the collection. \r
+               /// </summary>\r
+               /// <param name="item">Value to add or update.</param>\r
+               /// <returns>True if the item was found and updated (hence not added).</returns>\r
+               bool UpdateOrAdd(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection. If the collection has bag\r
+               /// semantics only one copy equivalent to the supplied item is removed. \r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               bool Remove(T item);\r
+\r
+\r
+               //CLR will allow us to let this be bool Remove(ref T item); !!!\r
+               /// <summary>\r
+               /// Remove a particular item from this collection if found. If the collection\r
+               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
+               /// which one is implementation dependent. \r
+               /// If an item was removed, report a binary copy of the actual item removed in \r
+               /// the argument.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove on input.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               bool RemoveWithReturn(ref T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items equivalent to a given value.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               void RemoveAllCopies(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in another collection from this one. If this collection\r
+               /// has bag semantics, take multiplicities into account.\r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               void RemoveAll(MSG.IEnumerable<T> items);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from this collection.\r
+               /// </summary>\r
+               void Clear();\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items not in some other collection from this one. If this collection\r
+               /// has bag semantics, take multiplicities into account.\r
+               /// </summary>\r
+               /// <param name="items">The items to retain.</param>\r
+               void RetainAll(MSG.IEnumerable<T> items);\r
+\r
+               //IDictionary<T> UniqueItems()\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// An editable collection maintaining a definite sequence order of the items.\r
+       ///\r
+       /// <p>Implementations of this interface must compute the hash code and \r
+       /// equality exactly as prescribed in the method definitions in order to\r
+       /// be consistent with other collection classes implementing this interface.</p>\r
+       /// <p>This interface is usually implemented by explicit interface implementation,\r
+       /// not as ordinary virtual methods.</p>\r
+       /// </summary>\r
+       public interface ISequenced<T>: ICollection<T>, IDirectedCollectionValue<T>\r
+       {\r
+               /// <summary>\r
+               /// The hashcode is defined as <code>h(...h(h(x1),x2)...,xn)</code> for\r
+               /// <code>h(a,b)=31*a+b</code> and the x's the hash codes of \r
+               /// </summary>\r
+               /// <returns>The sequence order hashcode of this collection.</returns>\r
+               new int GetHashCode();\r
+\r
+\r
+               /// <summary>\r
+               /// Compare this sequenced collection to another one in sequence order.\r
+               /// </summary>\r
+               /// <param name="that">The sequenced collection to compare to.</param>\r
+               /// <returns>True if this collection and that contains equal (according to\r
+               /// this collection's itemhasher) in the same sequence order.</returns>\r
+               bool Equals(ISequenced<T> that);\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A sequenced collection, where indices of items in the order are maintained\r
+       /// </summary>\r
+       public interface IIndexed<T>: ISequenced<T>\r
+       {\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <value>The i'th item of this list.</value>\r
+               /// <param name="i">the index to lookup</param>\r
+               T this[int i] { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/>.\r
+               /// </summary>\r
+               /// <value>The directed collection of items in a specific index interval.</value>\r
+               /// <param name="start">The low index of the interval (inclusive).</param>\r
+               /// <param name="count">The size of the range.</param>\r
+               IDirectedCollectionValue<T> this[int start, int count] { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going forwrds from the start.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of item from start.</returns>\r
+               int IndexOf(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going backwords from the end.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of of item from the end.</returns>\r
+               int LastIndexOf(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the item at a specific position of the list.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <param name="i">The index of the item to remove.</param>\r
+               /// <returns>The removed item.</returns>\r
+               T RemoveAt(int i);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in an index interval.\r
+               /// <exception cref="IndexOutOfRangeException"/>???. \r
+               /// </summary>\r
+               /// <param name="start">The index of the first item to remove.</param>\r
+               /// <param name="count">The number of items to remove.</param>\r
+               void RemoveInterval(int start, int count);\r
+       }\r
+\r
+    //TODO: decide if this should extend ICollection\r
+    /// <summary>\r
+    /// The interface describing the operations of a LIFO stack data structure.\r
+    /// </summary>\r
+    /// <typeparam name="T">The item type</typeparam>\r
+    public interface IStack<T>\r
+    {\r
+        /// <summary>\r
+        /// Push an item to the top of the stack.\r
+        /// </summary>\r
+        /// <param name="item">The item</param>\r
+        void Push(T item);\r
+        /// <summary>\r
+        /// Pop the item at the top of the stack from the stack.\r
+        /// </summary>\r
+        /// <returns>The popped item.</returns>\r
+        T Pop();\r
+    }\r
+\r
+    //TODO: decide if this should extend ICollection\r
+    /// <summary>\r
+    /// The interface describing the operations of a FIFO queue data structure.\r
+    /// </summary>\r
+    /// <typeparam name="T">The item type</typeparam>\r
+    public interface IQueue<T>\r
+    {\r
+        /// <summary>\r
+        /// Enqueue an item at the back of the queue. \r
+        /// </summary>\r
+        /// <param name="item">The item</param>\r
+        void EnQueue(T item);\r
+        /// <summary>\r
+        /// Dequeue an item from the front of the queue.\r
+        /// </summary>\r
+        /// <returns>The item</returns>\r
+        T DeQueue();\r
+    }\r
+\r
+\r
+       /// <summary>\r
+       /// This is an indexed collection, where the item order is chosen by \r
+       /// the user at insertion time.\r
+       ///\r
+       /// NBNBNB: we neeed a description of the view functionality here!\r
+       /// </summary>\r
+       public interface IList<T>: IIndexed<T>, IStack<T>, IQueue<T>\r
+       {\r
+               /// <summary>\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <value>The first item in this list.</value>\r
+               T First { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <value>The last item in this list.</value>\r
+               T Last { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// Since <code>Add(T item)</code> always add at the end of the list,\r
+               /// this describes if list has FIFO or LIFO semantics.\r
+               /// </summary>\r
+               /// <value>True if the <code>Remove()</code> operation removes from the\r
+               /// start of the list, false if it removes from the end.</value>\r
+               bool FIFO { get; set;}\r
+\r
+\r
+               /// <summary>\r
+               /// On this list, this indexer is read/write.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <value>The i'th item of this list.</value>\r
+               /// <param name="i">The index of the item to fetch or store.</param>\r
+               new T this[int i] { get; set;}\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at a specific index location in this list. \r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt; the size of the collection.</summary>\r
+               /// <exception cref="InvalidOperationException"/> if the list has\r
+               /// <code>NoDuplicates=true</code> and the item is \r
+               /// already in the list.\r
+               /// <param name="i">The index at which to insert.</param>\r
+               /// <param name="item">The item to insert.</param>\r
+               void Insert(int i, T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at the front of this list.\r
+               /// <exception cref="InvalidOperationException"/> if the list has\r
+               /// <code>NoDuplicates=true</code> and the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               void InsertFirst(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at the back of this list.\r
+               /// <exception cref="InvalidOperationException"/> if the list has\r
+               /// <code>NoDuplicates=true</code> and the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               void InsertLast(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item right before the first occurrence of some target item.\r
+               /// <exception cref="InvalidOperationException"/> if target     is not found\r
+               /// or if the list has <code>NoDuplicates=true</code> and the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target before which to insert.</param>\r
+               void InsertBefore(T item, T target);\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item right after the last(???) occurrence of some target item.\r
+               /// <exception cref="InvalidOperationException"/> if target     is not found\r
+               /// or if the list has <code>NoDuplicates=true</code> and the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target after which to insert.</param>\r
+               void InsertAfter(T item, T target);\r
+\r
+\r
+               /// <summary>\r
+               /// Insert into this list all items from an enumerable collection starting \r
+               /// at a particular index.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt; the size of the collection.\r
+               /// <exception cref="InvalidOperationException"/> if the list has \r
+               /// <code>NoDuplicates=true</code> and one of the items to insert is\r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="i">Index to start inserting at</param>\r
+               /// <param name="items">Items to insert</param>\r
+               void InsertAll(int i, MSG.IEnumerable<T> items);\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new list consisting of the items of this list satisfying a \r
+               /// certain predicate.\r
+               /// </summary>\r
+               /// <param name="filter">The filter delegate defining the predicate.</param>\r
+               /// <returns>The new list.</returns>\r
+               IList<T> FindAll(Filter<T> filter);\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new list consisting of the results of mapping all items of this\r
+               /// list. The new list will use the default hasher for the item type V.\r
+               /// </summary>\r
+               /// <typeparam name="V">The type of items of the new list</typeparam>\r
+               /// <param name="mapper">The delegate defining the map.</param>\r
+               /// <returns>The new list.</returns>\r
+               IList<V> Map<V>(Mapper<T,V> mapper);\r
+\r
+        /// <summary>\r
+        /// Create a new list consisting of the results of mapping all items of this\r
+               /// list. The new list will use a specified hasher for the item type.\r
+        /// </summary>\r
+        /// <typeparam name="V">The type of items of the new list</typeparam>\r
+        /// <param name="mapper">The delegate defining the map.</param>\r
+        /// <param name="hasher">The hasher to use for the new list</param>\r
+        /// <returns>The new list.</returns>\r
+        IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher);\r
+        \r
+        /// <summary>\r
+        /// Remove one item from the list: from the front if <code>FIFO</code>\r
+               /// is true, else from the back.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               T Remove();\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one item from the fromnt of the list.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               T RemoveFirst();\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one item from the back of the list.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               T RemoveLast();\r
+\r
+\r
+               /// <summary>\r
+               /// Create a list view on this list. \r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the view would not fit into\r
+               /// this list.\r
+               /// </summary>\r
+               /// <param name="start">The index in this list of the start of the view.</param>\r
+               /// <param name="count">The size of the view.</param>\r
+               /// <returns>The new list view.</returns>\r
+               IList<T> View(int start, int count);\r
+\r
+\r
+               /// <summary>\r
+               /// Null if this list is not a view.\r
+               /// </summary>\r
+        /// <value>Underlying list for view.</value>\r
+        IList<T> Underlying { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// </summary>\r
+        /// <value>Offset for this list view or 0 for an underlying list.</value>\r
+        int Offset { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// Slide this list view along the underlying list.\r
+               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
+               /// would bring either end of the view outside the underlying list.\r
+               /// </summary>\r
+               /// <param name="offset">The signed amount to slide: positive to slide\r
+               /// towards the end.</param>\r
+               void Slide(int offset);\r
+\r
+\r
+               /// <summary>\r
+               /// Slide this list view along the underlying list, changing its size.\r
+               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
+               /// would bring either end of the view outside the underlying list.\r
+               /// </summary>\r
+               /// <param name="offset">The signed amount to slide: positive to slide\r
+               /// towards the end.</param>\r
+               /// <param name="size">The new size of the view.</param>\r
+               void Slide(int offset, int size);\r
+\r
+\r
+               /// <summary>\r
+               /// Reverse the list so the items are in the opposite sequence order.\r
+               /// </summary>\r
+               void Reverse();\r
+\r
+\r
+               /// <summary>\r
+               /// Reverst part of the list so the items are in the opposite sequence order.\r
+               /// <exception cref="ArgumentException"/> if the count is negative.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
+               /// into the list.\r
+               /// </summary>\r
+               /// <param name="start">The index of the start of the part to reverse.</param>\r
+               /// <param name="count">The size of the part to reverse.</param>\r
+               void Reverse(int start, int count);\r
+\r
+\r
+               //NaturalSort for comparable items?\r
+               /// <summary>\r
+               /// Check if this list is sorted according to a specific sorting order.\r
+               /// </summary>\r
+               /// <param name="c">The comparer defining the sorting order.</param>\r
+               /// <returns>True if the list is sorted, else false.</returns>\r
+               bool IsSorted(IComparer<T> c);\r
+\r
+\r
+               /// <summary>\r
+               /// Sort the items of the list according to a specific sorting order.\r
+               /// </summary>\r
+               /// <param name="c">The comparer defining the sorting order.</param>\r
+               void Sort(IComparer<T> c);\r
+\r
+\r
+               /// <summary>\r
+               /// Randonmly shuffle the items of this list. \r
+               /// </summary>\r
+               void Shuffle();\r
+\r
+\r
+               /// <summary>\r
+               /// Shuffle the items of this list according to a specific random source.\r
+               /// </summary>\r
+               /// <param name="rnd">The random source.</param>\r
+               void Shuffle(Random rnd);\r
+       }\r
+\r
+\r
+    /// <summary>\r
+       /// A generic collection of items prioritized by a comparison (order) relation.\r
+       /// Supports adding items and reporting or removing extremal elements. \r
+       /// The priority queue itself exports the used\r
+       /// order relation through its implementation of <code>IComparer&lt;T&gt;</code>\r
+       /// </summary>\r
+       public interface IPriorityQueue<T>: IExtensible<T>\r
+       {\r
+\r
+               /// <summary>\r
+               /// Find the current least item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The least item.</returns>\r
+               T FindMin();\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the least item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               T DeleteMin();\r
+\r
+\r
+               /// <summary>\r
+               /// Find the current largest item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The largest item.</returns>\r
+               T FindMax();\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the largest item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               T DeleteMax();\r
+\r
+        /// <summary>\r
+        /// The comparer object supplied at creation time for this collection\r
+        /// </summary>\r
+        /// <value>The comparer</value>\r
+        IComparer<T> Comparer { get;}\r
+    }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A collection where items are maintained in sorted order.\r
+       /// </summary>\r
+       public interface ISorted<T>: ISequenced<T>, IPriorityQueue<T>\r
+       {\r
+               /// <summary>\r
+               /// Find the strict predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than or equal to the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the predecessor for.</param>\r
+               /// <returns>The predecessor.</returns>\r
+               T Predecessor(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Find the strict successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than or equal to the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the successor for.</param>\r
+               /// <returns>The successor.</returns>\r
+               T Successor(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak predecessor for.</param>\r
+               /// <returns>The weak predecessor.</returns>\r
+               T WeakPredecessor(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak successor for.</param>\r
+               /// <returns>The weak successor.</returns>\r
+               T WeakSuccessor(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Perform a search in the sorted collection for the ranges in which a\r
+               /// non-decreasing function from the item type to <code>int</code> is\r
+               /// negative, zero respectively positive. If the supplied cut function is\r
+               /// not non-decreasing, the result of this call is undefined.\r
+               /// </summary>\r
+               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
+               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
+               /// the <code>c.CompareTo(T that)</code> method.</param>\r
+               /// <param name="low">Returns the largest item in the collection, where the\r
+               /// cut function is negative (if any).</param>\r
+               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
+               /// on this collection.</param>\r
+               /// <param name="high">Returns the least item in the collection, where the\r
+               /// cut function is positive (if any).</param>\r
+               /// <param name="highIsValid">True if the cut function is positive somewhere\r
+               /// on this collection.</param>\r
+               /// <returns></returns>\r
+               bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid);\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items greater than or equal to a supplied value.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               IDirectedEnumerable<T> RangeFrom(T bot);\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items between two supplied values.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               IDirectedEnumerable<T> RangeFromTo(T bot, T top);\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items less than a supplied value.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               IDirectedEnumerable<T> RangeTo(T top);\r
+\r
+\r
+               /// <summary>\r
+               /// Create a directed collection with the same items as this collection.\r
+               /// </summary>\r
+               /// <returns>The result directed collection.</returns>\r
+               IDirectedCollectionValue<T> RangeAll();\r
+\r
+\r
+               /// <summary>\r
+               /// Add all the items from another collection with an enumeration order that \r
+               /// is increasing in the items.\r
+               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
+               /// not to be in increasing order.\r
+               /// </summary>\r
+               /// <param name="items">The collection to add.</param>\r
+               void AddSorted(MSG.IEnumerable<T> items);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection above or at a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               void RemoveRangeFrom(T low);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               void RemoveRangeFromTo(T low, T hi);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               void RemoveRangeTo(T hi);\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A collection where items are maintained in sorted order together\r
+       /// with their indexes in that order.\r
+       /// </summary>\r
+       public interface IIndexedSorted<T>: ISorted<T>, IIndexed<T>\r
+       {\r
+               /// <summary>\r
+               /// Determine the number of items at or above a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               int CountFrom(T bot);\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               int CountFromTo(T bot, T top);\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               int CountTo(T top);\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items greater than or equal to a supplied value.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               new IDirectedCollectionValue<T> RangeFrom(T bot);\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items between two supplied values.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               new IDirectedCollectionValue<T> RangeFromTo(T bot, T top);\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items less than a supplied value.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               new IDirectedCollectionValue<T> RangeTo(T top);\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the items of this\r
+               /// indexed sorted collection satisfying a certain predicate.\r
+               /// </summary>\r
+               /// <param name="f">The filter delegate defining the predicate.</param>\r
+               /// <returns>The new indexed sorted collection.</returns>\r
+               IIndexedSorted<T> FindAll(Filter<T> f);\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the results of\r
+               /// mapping all items of this list.\r
+               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
+               /// the items of this collection (with respect to the two given comparison \r
+               /// relations).\r
+               /// </summary>\r
+               /// <param name="m">The delegate definging the map.</param>\r
+               /// <param name="c">The comparion relation to use for the result.</param>\r
+               /// <returns>The new sorted collection.</returns>\r
+               IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c);\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// The type of a sorted collection with persistence\r
+       /// </summary>\r
+       public interface IPersistentSorted<T>: ISorted<T>, IDisposable\r
+       {\r
+               /// <summary>\r
+               /// Make a (read-only) snap shot of this collection.\r
+               /// </summary>\r
+               /// <returns>The snap shot.</returns>\r
+               ISorted<T> Snapshot();\r
+    }\r
+\r
+\r
+\r
+       /*************************************************************************/\r
+       /// <summary>\r
+       /// A dictionary with keys of type K and values of type V. Equivalent to a\r
+       /// finite partial map from K to V.\r
+       /// </summary>\r
+       public interface IDictionary<K,V>: MSG.IEnumerable<KeyValuePair<K,V>>\r
+       {\r
+               /// <summary>\r
+               /// Indexer for dictionary.\r
+               /// <exception cref="InvalidOperationException"/> if no entry is found. \r
+               /// </summary>\r
+               /// <value>The value corresponding to the key</value>\r
+               V this[K key] { get; set;}\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>The number of entrues in the dictionary</value>\r
+               int Count { get; }\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True if dictionary is read  only</value>\r
+               bool IsReadOnly { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>The distinguished object to use for locking to synchronize multithreaded access</value>\r
+               object SyncRoot { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>A collection containg the all the keys of the dictionary</value>\r
+               ICollectionValue<K> Keys { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>A collection containing all the values of the dictionary</value>\r
+               ICollectionValue<V> Values { get;}\r
+\r
+\r
+               /// <summary>\r
+               /// Add a new (key, value) pair (a mapping) to the dictionary.\r
+               /// <exception cref="InvalidOperationException"/> if there already is an entry with the same key. \r
+               /// </summary>\r
+               /// <param name="key">Key to add</param>\r
+               /// <param name="val">Value to add</param>\r
+               void Add(K key, V val);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove an entry with a given key from the dictionary\r
+               /// </summary>\r
+               /// <param name="key">The key of the entry to remove</param>\r
+               /// <returns>True if an entry was found (and removed)</returns>\r
+               bool Remove(K key);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove an entry with a given key from the dictionary and report its value.\r
+               /// </summary>\r
+               /// <param name="key">The key of the entry to remove</param>\r
+               /// <param name="val">On exit, the value of the removed entry</param>\r
+               /// <returns>True if an entry was found (and removed)</returns>\r
+               bool Remove(K key, out V val);\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all entries from the dictionary\r
+               /// </summary>\r
+               void Clear();\r
+\r
+\r
+               /// <summary>\r
+               /// Check if there is an entry with a specified key\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <returns>True if key was found</returns>\r
+               bool Contains(K key);\r
+\r
+\r
+               /// <summary>\r
+               /// Check if there is an entry with a specified key and report the corresponding\r
+               /// value if found. This can be seen as a safe form of "val = this[key]".\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">On exit, the value of the entry</param>\r
+               /// <returns>True if key was found</returns>\r
+               bool Find(K key, out V val);        \r
+\r
+\r
+               /// <summary>\r
+               /// Look for a specific key in the dictionary and if found replace the value with a new one.\r
+               /// This can be seen as a non-adding version of "this[key] = val".\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">The new value</param>\r
+               /// <returns>True if key was found</returns>\r
+               bool Update(K key, V val);          //no-adding                                 \r
+\r
+\r
+               /// <summary>\r
+               /// Look for a specific key in the dictionary. If found, report the corresponding value,\r
+               /// else add an entry with the key and the supplied value.\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">On entry the value to add if the key is not found.\r
+               /// On exit the value found if any.</param>\r
+               /// <returns>True if key was found</returns>\r
+               bool FindOrAdd(K key, ref V val);   //mixture\r
+\r
+\r
+               /// <summary>\r
+               /// Update value in dictionary corresponding to key if found, else add new entry.\r
+               /// More general than "this[key] = val;" by reporting if key was found.\r
+               /// </summary>\r
+               /// <param name="key">The key to look for</param>\r
+               /// <param name="val">The value to add or replace with.</param>\r
+               /// <returns>True if key was found and value updated.</returns>\r
+               bool UpdateOrAdd(K key, V val);     \r
+\r
+\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this dictionary.\r
+               /// Only avaliable in DEBUG builds???\r
+               /// </summary>\r
+               /// <returns>True if check does not fail.</returns>\r
+               bool Check();\r
+       }\r
+\r
+\r
+\r
+       /// <summary>\r
+       /// A dictionary with sorted keys.\r
+       /// </summary>\r
+       public interface ISortedDictionary<K,V>: IDictionary<K,V>\r
+       {\r
+               /// <summary>\r
+               /// Find the entry with the largest key less than a given key.\r
+               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
+               /// </summary>\r
+               /// <param name="key">The key to compare to</param>\r
+               /// <returns>The entry</returns>\r
+               KeyValuePair<K,V> Predecessor(K key);\r
+\r
+\r
+               /// <summary>\r
+               /// Find the entry with the least key greater than a given key.\r
+               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
+               /// </summary>\r
+               /// <param name="key">The key to compare to</param>\r
+               /// <returns>The entry</returns>\r
+               KeyValuePair<K,V> Successor(K key);\r
+\r
+\r
+               /// <summary>\r
+               /// Find the entry with the largest key less than or equal to a given key.\r
+               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
+               /// </summary>\r
+               /// <param name="key">The key to compare to</param>\r
+               /// <returns>The entry</returns>\r
+               KeyValuePair<K,V> WeakPredecessor(K key);\r
+\r
+\r
+               /// <summary>\r
+               /// Find the entry with the least key greater than or equal to a given key.\r
+               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
+               /// </summary>\r
+               /// <param name="key">The key to compare to</param>\r
+               /// <returns>The entry</returns>\r
+               KeyValuePair<K,V> WeakSuccessor(K key);\r
+       }\r
+\r
+\r
+\r
+       /*******************************************************************/\r
+       /// <summary>\r
+       /// The type of an item comparer\r
+       /// <p>Implementations of this interface must asure that the method is self-consistent\r
+       /// and defines a sorting order on items, or state precise conditions under which this is true.</p>\r
+       /// <p>Implementations <b>must</b> assure that repeated calls of\r
+       /// the method to the same (in reference or binary identity sense) arguments \r
+       /// will return values with the same sign (-1, 0 or +1), or state precise conditions\r
+       /// under which the user \r
+       /// can be assured repeated calls will return the same sign.</p>\r
+       /// <p>Implementations of this interface must always return values from the method\r
+       /// and never throw exceptions.</p>\r
+       /// <p>This interface is identical to System.Collections.Generic.IComparer&lt;T&gt;</p>\r
+       /// </summary>\r
+       public interface IComparer<T>\r
+       {\r
+               /// <summary>\r
+               /// Compare two items with respect to this item comparer\r
+               /// </summary>\r
+               /// <param name="a">First item</param>\r
+               /// <param name="b">Second item</param>\r
+               /// <returns>Positive if a is greater than b, 0 if they are equal, negative if a is less than b</returns>\r
+               int Compare(T a, T b);\r
+       }\r
+\r
+\r
+    /*\r
+       /// <summary>\r
+       /// The interface for an item that is generic comparable.\r
+       /// <p>Implementations of this interface <b>must</b> assure that repeated calls of\r
+       /// the method to the same (in reference or binary identity sense) object and argument\r
+       /// will return values with the same sign (-1, 0 or +1), or state precise conditions\r
+       /// under which the user \r
+       /// can be assured repeated calls will return the same sign.</p>\r
+       /// <p>Implementations of this interface must always return values from the method\r
+       /// and never throw exceptions.</p>\r
+       /// <p>This interface is identical to System.Collections.Generic.IComparable&lt;T&gt;</p>\r
+       /// </summary>\r
+       public interface unIComparable<T> //: System.IComparable<T>\r
+       {\r
+               /// <summary>\r
+               /// Compare this item to another one\r
+               /// </summary>\r
+               /// <param name="that">The other item</param>\r
+               /// <returns>Positive if this is greater than , 0 if equal to, negative if less than that</returns>\r
+               int CompareTo(T that);\r
+       }\r
+    */\r
+\r
+\r
+       /// <summary>\r
+       /// The type of an item hasher. \r
+       /// <p>Implementations of this interface <b>must</b> assure that the methods are \r
+       /// consistent, i.e. that whenever two items i1 and i2 satisfies that Equals(i1,i2)\r
+       /// returns true, then GetHashCode returns the same values for i1 and i2.</p>\r
+       /// <p>Implementations of this interface <b>must</b> assure that repeated calls of\r
+       /// the methods to the same (in reference or binary identity sense) arguments \r
+       /// will return the same values, or state precise conditions under which the user \r
+       /// can be assured repeated calls will return the same values.</p>\r
+       /// <p>Implementations of this interface must always return values from the methods\r
+       /// and never throw exceptions.</p>\r
+       /// <p>This interface is similar in function to System.IKeyComparer&lt;T&gt;</p>\r
+       /// </summary>\r
+       public interface IHasher<T>\r
+       {\r
+               /// <summary>\r
+               /// Get the hash code with respect to this item hasher\r
+               /// </summary>\r
+               /// <param name="item">The item</param>\r
+               /// <returns>The hash code</returns>\r
+               int GetHashCode(T item);\r
+\r
+\r
+               /// <summary>\r
+               /// Check if two items are equal with respect to this item hasher\r
+               /// </summary>\r
+               /// <param name="i1">first item</param>\r
+               /// <param name="i2">second item</param>\r
+               /// <returns>True if equal</returns>\r
+               bool Equals(T i1, T i2);\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/Wrappers.cs b/mcs/class/Mono.C5/C5/Wrappers.cs
new file mode 100644 (file)
index 0000000..fed4fa7
--- /dev/null
@@ -0,0 +1,1594 @@
+#if NET_2_0
+/*
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using MSG = System.Collections.Generic;
+using SC = System.Collections;
+namespace C5
+{
+       /// <summary>
+       /// A read-only wrapper class for a generic enumerator
+       /// </summary>
+       public class GuardedEnumerator<T>: MSG.IEnumerator<T>
+       {
+               #region Fields
+
+               MSG.IEnumerator<T> enumerator;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Create a wrapper around a generic enumerator
+               /// </summary>
+               /// <param name="enumerator">The enumerator to wrap</param>
+               public GuardedEnumerator(MSG.IEnumerator<T> enumerator)
+               { this.enumerator = enumerator; }
+
+               #endregion
+
+               #region IEnumerator<T> Members
+
+               /// <summary>
+               /// Move wrapped enumerator to next item, or the first item if
+               /// this is the first call to MoveNext. 
+               /// </summary>
+               /// <returns>True if enumerator is valid now</returns>
+               public bool MoveNext() { return enumerator.MoveNext(); }
+
+
+               /// <summary>
+               /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+               /// </summary>
+               /// <value>The current item of the wrapped enumerator.</value>
+               public T Current { get { return enumerator.Current; } }
+
+               void SC.IEnumerator.Reset ()
+               {
+                       enumerator.Reset ();
+               }
+
+               object SC.IEnumerator.Current {
+                       get { return enumerator.Current; }
+               }
+
+               #endregion
+
+               #region IDisposable Members
+
+               /// <summary>
+               /// Dispose wrapped enumerator
+               /// </summary>
+               public void Dispose() { enumerator.Dispose(); }
+
+               #endregion
+       }
+
+
+
+       /// <summary>
+       /// A read-only wrapper class for a generic enumerable
+       ///
+       /// <p>This is mainly interesting as a base of other guard classes</p>
+       /// </summary>
+       public class GuardedEnumerable<T>: MSG.IEnumerable<T>
+       {
+               #region Fields
+
+               MSG.IEnumerable<T> enumerable;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap an enumerable in a read-only wrapper
+               /// </summary>
+               /// <param name="enumerable">The enumerable to wrap</param>
+               public GuardedEnumerable(MSG.IEnumerable<T> enumerable)
+               { this.enumerable = enumerable; }
+
+               #endregion
+
+               #region MSG.IEnumerable<T> Members
+
+               /// <summary>
+               /// Get an enumerator from the wrapped enumerable
+               /// </summary>
+               /// <returns>The enumerator (itself wrapped)</returns>
+               public MSG.IEnumerator<T> GetEnumerator()
+               { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
+
+               #endregion
+
+               SC.IEnumerator SC.IEnumerable.GetEnumerator()
+               { return GetEnumerator (); }
+       }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for a generic directed enumerable
+       ///
+       /// <p>This is mainly interesting as a base of other guard classes</p>
+       /// </summary>
+       public class GuardedDirectedEnumerable<T>: GuardedEnumerable<T>, IDirectedEnumerable<T>
+       {
+               #region Fields
+
+               IDirectedEnumerable<T> directedenumerable;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a directed enumerable in a read-only wrapper
+               /// </summary>
+               /// <param name="directedenumerable">the collection to wrap</param>
+               public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
+                       : base(directedenumerable)
+               { this.directedenumerable = directedenumerable; }
+
+               #endregion
+
+               #region IDirectedEnumerable<T> Members
+
+               /// <summary>
+               /// Get a enumerable that enumerates the wrapped collection in the opposite direction
+               /// </summary>
+               /// <returns>The mirrored enumerable</returns>
+               public IDirectedEnumerable<T> Backwards()
+               { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
+
+
+               /// <summary>
+               /// <code>Forwards</code> if same, else <code>Backwards</code>
+               /// </summary>
+               /// <value>The enumeration direction relative to the original collection.</value>
+               public EnumerationDirection Direction
+               { get { return directedenumerable.Direction; } }
+
+               #endregion
+       }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for an ICollectionValue&lt;T&gt;
+       ///
+       /// <p>This is mainly interesting as a base of other guard classes</p>
+       /// </summary>
+       public class GuardedCollectionValue<T>: GuardedEnumerable<T>, ICollectionValue<T>
+       {
+               #region Fields
+
+               ICollectionValue<T> collection;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper
+               /// </summary>
+               /// <param name="collection">the collection to wrap</param>
+               public GuardedCollectionValue(ICollectionValue<T> collection) : base(collection)
+               { this.collection = collection; }
+
+               #endregion
+
+               #region ICollection<T> Members
+
+               /// <summary>
+               /// Get the size of the wrapped collection
+               /// </summary>
+               /// <value>The size</value>
+               public int Count { get { return collection.Count; } }
+
+        /// <summary>
+        /// The value is symbolic indicating the type of asymptotic complexity
+        /// in terms of the size of this collection (worst-case or amortized as
+        /// relevant).
+        /// </summary>
+        /// <value>A characterization of the speed of the 
+        /// <code>Count</code> property in this collection.</value>
+        public Speed CountSpeed { get { return collection.CountSpeed; } }
+
+        /// <summary>
+               /// Copy the items of the wrapped collection to an array
+               /// </summary>
+               /// <param name="a">The array</param>
+               /// <param name="i">Starting offset</param>
+               public void CopyTo(T[] a, int i) { collection.CopyTo(a, i); }
+
+        /// <summary>
+        /// Create an array from the items of the wrapped collection
+        /// </summary>
+        /// <returns>The array</returns>
+        public T[] ToArray() { return collection.ToArray(); }
+
+        /// <summary>
+        /// Apply a delegate to all items of the wrapped enumerable.
+        /// </summary>
+        /// <param name="a">The delegate to apply</param>
+        //TODO: change this to throw an exception?
+        public void Apply(Applier<T> a) { collection.Apply(a); }
+
+
+        /// <summary>
+        /// Check if there exists an item  that satisfies a
+        /// specific predicate in the wrapped enumerable.
+        /// </summary>
+        /// <param name="filter">A filter delegate 
+        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
+        /// <returns>True is such an item exists</returns>
+        public bool Exists(Filter<T> filter) { return collection.Exists(filter); }
+
+
+        /// <summary>
+        /// Check if all items in the wrapped enumerable satisfies a specific predicate.
+        /// </summary>
+        /// <param name="filter">A filter delegate 
+        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
+        /// <returns>True if all items satisfies the predicate</returns>
+        public bool All(Filter<T> filter) { return collection.All(filter); }
+        #endregion
+    }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for a directed collection
+       ///
+       /// <p>This is mainly interesting as a base of other guard classes</p>
+       /// </summary>
+       public class GuardedDirectedCollectionValue<T>: GuardedCollectionValue<T>, IDirectedCollectionValue<T>
+       {
+               #region Fields
+
+               IDirectedCollectionValue<T> directedcollection;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a directed collection in a read-only wrapper
+               /// </summary>
+               /// <param name="directedcollection">the collection to wrap</param>
+               public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection) : 
+                       base(directedcollection)
+               { this.directedcollection = directedcollection; }
+
+               #endregion
+
+               #region IDirectedCollection<T> Members
+
+               /// <summary>
+               /// Get a collection that enumerates the wrapped collection in the opposite direction
+               /// </summary>
+               /// <returns>The mirrored collection</returns>
+               public IDirectedCollectionValue<T> Backwards()
+               { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
+
+               #endregion
+
+               #region IDirectedEnumerable<T> Members
+
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+               { return Backwards(); }
+
+
+               /// <summary>
+               /// <code>Forwards</code> if same, else <code>Backwards</code>
+               /// </summary>
+               /// <value>The enumeration direction relative to the original collection.</value>
+               public EnumerationDirection Direction
+               { get { return directedcollection.Direction; } }
+
+               #endregion
+       }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for an ICollection&lt;T&gt;.
+       /// <see cref="T:C5.ICollection!1"/>
+       ///
+       /// <p>Suitable for wrapping hash tables, <see cref="T:C5.HashSet!1"/>
+       /// and <see cref="T:C5.HashBag!1"/>  </p>
+       /// </summary>
+       public class GuardedCollection<T>: GuardedCollectionValue<T>, ICollection<T>
+       {
+               #region Fields
+
+               ICollection<T> collection;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap an ICollection&lt;T&gt; in a read-only wrapper
+               /// </summary>
+               /// <param name="collection">the collection to wrap</param>
+               public GuardedCollection(ICollection<T> collection)
+                       :base(collection)
+               { this.collection = collection; }
+
+               #endregion
+
+               #region ICollection<T> Members
+
+               /// <summary>
+               /// (This is a read-only wrapper)
+               /// </summary>
+               /// <value>True</value>
+               public bool IsReadOnly { get { return true; } }
+
+
+               /// <summary> </summary>
+               /// <value>Speed of wrapped collection</value>
+               public Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
+
+
+               int ICollection<T>.GetHashCode()
+               { return ((ICollection<T>)collection).GetHashCode(); }
+
+
+               bool ICollection<T>.Equals(ICollection<T> that)
+               { return ((ICollection<T>)collection).Equals(that); }
+
+
+               /// <summary>
+               /// Check if an item is in the wrapped collection
+               /// </summary>
+               /// <param name="item">The item</param>
+               /// <returns>True if found</returns>
+               public bool Contains(T item) { return collection.Contains(item); }
+
+
+               /// <summary>
+               /// Count the number of times an item appears in the wrapped collection
+               /// </summary>
+               /// <param name="item">The item</param>
+               /// <returns>The number of copies</returns>
+               public int ContainsCount(T item) { return collection.ContainsCount(item); }
+
+
+               /// <summary>
+               /// Check if all items in the argument is in the wrapped collection
+               /// </summary>
+               /// <param name="items">The items</param>
+               /// <returns>True if so</returns>
+               public bool ContainsAll(MSG.IEnumerable<T> items) { return collection.ContainsAll(items); }
+
+
+               /// <summary>
+               /// Search for an item in the wrapped collection
+               /// </summary>
+               /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
+               /// <returns></returns>
+               public bool Find(ref T item) { return collection.Find(ref item); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public bool FindOrAdd(ref T item)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public bool Update(T item)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public bool UpdateOrAdd(T item)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public bool Remove(T item)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public bool RemoveWithReturn(ref T item)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               public void RemoveAllCopies(T item)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="items"></param>
+               public void RemoveAll(MSG.IEnumerable<T> items)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               public void Clear()
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="items"></param>
+               public void RetainAll(MSG.IEnumerable<T> items)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// Check  wrapped collection for internal consistency
+               /// </summary>
+               /// <returns>True if check passed</returns>
+               public bool Check() { return collection.Check(); }
+
+               #endregion
+
+               #region ISink<T> Members
+
+               /// <summary> </summary>
+               /// <value>False if wrapped collection has set semantics</value>
+        public bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
+
+
+        /// <summary> </summary>
+               /// <value>The sync root of the wrapped collection</value>
+               public object SyncRoot { get { return collection.SyncRoot; } }
+
+
+               /// <summary> </summary>
+               /// <value>True if wrapped collection is empty</value>
+               public bool IsEmpty { get { return collection.IsEmpty; } }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public bool Add(T item)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+        /// <summary>
+        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+        /// </summary>
+        /// <param name="items"></param>
+        public void AddAll(MSG.IEnumerable<T> items)
+        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+        /// </summary>
+        /// <param name="items"></param>
+        /*public*/ void C5.IExtensible<T>.AddAll<U>(MSG.IEnumerable<U> items) //where U : T
+        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+        #endregion
+    }
+
+
+       /// <summary>
+       /// A read-only wrapper for a sequenced collection
+       ///
+       /// <p>This is mainly interesting as a base of other guard classes</p>
+       /// </summary>
+       public class GuardedSequenced<T>: GuardedCollection<T>, ISequenced<T>
+       {
+               #region Fields
+
+               ISequenced<T> sequenced;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a sequenced collection in a read-only wrapper
+               /// </summary>
+               /// <param name="sorted"></param>
+               public GuardedSequenced(ISequenced<T> sorted):base(sorted) { this.sequenced = sorted; }
+
+               #endregion
+
+               #region ISequenced<T> Members
+
+               int ISequenced<T>.GetHashCode()
+               { return ((ISequenced<T>)sequenced).GetHashCode(); }
+
+
+               bool ISequenced<T>.Equals(ISequenced<T> that)
+               { return ((ISequenced<T>)sequenced).Equals(that); }
+
+               #endregion
+
+               #region IEditableCollection<T> Members
+
+               int ICollection<T>.GetHashCode()
+               { return ((ICollection<T>)sequenced).GetHashCode(); }
+
+
+               bool ICollection<T>.Equals(ICollection<T> that)
+               { return ((ICollection<T>)sequenced).Equals(that); }
+
+               #endregion
+
+               #region IDirectedCollection<T> Members
+
+               /// <summary>
+               /// Get a collection that enumerates the wrapped collection in the opposite direction
+               /// </summary>
+               /// <returns>The mirrored collection</returns>
+               public IDirectedCollectionValue<T> Backwards()
+               { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
+
+               #endregion
+
+               #region IDirectedEnumerable<T> Members
+
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+               { return Backwards(); }
+
+
+
+               /// <summary>
+               /// <code>Forwards</code> if same, else <code>Backwards</code>
+               /// </summary>
+               /// <value>The enumeration direction relative to the original collection.</value>
+               public EnumerationDirection Direction
+               { get { return EnumerationDirection.Forwards; } }
+
+               #endregion
+       }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for a sorted collection
+       ///
+       /// <p>This is mainly interesting as a base of other guard classes</p>
+       /// </summary>
+       public class GuardedSorted<T>: GuardedSequenced<T>, ISorted<T>
+       {
+               #region Fields
+
+               ISorted<T> sorted;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a sorted collection in a read-only wrapper
+               /// </summary>
+               /// <param name="sorted"></param>
+               public GuardedSorted(ISorted<T> sorted):base(sorted) { this.sorted = sorted; }
+
+               #endregion
+
+        #region IEditableCollection Members
+
+               int ICollection<T>.GetHashCode()
+               { return ((ICollection<T>)sorted).GetHashCode(); }
+
+
+               bool ICollection<T>.Equals(ICollection<T> that)
+               { return ((ICollection<T>)sorted).Equals(that); }
+
+               #endregion
+
+               #region ISequenced<T> Members
+
+               int ISequenced<T>.GetHashCode()
+               { return ((ISequenced<T>)sorted).GetHashCode(); }
+
+
+               bool ISequenced<T>.Equals(ISequenced<T> that)
+               { return ((ISequenced<T>)sorted).Equals(that); }
+
+
+               #endregion
+
+               #region ISorted<T> Members
+
+               /// <summary>
+               /// Find the predecessor of the item in the wrapped sorted collection
+               /// </summary>
+               /// <param name="item">The item</param>
+               /// <returns>The predecessor</returns>
+               public T Predecessor(T item) { return sorted.Predecessor(item); }
+
+
+               /// <summary>
+               /// Find the Successor of the item in the wrapped sorted collection
+               /// </summary>
+               /// <param name="item">The item</param>
+               /// <returns>The Successor</returns>
+               public T Successor(T item) { return sorted.Successor(item); }
+
+
+               /// <summary>
+               /// Find the weak predecessor of the item in the wrapped sorted collection
+               /// </summary>
+               /// <param name="item">The item</param>
+               /// <returns>The weak predecessor</returns>
+               public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
+
+
+               /// <summary>
+               /// Find the weak Successor of the item in the wrapped sorted collection
+               /// </summary>
+               /// <param name="item">The item</param>
+               /// <returns>The weak Successor</returns>
+               public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
+
+
+               /// <summary>
+               /// Run Cut on the wrapped sorted collection
+               /// </summary>
+               /// <param name="c"></param>
+               /// <param name="low"></param>
+               /// <param name="lval"></param>
+               /// <param name="high"></param>
+               /// <param name="hval"></param>
+               /// <returns></returns>
+               public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
+               { return sorted.Cut(c, out low, out lval, out high, out hval); }
+
+
+               /// <summary>
+               /// Get the specified range from the wrapped collection. 
+               /// (The current implementation erroneously does not wrap the result.)
+               /// </summary>
+               /// <param name="bot"></param>
+               /// <returns></returns>
+               public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
+
+
+               /// <summary>
+               /// Get the specified range from the wrapped collection. 
+               /// (The current implementation erroneously does not wrap the result.)
+               /// </summary>
+               /// <param name="bot"></param>
+               /// <param name="top"></param>
+               /// <returns></returns>
+               public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
+               { return sorted.RangeFromTo(bot, top); }
+
+
+               /// <summary>
+               /// Get the specified range from the wrapped collection. 
+               /// (The current implementation erroneously does not wrap the result.)
+               /// </summary>
+               /// <param name="top"></param>
+               /// <returns></returns>
+               public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
+
+
+               /// <summary>
+               /// Get the specified range from the wrapped collection. 
+               /// (The current implementation erroneously does not wrap the result.)
+               /// </summary>
+               /// <returns></returns>
+               public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="items"></param>
+               public void AddSorted(MSG.IEnumerable<T> items)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="low"></param>
+               public void RemoveRangeFrom(T low)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="low"></param>
+               /// <param name="hi"></param>
+               public void RemoveRangeFromTo(T low, T hi)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="hi"></param>
+               public void RemoveRangeTo(T hi)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+               #endregion
+
+               #region IPriorityQueue<T> Members
+
+               /// <summary>
+               /// Find the minimum of the wrapped collection
+               /// </summary>
+               /// <returns>The minimum</returns>
+               public T FindMin() { return sorted.FindMin(); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <returns></returns>
+               public T DeleteMin()
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// Find the maximum of the wrapped collection
+               /// </summary>
+               /// <returns>The maximum</returns>
+               public T FindMax() { return sorted.FindMax(); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <returns></returns>
+               public T DeleteMax()
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// The comparer object supplied at creation time for the underlying collection
+        /// </summary>
+        /// <value>The comparer</value>
+        public IComparer<T> Comparer { get { return sorted.Comparer; } }
+        #endregion
+
+
+               #region IDirectedEnumerable<T> Members
+
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+               { return Backwards(); }
+
+               #endregion
+       }
+
+
+
+       /// <summary>
+       /// Read-only wrapper for indexed sorted collections
+       ///
+       /// <p>Suitable for wrapping TreeSet, TreeBag and SortedArray</p>
+       /// </summary>
+       public class GuardedIndexedSorted<T>: GuardedSorted<T>, IIndexedSorted<T>
+       {
+               #region Fields
+
+               IIndexedSorted<T> indexedsorted;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap an indexed sorted collection in a read-only wrapper
+               /// </summary>
+               /// <param name="list">the indexed sorted collection</param>
+               public GuardedIndexedSorted(IIndexedSorted<T> list):base(list)
+               { this.indexedsorted = list; }
+
+               #endregion
+
+               #region IIndexedSorted<T> Members
+
+               /// <summary>
+               /// Get the specified range from the wrapped collection. 
+               /// (The current implementation erroneously does not wrap the result.)
+               /// </summary>
+               /// <param name="bot"></param>
+               /// <returns></returns>
+               public new IDirectedCollectionValue<T> RangeFrom(T bot)
+               { return indexedsorted.RangeFrom(bot); }
+
+
+               /// <summary>
+               /// Get the specified range from the wrapped collection. 
+               /// (The current implementation erroneously does not wrap the result.)
+               /// </summary>
+               /// <param name="bot"></param>
+               /// <param name="top"></param>
+               /// <returns></returns>
+               public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
+               { return indexedsorted.RangeFromTo(bot, top); }
+
+
+               /// <summary>
+               /// Get the specified range from the wrapped collection. 
+               /// (The current implementation erroneously does not wrap the result.)
+               /// </summary>
+               /// <param name="top"></param>
+               /// <returns></returns>
+               public new IDirectedCollectionValue<T> RangeTo(T top)
+               { return indexedsorted.RangeTo(top); }
+
+
+               /// <summary>
+               /// Report the number of items in the specified range of the wrapped collection
+               /// </summary>
+               /// <param name="bot"></param>
+               /// <returns></returns>
+               public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
+
+
+               /// <summary>
+               /// Report the number of items in the specified range of the wrapped collection
+               /// </summary>
+               /// <param name="bot"></param>
+               /// <param name="top"></param>
+               /// <returns></returns>
+               public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
+
+
+               /// <summary>
+               /// Report the number of items in the specified range of the wrapped collection
+               /// </summary>
+               /// <param name="top"></param>
+               /// <returns></returns>
+               public int CountTo(T top) { return indexedsorted.CountTo(top); }
+
+
+               /// <summary>
+               /// Run FindAll on the wrapped collection with the indicated filter.
+               /// The result will <b>not</b> be read-only.
+               /// </summary>
+               /// <param name="f"></param>
+               /// <returns></returns>
+               public IIndexedSorted<T> FindAll(Filter<T> f)
+               { return indexedsorted.FindAll(f); }
+
+
+               /// <summary>
+               /// Run Map on the wrapped collection with the indicated mapper.
+               /// The result will <b>not</b> be read-only.
+               /// </summary>
+               /// <param name="m"></param>
+               /// <param name="c">The comparer to use in the result</param>
+               /// <returns></returns>
+               public IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c)
+               { return indexedsorted.Map<V>(m, c); }
+
+               #endregion
+
+               #region IIndexed<T> Members
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <value>The i'th item of the wrapped sorted collection</value>
+               public T this[int i] { get { return indexedsorted[i]; } }
+
+
+               /// <summary> </summary>
+               /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
+               public IDirectedCollectionValue<T> this[int start, int end]
+               { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
+
+
+               /// <summary>
+               /// Find the (first) index of an item in the wrapped collection
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
+
+
+               /// <summary>
+               /// Find the last index of an item in the wrapped collection
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="i"></param>
+               /// <returns></returns>
+               public T RemoveAt(int i)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="start"></param>
+               /// <param name="count"></param>
+               public void RemoveInterval(int start, int count)
+               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+               #endregion
+
+               #region ISequenced<T> Members
+
+               int ISequenced<T>.GetHashCode()
+               { return ((ISequenced<T>)indexedsorted).GetHashCode(); }
+
+
+               bool ISequenced<T>.Equals(ISequenced<T> that)
+               { return ((ISequenced<T>)indexedsorted).Equals(that); }
+
+               #endregion
+
+               #region IEditableCollection<T> Members
+
+               int ICollection<T>.GetHashCode()
+               { return ((ICollection<T>)indexedsorted).GetHashCode(); }
+
+
+               bool ICollection<T>.Equals(ICollection<T> that)
+               { return ((ICollection<T>)indexedsorted).Equals(that); }
+
+               #endregion
+
+               #region IDirectedEnumerable<T> Members
+
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+               { return Backwards(); }
+
+               #endregion
+       }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for a generic list collection
+       /// <p>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
+       /// <see cref="T:C5.LinkedList!1"/>, 
+       /// <see cref="T:C5.HashedLinkedList!1"/>, 
+       /// <see cref="T:C5.ArrayList!1"/> or
+       /// <see cref="T:C5.HashedArray!1"/>.
+       /// </p>
+       /// </summary>
+       public class GuardedList<T>: GuardedSequenced<T>, IList<T>
+       {
+               #region Fields
+
+               IList<T> list;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a list in a read-only wrapper
+               /// </summary>
+               /// <param name="list">The list</param>
+               public GuardedList(IList<T> list) : base (list) { this.list = list; }
+
+               #endregion
+
+               #region IList<T> Members
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <value>The first item of the wrapped list</value>
+               public T First { get { return list.First; } }
+
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <value>The last item of the wrapped list</value>
+               public T Last { get { return list.Last; } }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> if used as setter
+               /// </summary>
+               /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
+               public bool FIFO
+               {
+                       get { return list.FIFO; }
+                       set { throw new InvalidOperationException("List is read only"); }
+               }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> if used as setter
+               /// </summary>
+               /// <value>The i'th item of the wrapped list</value>
+               public T this[int i]
+               {
+                       get { return list[i]; }
+                       set { throw new InvalidOperationException("List is read only"); }
+               }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="i"></param>
+               /// <param name="item"></param>
+               public void Insert(int i, T item)
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               public void InsertFirst(T item)
+               { throw new InvalidOperationException("List is read only"); }
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               public void InsertLast(T item)
+               { throw new InvalidOperationException("List is read only"); }
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <param name="target"></param>
+               public void InsertBefore(T item, T target)
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="item"></param>
+               /// <param name="target"></param>
+               public void InsertAfter(T item, T target)
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="i"></param>
+               /// <param name="items"></param>
+               public void InsertAll(int i, MSG.IEnumerable<T> items)
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
+               /// </summary>
+               /// <param name="filter">The filter to use</param>
+               /// <returns></returns>
+               public IList<T> FindAll(Filter<T> filter) { return list.FindAll(filter); }
+
+
+               /// <summary>
+               /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
+               /// </summary>
+        /// <typeparam name="V">The type of items of the new list</typeparam>
+        /// <param name="mapper">The mapper to use.</param>
+        /// <returns>The mapped list</returns>
+        public IList<V> Map<V>(Mapper<T, V> mapper) { return list.Map<V>(mapper); }
+
+        /// <summary>
+        /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
+        /// </summary>
+        /// <typeparam name="V">The type of items of the new list</typeparam>
+        /// <param name="mapper">The delegate defining the map.</param>
+        /// <param name="hasher">The hasher to use for the new list</param>
+        /// <returns>The new list.</returns>
+        public IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher) { return list.Map<V>(mapper, hasher); }
+
+        /// <summary>
+        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <returns></returns>
+               public T Remove() { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <returns></returns>
+               public T RemoveFirst() { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <returns></returns>
+               public T RemoveLast() { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// Create the indicated view on the wrapped list and wrap it read-only.
+               /// </summary>
+               /// <param name="start"></param>
+               /// <param name="count"></param>
+               /// <returns></returns>
+               public IList<T> View(int start, int count)
+               {
+                       return new GuardedList<T>(list.View(start, count));
+               }
+
+
+               //TODO: This is wrong!
+               /// <summary>
+               /// (This is wrong functionality)
+               /// </summary>
+        /// <value>The wrapped underlying list of the wrapped view </value>
+        public IList<T> Underlying { get { return new GuardedList<T>(list.Underlying); } }
+
+
+        /// <summary>
+               /// 
+               /// </summary>
+               /// <value>The offset of the wrapped list as a view.</value>
+               public int Offset { get { return list.Offset; } }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="offset"></param>
+               public void Slide(int offset) { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="offset"></param>
+               /// <param name="size"></param>
+               public void Slide(int offset, int size) { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               public void Reverse() { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="start"></param>
+               /// <param name="count"></param>
+               public void Reverse(int start, int count)
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// Check if wrapped list is sorted
+               /// </summary>
+               /// <param name="c">The sorting order to use</param>
+               /// <returns>True if sorted</returns>
+               public bool IsSorted(IComparer<T> c) { return list.IsSorted(c); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="c"></param>
+               public void Sort(IComparer<T> c)
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               public void Shuffle()
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="rnd"></param>
+               public void Shuffle(Random rnd)
+               { throw new InvalidOperationException("List is read only"); }
+
+               #endregion
+
+               #region IIndexed<T> Members
+
+               /// <summary> </summary>
+               /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
+               public IDirectedCollectionValue<T> this[int start, int end]
+               { get { return new GuardedDirectedCollectionValue<T>(list[start, end]); } }
+
+
+               /// <summary>
+               /// Find the (first) index of an item in the wrapped collection
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public int IndexOf(T item) { return list.IndexOf(item); }
+
+
+               /// <summary>
+               /// Find the last index of an item in the wrapped collection
+               /// </summary>
+               /// <param name="item"></param>
+               /// <returns></returns>
+               public int LastIndexOf(T item) { return list.LastIndexOf(item); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="i"></param>
+               /// <returns></returns>
+               public T RemoveAt(int i)
+               { throw new InvalidOperationException("List is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="start"></param>
+               /// <param name="count"></param>
+               public void RemoveInterval(int start, int count)
+               { throw new InvalidOperationException("List is read only"); }
+
+               #endregion
+
+               #region ISequenced<T> Members
+
+               int ISequenced<T>.GetHashCode()
+               { return ((ISequenced<T>)list).GetHashCode(); }
+
+
+               bool ISequenced<T>.Equals(ISequenced<T> that)
+               { return ((ISequenced<T>)list).Equals(that); }
+
+               #endregion
+
+               #region IEditableCollection<T> Members
+
+               int ICollection<T>.GetHashCode()
+               { return ((ICollection<T>)list).GetHashCode(); }
+
+
+               bool ICollection<T>.Equals(ICollection<T> that)
+               { return ((ICollection<T>)list).Equals(that); }
+
+               #endregion
+
+               #region IDirectedEnumerable<T> Members
+
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+               { return Backwards(); }
+
+               #endregion
+
+        #region IStack<T> Members
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+        /// <returns>-</returns>
+        public void Push(T item)
+        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+        /// <returns>-</returns>
+        public T Pop()
+        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+                #endregion
+
+        #region IQueue<T> Members
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+        /// <returns>-</returns>
+        public void EnQueue(T item)
+        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+        /// <returns>-</returns>
+        public T DeQueue()
+        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
+
+                #endregion
+
+    }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for a dictionary.
+       ///
+       /// <p>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary!2"/></p>
+       /// </summary>
+       public class GuardedDictionary<K,V>: GuardedEnumerable<KeyValuePair<K,V>>, IDictionary<K,V>
+       {
+               #region Fields
+
+               IDictionary<K,V> dict;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a dictionary in a read-only wrapper
+               /// </summary>
+               /// <param name="dict">the dictionary</param>
+               public GuardedDictionary(IDictionary<K,V> dict) : base(dict) { this.dict = dict; }
+
+               #endregion
+
+               #region IDictionary<K,V> Members
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a
+               /// read-only wrappper if used as a setter
+               /// </summary>
+               /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
+               public V this[K key]
+               {
+                       get { return dict[key]; }
+                       set { throw new InvalidOperationException("Dictionary is read only"); }
+               }
+
+
+               /// <summary> </summary>
+               /// <value>The size of the wrapped dictionary</value>
+               public int Count { get { return dict.Count; } }
+
+
+               /// <summary>
+               /// (This is a read-only wrapper)
+               /// </summary>
+               /// <value>True</value>
+               public bool IsReadOnly { get { return true; } }
+
+
+               /// <summary> </summary>
+               /// <value>The sync root of the wrapped dictionary</value>
+               public object SyncRoot { get { return dict.SyncRoot; } }
+
+
+               //TODO: guard with a read-only wrapper? Probably so!
+               /// <summary> </summary>
+               /// <value>The collection of keys of the wrapped dictionary</value>
+               public ICollectionValue<K> Keys
+               { get { return dict.Keys; } }
+
+
+               /// <summary> </summary>
+               /// <value>The collection of values of the wrapped dictionary</value>
+               public ICollectionValue<V> Values { get { return dict.Values; } }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="key"></param>
+               /// <param name="val"></param>
+               public void Add(K key, V val)
+               { throw new InvalidOperationException("Dictionary is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="key"></param>
+               /// <returns></returns>
+               public bool Remove(K key)
+               { throw new InvalidOperationException("Dictionary is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="key"></param>
+               /// <param name="val"></param>
+               /// <returns></returns>
+               public bool Remove(K key, out V val)
+               { throw new InvalidOperationException("Dictionary is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               public void Clear()
+               { throw new InvalidOperationException("Dictionary is read only"); }
+
+
+               /// <summary>
+               /// Check if the wrapped dictionary contains a specific key
+               /// </summary>
+               /// <param name="key">The key</param>
+               /// <returns>True if it does</returns>
+               public bool Contains(K key) { return dict.Contains(key); }
+
+
+               /// <summary>
+               /// Search for a key in the wrapped dictionary, reporting the value if found
+               /// </summary>
+               /// <param name="key">The key</param>
+               /// <param name="val">On exit: the value if found</param>
+               /// <returns>True if found</returns>
+               public bool Find(K key, out V val) { return dict.Find(key, out val); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="key"></param>
+               /// <param name="val"></param>
+               /// <returns></returns>
+               public bool Update(K key, V val)
+               { throw new InvalidOperationException("Dictionary is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="key"></param>
+               /// <param name="val"></param>
+               /// <returns></returns>
+               public bool FindOrAdd(K key, ref V val)
+               { throw new InvalidOperationException("Dictionary is read only"); }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
+               /// </summary>
+               /// <param name="key"></param>
+               /// <param name="val"></param>
+               /// <returns></returns>
+               public bool UpdateOrAdd(K key, V val)
+               { throw new InvalidOperationException("Dictionary is read only"); }
+
+
+               /// <summary>
+               /// Check the internal consistency of the wrapped dictionary
+               /// </summary>
+               /// <returns>True if check passed</returns>
+               public bool Check() { return dict.Check(); }
+
+               #endregion
+       }
+
+
+
+       /// <summary>
+       /// A read-only wrapper for a sorted dictionary.
+       ///
+       /// <p>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary!2"/></p>
+       /// </summary>
+       public class GuardedSortedDictionary<K,V>: GuardedDictionary<K,V>, ISortedDictionary<K,V>
+       {
+               #region Fields
+
+               ISortedDictionary<K,V> sorteddict;
+
+               #endregion
+
+               #region Constructor
+
+               /// <summary>
+               /// Wrap a sorted dictionary in a read-only wrapper
+               /// </summary>
+               /// <param name="sorteddict">the dictionary</param>
+               public GuardedSortedDictionary(ISortedDictionary<K,V> sorteddict) :base(sorteddict)
+               { this.sorteddict = sorteddict; }
+
+               #endregion
+
+               #region ISortedDictionary<K,V> Members
+
+               /// <summary>
+               /// Get the entry in the wrapped dictionary whose key is the
+               /// predecessor of a specified key.
+               /// </summary>
+               /// <param name="key">The key</param>
+               /// <returns>The entry</returns>
+               public KeyValuePair<K,V> Predecessor(K key)
+               { return sorteddict.Predecessor(key); }
+
+
+               /// <summary>
+               /// Get the entry in the wrapped dictionary whose key is the
+               /// successor of a specified key.
+               /// </summary>
+               /// <param name="key">The key</param>
+               /// <returns>The entry</returns>
+               public KeyValuePair<K,V> Successor(K key)
+               { return sorteddict.Successor(key); }
+
+
+               /// <summary>
+               /// Get the entry in the wrapped dictionary whose key is the
+               /// weak predecessor of a specified key.
+               /// </summary>
+               /// <param name="key">The key</param>
+               /// <returns>The entry</returns>
+               public KeyValuePair<K,V> WeakPredecessor(K key)
+               { return sorteddict.WeakPredecessor(key); }
+
+
+               /// <summary>
+               /// Get the entry in the wrapped dictionary whose key is the
+               /// weak successor of a specified key.
+               /// </summary>
+               /// <param name="key">The key</param>
+               /// <returns>The entry</returns>
+               public KeyValuePair<K,V> WeakSuccessor(K key)
+               { return sorteddict.WeakSuccessor(key); }
+
+               #endregion
+       }
+
+}
+#endif
diff --git a/mcs/class/Mono.C5/C5/arrays/ArrayList.cs b/mcs/class/Mono.C5/C5/arrays/ArrayList.cs
new file mode 100644 (file)
index 0000000..cc7a050
--- /dev/null
@@ -0,0 +1,1298 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A list collection based on a plain dynamic array data structure.\r
+       /// Expansion of the internal array is performed by doubling on demand. \r
+       /// The internal array is only shrinked by the Clear method. \r
+       ///\r
+       /// <p>When the FIFO property is set to false this class works fine as a stack of T.\r
+       /// When the FIFO property is set to true the class will function as a (FIFO) queue\r
+       /// but very inefficiently, use a LinkedList (<see cref="T:C5.LinkedList!1"/>) instead.</p>\r
+       /// </summary>\r
+       public class ArrayList<T>: ArrayBase<T>, IList<T>\r
+       {\r
+               #region Fields\r
+\r
+               /// <summary>\r
+               /// The underlying list if we are a view, null else.\r
+               /// </summary>\r
+               protected ArrayList<T> underlying;\r
+\r
+               /// <summary>\r
+               /// The size of the underlying list.\r
+               /// </summary>\r
+               protected int underlyingsize;\r
+\r
+               /// <summary>\r
+               /// The underlying field of the FIFO property\r
+               /// </summary>\r
+               protected bool fIFO = true;\r
+\r
+               #endregion\r
+\r
+               #region Util\r
+\r
+               bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }\r
+\r
+\r
+               /// <summary>\r
+               /// Double the size of the internal array.\r
+               /// </summary>\r
+               protected override void expand()\r
+               { expand(2 * array.Length, underlyingsize); }\r
+\r
+\r
+               /// <summary>\r
+               /// Expand the internal array, resetting the index of the first unused element.\r
+               /// </summary>\r
+               /// <param name="newcapacity">The new capacity (will be rouded upwards to a power of 2).</param>\r
+               /// <param name="newsize">The new count of </param>\r
+               protected override void expand(int newcapacity, int newsize)\r
+               {\r
+                       base.expand(newcapacity, newsize);\r
+                       if (underlying != null)\r
+                               underlying.array = array;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if it is valid to perform updates and increment stamp.\r
+               /// <exception cref="InvalidOperationException"/> if check fails.\r
+               /// </summary>\r
+               protected override void updatecheck()\r
+               {\r
+                       modifycheck();\r
+                       base.updatecheck();\r
+                       if (underlying != null)\r
+                               underlying.stamp++;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if we are a view that the underlying list has only been updated through us.\r
+               /// <exception cref="InvalidOperationException"/> if check fails.\r
+               /// <br/>\r
+               /// This method should be called from enumerators etc to guard against \r
+               /// modification of the base collection.\r
+               /// </summary>\r
+               protected void modifycheck()\r
+               {\r
+                       if (underlying != null && stamp != underlying.stamp)\r
+                               throw new InvalidOperationException("underlying list was modified");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check that the list has not been updated since a particular time.\r
+               /// <exception cref="InvalidOperationException"/> if check fails.\r
+               /// </summary>\r
+               /// <param name="stamp">The stamp indicating the time.</param>\r
+               protected override void modifycheck(int stamp)\r
+               {\r
+                       modifycheck();\r
+                       if (this.stamp != stamp)\r
+                               throw new InvalidOperationException("Collection was modified");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Increment or decrement the private size fields\r
+               /// </summary>\r
+               /// <param name="delta">Increment (with sign)</param>\r
+               protected void addtosize(int delta)\r
+               {\r
+                       size += delta;\r
+                       underlyingsize += delta;\r
+                       if (underlying != null)\r
+                       {\r
+                               underlying.size += delta;\r
+                               underlying.underlyingsize += delta;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of IndexOf without modification checks.\r
+               /// </summary>\r
+               /// <param name="item">Item to look for</param>\r
+               /// <returns>The index of first occurrence</returns>\r
+               protected virtual int indexOf(T item)\r
+               {\r
+                       for (int i = 0; i < size; i++)\r
+                               if (equals(item, array[offset + i]))\r
+                                       return i;\r
+\r
+                       return -1;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of LastIndexOf without modification checks.\r
+               /// </summary>\r
+               /// <param name="item">Item to look for</param>\r
+               /// <returns>The index of last occurrence</returns>\r
+               protected virtual int lastIndexOf(T item)\r
+               {\r
+                       for (int i = size - 1; i >= 0; i--)\r
+                               if (equals(item, array[offset + i]))\r
+                                       return i;\r
+\r
+                       return -1;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of Insert with no modification checks.\r
+               /// </summary>\r
+               /// <param name="i">Index to insert at</param>\r
+               /// <param name="item">Item to insert</param>\r
+               protected override void insert(int i, T item)\r
+               {\r
+                       if (underlyingsize == array.Length)\r
+                               expand();\r
+\r
+                       i += offset;\r
+                       if (i < underlyingsize)\r
+                               Array.Copy(array, i, array, i + 1, underlyingsize - i);\r
+\r
+                       array[i] = item;\r
+                       addtosize(1);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of RemoveAt with no modification checks.\r
+               /// </summary>\r
+               /// <param name="i">Index to remove at</param>\r
+               /// <returns>The removed item</returns>\r
+               protected virtual T removeAt(int i)\r
+               {\r
+                       i += offset;\r
+\r
+                       T retval = array[i];\r
+\r
+                       addtosize(-1);\r
+                       if (underlyingsize > i)\r
+                               Array.Copy(array, i + 1, array, i, underlyingsize - i);\r
+\r
+                       array[underlyingsize] = default(T);\r
+                       return retval;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+               /// <summary>\r
+               /// Create an array list with default item hasher and initial capacity 8 items.\r
+               /// </summary>\r
+               public ArrayList() : this(8) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an array list with external item hasher and initial capacity 8 items.\r
+               /// </summary>\r
+               /// <param name="hasher">The external hasher</param>\r
+               public ArrayList(IHasher<T> hasher) : this(8,hasher) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an array list with default item hasher and prescribed initial capacity.\r
+               /// </summary>\r
+               /// <param name="capacity">The prescribed capacity</param>\r
+               public ArrayList(int capacity) : this(capacity,HasherBuilder.ByPrototype<T>.Examine()) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an array list with external item hasher and prescribed initial capacity.\r
+               /// </summary>\r
+               /// <param name="capacity">The prescribed capacity</param>\r
+               /// <param name="hasher">The external hasher</param>\r
+               public ArrayList(int capacity, IHasher<T> hasher) : base(capacity,hasher) { }\r
+\r
+               #endregion\r
+\r
+        #region IList<T> Members\r
+\r
+               /// <summary>\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <value>The first item in this list.</value>\r
+               [Tested]\r
+               public virtual T First\r
+               {\r
+                       [Tested]get\r
+                       {\r
+                               modifycheck();\r
+                               if (size == 0)\r
+                                       throw new InvalidOperationException("List is empty");\r
+\r
+                               return array[offset];\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <value>The last item in this list.</value>\r
+               [Tested]\r
+               public virtual T Last\r
+               {\r
+                       [Tested]get\r
+                       {\r
+                               modifycheck();\r
+                               if (size == 0)\r
+                                       throw new InvalidOperationException("List is empty");\r
+\r
+                               return array[offset + size - 1];\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Since <code>Add(T item)</code> always add at the end of the list,\r
+               /// this describes if list has FIFO or LIFO semantics.\r
+               /// </summary>\r
+               /// <value>True if the <code>Remove()</code> operation removes from the\r
+               /// start of the list, false if it removes from the end.</value>\r
+               [Tested]\r
+               public virtual bool FIFO\r
+               {\r
+                       [Tested]\r
+                       get { modifycheck(); return fIFO; }\r
+                       [Tested]\r
+                       set { updatecheck(); fIFO = value; }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// On this list, this indexer is read/write.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <value>The i'th item of this list.</value>\r
+               /// <param name="i">The index of the item to fetch or store.</param>\r
+               [Tested]\r
+               public virtual T this[int i]\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+                               modifycheck();\r
+                               if (i < 0 || i >= size)\r
+                                       throw new IndexOutOfRangeException();\r
+\r
+                               return array[offset + i];\r
+                       }\r
+                       [Tested]\r
+                       set\r
+                       {\r
+                               updatecheck();\r
+                               if (i < 0 || i >= size)\r
+                                       throw new IndexOutOfRangeException();\r
+\r
+                               array[offset + i] = value;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at a specific index location in this list. \r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt; the size of the collection.</summary>\r
+               /// <param name="i">The index at which to insert.</param>\r
+               /// <param name="item">The item to insert.</param>\r
+               [Tested]\r
+               public virtual void Insert(int i, T item)\r
+               {\r
+                       updatecheck();\r
+                       if (i < 0 || i > size)\r
+                               throw new IndexOutOfRangeException();\r
+\r
+                       insert(i, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert into this list all items from an enumerable collection starting \r
+               /// at a particular index.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt; the size of the collection.\r
+               /// </summary>\r
+               /// <param name="i">Index to start inserting at</param>\r
+               /// <param name="items">Items to insert</param>\r
+               [Tested]\r
+               public virtual void InsertAll(int i, MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+                       if (i < 0 || i > size)\r
+                               throw new IndexOutOfRangeException();\r
+\r
+                       int toadd = EnumerableBase<T>.countItems(items);\r
+\r
+                       if (toadd + underlyingsize > array.Length)\r
+                               expand(toadd + underlyingsize, underlyingsize);\r
+\r
+                       i += offset;\r
+                       if (underlyingsize > i)\r
+                               Array.Copy(array, i, array, i + toadd, underlyingsize - i);\r
+\r
+                       foreach (T item in items)\r
+                               array[i++] = item;\r
+\r
+                       addtosize(toadd);\r
+               }\r
+\r
+        internal virtual void InsertAll<U>(int i, MSG.IEnumerable<U> items) where U:T\r
+        {\r
+            updatecheck();\r
+            if (i < 0 || i > size)\r
+                throw new IndexOutOfRangeException();\r
+\r
+            int toadd = EnumerableBase<U>.countItems(items);\r
+\r
+            if (toadd + underlyingsize > array.Length)\r
+                expand(toadd + underlyingsize, underlyingsize);\r
+\r
+            i += offset;\r
+            if (underlyingsize > i)\r
+                Array.Copy(array, i, array, i + toadd, underlyingsize - i);\r
+\r
+            foreach (T item in items)\r
+                array[i++] = item;\r
+\r
+            addtosize(toadd);\r
+        }\r
+\r
+        /// <summary>\r
+               /// Insert an item right before the first occurrence of some target item.\r
+               /// <exception cref="ArgumentException"/> if target     is not found.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target before which to insert.</param>\r
+               [Tested]\r
+               public virtual void InsertBefore(T item, T target)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int i = indexOf(target);\r
+\r
+                       if (i == -1)\r
+                               throw new ArgumentException("Target item not found");\r
+\r
+                       insert(i, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item right after the last(???) occurrence of some target item.\r
+               /// <exception cref="ArgumentException"/> if target     is not found.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target after which to insert.</param>\r
+               [Tested]\r
+               public virtual void InsertAfter(T item, T target)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int i = lastIndexOf(target);\r
+\r
+                       if (i == -1)\r
+                               throw new ArgumentException("Target item not found");\r
+\r
+                       insert(i + 1, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at the front of this list;\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               [Tested]\r
+               public virtual void InsertFirst(T item)\r
+               {\r
+                       updatecheck();\r
+                       insert(0, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at the back of this list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               [Tested]\r
+               public virtual void InsertLast(T item)\r
+               {\r
+                       updatecheck();\r
+                       insert(size, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new list consisting of the items of this list satisfying a \r
+               /// certain predicate.\r
+               /// </summary>\r
+               /// <param name="filter">The filter delegate defining the predicate.</param>\r
+               /// <returns>The new list.</returns>\r
+               [Tested]\r
+               public virtual IList<T> FindAll(Filter<T> filter)\r
+               {\r
+                       modifycheck();\r
+\r
+                       ArrayList<T> res = new ArrayList<T>(itemhasher);\r
+                       int j = 0, rescap = res.array.Length;\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                       {\r
+                               T a = array[offset + i];\r
+\r
+                               if (filter(a))\r
+                               {\r
+                                       if (j == rescap) res.expand(rescap = 2 * rescap, j);\r
+\r
+                                       res.array[j++] = a;\r
+                               }\r
+                       }\r
+\r
+                       res.underlyingsize = res.size = j;\r
+                       return res;\r
+               }\r
+\r
+\r
+        /// <summary>\r
+        /// Create a new list consisting of the results of mapping all items of this\r
+        /// list. The new list will use the default hasher for the item type V.\r
+        /// </summary>\r
+        /// <typeparam name="V">The type of items of the new list</typeparam>\r
+        /// <param name="mapper">The delegate defining the map.</param>\r
+        /// <returns>The new list.</returns>\r
+        [Tested]\r
+        public virtual IList<V> Map<V>(Mapper<T, V> mapper)\r
+        {\r
+            modifycheck();\r
+\r
+            ArrayList<V> res = new ArrayList<V>(size);\r
+\r
+            return map<V>(mapper, res);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Create a new list consisting of the results of mapping all items of this\r
+        /// list. The new list will use a specified hasher for the item type.\r
+        /// </summary>\r
+        /// <typeparam name="V">The type of items of the new list</typeparam>\r
+        /// <param name="mapper">The delegate defining the map.</param>\r
+        /// <param name="hasher">The hasher to use for the new list</param>\r
+        /// <returns>The new list.</returns>\r
+        public virtual IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher)\r
+        {\r
+            modifycheck();\r
+\r
+            ArrayList<V> res = new ArrayList<V>(size,hasher);\r
+\r
+            return map<V>(mapper, res);\r
+        }\r
+\r
+        private IList<V> map<V>(Mapper<T, V> mapper, ArrayList<V> res)\r
+        {\r
+            if (size > 0)\r
+                for (int i = 0; i < size; i++)\r
+                    res.array[i] = mapper(array[offset + i]);\r
+\r
+            res.underlyingsize = res.size = size;\r
+            return res;\r
+        }\r
+\r
+/// <summary>\r
+        /// Remove one item from the list: from the front if <code>FIFO</code>\r
+               /// is true, else from the back.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public virtual T Remove() { return fIFO ? RemoveFirst() : RemoveLast(); }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one item from the fromnt of the list.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public virtual T RemoveFirst()\r
+               {\r
+                       updatecheck();\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("List is empty");\r
+\r
+                       return removeAt(0);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one item from the back of the list.\r
+               /// </summary>\r
+               /// <exception cref="InvalidOperationException"> if this list is empty.</exception>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public virtual T RemoveLast()\r
+               {\r
+                       updatecheck();\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("List is empty");\r
+\r
+                       return removeAt(size - 1);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a list view on this list. \r
+        /// <exception cref="ArgumentOutOfRangeException"/> if the start or count is negative\r
+        /// <exception cref="ArgumentException"/> if the range does not fit within list.\r
+        /// </summary>\r
+        /// <param name="start">The index in this list of the start of the view.</param>\r
+               /// <param name="count">The size of the view.</param>\r
+               /// <returns>The new list view.</returns>\r
+               [Tested]\r
+               public virtual IList<T> View(int start, int count)\r
+               {\r
+            modifycheck();\r
+            checkRange(start, count);\r
+            \r
+            ArrayList<T> retval = (ArrayList<T>)MemberwiseClone();\r
+\r
+            retval.underlying = underlying != null ? underlying : this;\r
+                       retval.offset = start;\r
+                       retval.size = count;\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Null if this list is not a view.\r
+               /// </summary>\r
+        /// <value>Underlying list for view.</value>\r
+        [Tested]\r
+               public IList<T> Underlying { [Tested]get { return underlying; } }\r
+\r
+\r
+               /// <summary>\r
+               /// </summary>\r
+               /// <value>Offset for this list view or 0 for an underlying list.</value>\r
+               [Tested]\r
+               public int Offset { [Tested]get { return offset; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Slide this list view along the underlying list.\r
+               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
+               /// would bring either end of the view outside the underlying list.\r
+               /// </summary>\r
+               /// <param name="offset">The signed amount to slide: positive to slide\r
+               /// towards the end.</param>\r
+               [Tested]\r
+               public virtual void Slide(int offset)\r
+               {\r
+                       modifycheck();\r
+                       if (underlying == null)\r
+                               throw new InvalidOperationException("Not a view");\r
+\r
+                       int newoffset = this.offset + offset;\r
+\r
+                       if (newoffset < 0 || newoffset + size > underlyingsize)\r
+                               throw new ArgumentOutOfRangeException();\r
+\r
+                       this.offset = newoffset;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Slide this list view along the underlying list, changing its size.\r
+               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
+               /// would bring either end of the view outside the underlying list.\r
+               /// </summary>\r
+               /// <param name="offset">The signed amount to slide: positive to slide\r
+               /// towards the end.</param>\r
+               /// <param name="size">The new size of the view.</param>\r
+               [Tested]\r
+               public virtual void Slide(int offset, int size)\r
+               {\r
+                       modifycheck();\r
+                       if (underlying == null)\r
+                               throw new InvalidOperationException("Not a view");\r
+\r
+                       int newoffset = this.offset + offset;\r
+                       int newsize = size;\r
+\r
+                       if (newoffset < 0 || newsize < 0 || newoffset + newsize > underlyingsize)\r
+                               throw new ArgumentOutOfRangeException();\r
+\r
+                       this.offset = newoffset;\r
+                       this.size = newsize;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Reverst the list so the items are in the opposite sequence order.\r
+               /// </summary>\r
+               [Tested]\r
+               public virtual void Reverse() { Reverse(0, size); }\r
+\r
+\r
+               /// <summary>\r
+               /// Reverst part of the list so the items are in the opposite sequence order.\r
+               /// <exception cref="ArgumentException"/> if the count is negative.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
+               /// into the list.\r
+               /// </summary>\r
+               /// <param name="start">The index of the start of the part to reverse.</param>\r
+               /// <param name="count">The size of the part to reverse.</param>\r
+               [Tested]\r
+               public virtual void Reverse(int start, int count)\r
+               {\r
+                       updatecheck();\r
+                       checkRange(start, count);\r
+                       start += offset;\r
+                       for (int i = 0, length = count / 2, end = start + count - 1; i < length; i++)\r
+                       {\r
+                               T swap = array[start + i];\r
+\r
+                               array[start + i] = array[end - i];\r
+                               array[end - i] = swap;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this list is sorted according to a specific sorting order.\r
+               /// </summary>\r
+               /// <param name="c">The comparer defining the sorting order.</param>\r
+               /// <returns>True if the list is sorted, else false.</returns>\r
+               [Tested]\r
+               public virtual bool IsSorted(IComparer<T> c)\r
+               {\r
+                       modifycheck();\r
+                       for (int i = offset + 1, end = offset + size; i < end; i++)\r
+                               if (c.Compare(array[i - 1], array[i]) > 0)\r
+                                       return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Sort the items of the list according to a specific sorting order.\r
+               /// </summary>\r
+               /// <param name="c">The comparer defining the sorting order.</param>\r
+               [Tested]\r
+               public virtual void Sort(IComparer<T> c)\r
+               {\r
+                       updatecheck();\r
+                       Sorting.IntroSort<T>(array, offset, offset + size, c);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Randonmly shuffle the items of this list. \r
+               /// </summary>\r
+               public virtual void Shuffle() { Shuffle(new C5Random()); }\r
+\r
+\r
+               /// <summary>\r
+               /// Shuffle the items of this list according to a specific random source.\r
+               /// </summary>\r
+               /// <param name="rnd">The random source.</param>\r
+               public virtual void Shuffle(Random rnd)\r
+               {\r
+                       updatecheck();\r
+                       for (int i = offset, top = offset + size, end = top - 1; i < end; i++)\r
+                       {\r
+                               int j = rnd.Next(i, top);\r
+\r
+                               if (j != i)\r
+                               {\r
+                                       T tmp = array[i];\r
+\r
+                                       array[i] = array[j];\r
+                                       array[j] = tmp;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IIndexed<T> Members\r
+\r
+               /// <summary>\r
+               /// Search for an item in the list going forwrds from the start.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of item from start.</returns>\r
+               [Tested]\r
+               public virtual int IndexOf(T item) { modifycheck(); return indexOf(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Search for an item in the list going backwords from the end.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of of item from the end.</returns>\r
+               [Tested]\r
+               public virtual int LastIndexOf(T item) { modifycheck(); return lastIndexOf(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the item at a specific position of the list.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <param name="i">The index of the item to remove.</param>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public virtual T RemoveAt(int i)\r
+               {\r
+                       updatecheck();\r
+                       if (i < 0 || i >= size)\r
+                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
+\r
+                       return removeAt(i);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in an index interval.\r
+               /// <exception cref="IndexOutOfRangeException"/>???. \r
+               /// </summary>\r
+               /// <param name="start">The index of the first item to remove.</param>\r
+               /// <param name="count">The number of items to remove.</param>\r
+               [Tested]\r
+               public virtual void RemoveInterval(int start, int count)\r
+               {\r
+                       updatecheck();\r
+                       checkRange(start, count);\r
+                       start += offset;\r
+                       Array.Copy(array, start + count, array, start, underlyingsize - start - count);\r
+                       addtosize(-count);\r
+                       Array.Clear(array, underlyingsize, count);\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISequenced<T> Members\r
+\r
+\r
+               int ISequenced<T>.GetHashCode()\r
+               { modifycheck(); return sequencedhashcode(); }\r
+\r
+\r
+               bool ISequenced<T>.Equals(ISequenced<T> that)\r
+               { modifycheck(); return sequencedequals(that); }\r
+\r
+               #endregion\r
+\r
+               #region ICollection<T> Members\r
+\r
+               /// <summary>\r
+               /// The value is symbolic indicating the type of asymptotic complexity\r
+               /// in terms of the size of this collection (worst-case or amortized as\r
+               /// relevant).\r
+               /// </summary>\r
+               /// <value>Speed.Linear</value>\r
+               [Tested]\r
+               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Linear; } }\r
+\r
+\r
+               int ICollection<T>.GetHashCode()\r
+               { modifycheck(); return unsequencedhashcode(); }\r
+\r
+\r
+               bool ICollection<T>.Equals(ICollection<T> that)\r
+               { modifycheck(); return unsequencedequals(that); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains (an item equivalent to according to the\r
+               /// itemhasher) a particular value.\r
+               /// </summary>\r
+               /// <param name="item">The value to check for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public virtual bool Contains(T item)\r
+               { modifycheck(); return indexOf(item) >= 0; }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public virtual bool Find(ref T item)\r
+               {\r
+                       modifycheck();\r
+\r
+                       int i;\r
+\r
+                       if ((i = indexOf(item)) >= 0)\r
+                       {\r
+                               item = array[offset + i];\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value. This will only update the first \r
+               /// mathching item.\r
+               /// </summary>\r
+               /// <param name="item">Value to update.</param>\r
+               /// <returns>True if the item was found and hence updated.</returns>\r
+               [Tested]\r
+               public virtual bool Update(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int i;\r
+\r
+                       if ((i = indexOf(item)) >= 0)\r
+                       {\r
+                               array[offset + i] = item;\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found. Else, add the item to the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the item was found (hence not added).</returns>\r
+               [Tested]\r
+               public virtual bool FindOrAdd(ref T item)\r
+               {\r
+                       updatecheck();\r
+                       if (Find(ref item))\r
+                               return true;\r
+\r
+                       Add(item);\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value. This will only update the first \r
+               /// mathching item.\r
+               /// </summary>\r
+               /// <param name="item">Value to update.</param>\r
+               /// <returns>True if the item was found and hence updated.</returns>\r
+               [Tested]\r
+               public virtual bool UpdateOrAdd(T item)\r
+               {\r
+                       updatecheck();\r
+                       if (Update(item))\r
+                               return true;\r
+\r
+                       Add(item);\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the first copy of a particular item from this collection. \r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public virtual bool Remove(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int i = indexOf(item);\r
+\r
+                       if (i < 0)\r
+                               return false;\r
+\r
+                       removeAt(i);\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the first copy of a particular item from this collection if found.\r
+               /// If an item was removed, report a binary copy of the actual item removed in \r
+               /// the argument.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove on input.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public virtual bool RemoveWithReturn(ref T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int i = indexOf(item);\r
+\r
+                       if (i < 0)\r
+                               return false;\r
+\r
+                       item = removeAt(i);\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in another collection from this one, taking multiplicities into account.\r
+               /// Matching items will be removed from the front. Current implementation is not optimal.\r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public virtual void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int[] toremove = new int[(size >>5) + 1];\r
+\r
+                       foreach (T item in items)\r
+                               for (int i = 0; i < size; i++)\r
+                                       if ((toremove[i >>5] & (1 << (i & 31))) == 0 && equals(array[offset + i], item))\r
+                                       {\r
+                                               toremove[i >>5] |= 1 << (i & 31);\r
+                                               break;\r
+                                       }\r
+\r
+                       int j = offset;\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                               if ((toremove[i >>5] & (1 << (i & 31))) == 0)\r
+                                       array[j++] = array[offset + i];\r
+\r
+                       int removed = offset + size - j;\r
+\r
+                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+                       addtosize(-removed);\r
+                       Array.Clear(array, underlyingsize, removed);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from this collection, resetting internal array size.\r
+               /// </summary>\r
+               [Tested]\r
+               public override void Clear()\r
+               {\r
+                       updatecheck();\r
+                       if (underlying == null)\r
+                       {\r
+                               array = new T[8];\r
+                               underlyingsize = size = 0;\r
+                       }\r
+                       else\r
+                       {\r
+                               underlying.RemoveInterval(offset, size);\r
+                               size = 0;\r
+                               underlyingsize = underlying.size;\r
+                               stamp = underlying.stamp;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items not in some other collection from this one, taking multiplicities into account.\r
+               /// Items are retained front first.  Current implementation is not optimal.\r
+               /// </summary>\r
+               /// <param name="items">The items to retain.</param>\r
+               [Tested]\r
+               public virtual void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int[] toretain = new int[(size >>5) + 1];\r
+\r
+                       foreach (T item in items)\r
+                               for (int i = 0; i < size; i++)\r
+                                       if ((toretain[i >>5] & (1 << (i & 31))) == 0 && equals(array[offset + i], item))\r
+                                       {\r
+                                               toretain[i >>5] |= 1 << (i & 31);\r
+                                               break;\r
+                                       }\r
+\r
+                       int j = offset;\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                               if ((toretain[i >>5] & (1 << (i & 31))) != 0)\r
+                                       array[j++] = array[i + offset];\r
+\r
+                       int removed = offset + size - j;\r
+\r
+                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+                       addtosize(-removed);\r
+                       Array.Clear(array, underlyingsize, removed);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains all the values in another collection,\r
+               /// taking multiplicities into account.\r
+               /// Current implementation is not optimal.\r
+               /// </summary>\r
+               /// <param name="items">The </param>\r
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+               [Tested]\r
+               public virtual bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       modifycheck();\r
+\r
+                       int[] matched = new int[(size >>5) + 1];\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               for (int i = 0; i < size; i++)\r
+                                       if ((matched[i >>5] & (1 << (i & 31))) == 0 && equals(array[i + offset], item))\r
+                                       {\r
+                                               matched[i >>5] |= 1 << (i & 31);\r
+                                               goto next;\r
+                                       }\r
+\r
+                               return false;\r
+                       next :\r
+                               ;\r
+                       }\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Count the number of items of the collection equal to a particular value.\r
+               /// Returns 0 if and only if the value is not in the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to count.</param>\r
+               /// <returns>The number of copies found.</returns>\r
+               [Tested]\r
+               public virtual int ContainsCount(T item)\r
+               {\r
+                       modifycheck();\r
+\r
+                       int count = 0;\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                               if (equals(item, array[offset + i]))\r
+                                       count++;\r
+\r
+                       return count;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items equal to a given one.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               [Tested]\r
+               public virtual void RemoveAllCopies(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int j = offset;\r
+\r
+                       for (int i = offset, end = offset + size; i < end; i++)\r
+                               if (!equals(item, array[i]))\r
+                                       array[j++] = array[i];\r
+\r
+                       int removed = offset + size - j;\r
+\r
+                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+                       addtosize(-removed);\r
+                       Array.Clear(array, underlyingsize, removed);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this array list.\r
+               /// </summary>\r
+               /// <returns>True if check does not fail.</returns>\r
+               [Tested]\r
+               public override bool Check()\r
+               {\r
+                       bool retval = true;\r
+\r
+                       if (underlyingsize > array.Length)\r
+                       {\r
+                               Console.WriteLine("underlyingsize ({0}) > array.Length ({1})", size, array.Length);\r
+                               return false;\r
+                       }\r
+\r
+                       if (offset + size > underlyingsize)\r
+                       {\r
+                               Console.WriteLine("offset({0})+size({1}) > underlyingsize ({2})", offset, size, underlyingsize);\r
+                               return false;\r
+                       }\r
+\r
+                       if (offset < 0)\r
+                       {\r
+                               Console.WriteLine("offset({0}) < 0", offset);\r
+                               return false;\r
+                       }\r
+\r
+                       for (int i = 0; i < underlyingsize; i++)\r
+                       {\r
+                               if ((object)(array[i]) == null)\r
+                               {\r
+                                       Console.WriteLine("Bad element: null at (base)index {0}", i);\r
+                                       retval = false;\r
+                               }\r
+                       }\r
+\r
+                       for (int i = underlyingsize, length = array.Length; i < length; i++)\r
+                       {\r
+                               if (!equals(array[i], default(T)))\r
+                               {\r
+                                       Console.WriteLine("Bad element: != default(T) at (base)index {0}", i);\r
+                                       retval = false;\r
+                               }\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IExtensible<T> Members\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True, indicating array list has bag semantics.</value>\r
+               [Tested]\r
+               public virtual bool AllowsDuplicates { [Tested]get { return true; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to end of this list.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True</returns>\r
+               [Tested]\r
+               public virtual bool Add(T item)\r
+               {\r
+                       updatecheck();\r
+                       insert(size, item);\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add the elements from another collection to this collection. \r
+               /// </summary>\r
+               /// <param name="items">The items to add.</param>\r
+               [Tested]\r
+               public virtual void AddAll(MSG.IEnumerable<T> items) { InsertAll(size, items); }\r
+\r
+        /*public virtual*/ void C5.IExtensible<T>.AddAll<U>(MSG.IEnumerable<U> items) //where U : T \r
+        {\r
+            InsertAll(size, items);\r
+        }\r
+\r
+               #endregion\r
+\r
+               #region IDirectedEnumerable<T> Members\r
+\r
+               /// <summary>\r
+               /// Create a collection containing the same items as this collection, but\r
+               /// whose enumerator will enumerate the items backwards. The new collection\r
+               /// will become invalid if the original is modified. Method typicaly used as in\r
+               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
+               /// </summary>\r
+               /// <returns>The backwards collection.</returns>\r
+               [Tested]\r
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+               #endregion\r
+\r
+        #region IStack<T> Members\r
+\r
+        /// <summary>\r
+        /// Push an item to the top of the stack.\r
+        /// </summary>\r
+        /// <param name="item">The item</param>\r
+        [Tested]\r
+        public void Push(T item)\r
+        {\r
+            Add(item);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Pop the item at the top of the stack from the stack.\r
+        /// </summary>\r
+        /// <returns>The popped item.</returns>\r
+        [Tested]\r
+        public T Pop()\r
+        {\r
+            return RemoveLast();\r
+        }\r
+\r
+        #endregion\r
+\r
+        #region IQueue<T> Members\r
+\r
+        /// <summary>\r
+        /// Enqueue an item at the back of the queue. \r
+        /// </summary>\r
+        /// <param name="item">The item</param>\r
+        [Tested]\r
+        public void EnQueue(T item)\r
+        {\r
+            Add(item);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Dequeue an item from the front of the queue.\r
+        /// </summary>\r
+        /// <returns>The item</returns>\r
+        [Tested]\r
+        public T DeQueue()\r
+        {\r
+            return RemoveFirst();\r
+        }\r
+\r
+        #endregion\r
+    }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/arrays/HashedArray.cs b/mcs/class/Mono.C5/C5/arrays/HashedArray.cs
new file mode 100644 (file)
index 0000000..c5538d9
--- /dev/null
@@ -0,0 +1,638 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A set collection based on a dynamic  array combined with a hash index\r
+       /// for item to index lookup.\r
+       /// </summary>\r
+       public class HashedArrayList<T>: ArrayList<T>, IList<T>\r
+       {\r
+               #region Fields\r
+\r
+               HashSet<KeyValuePair<T,int>> index;\r
+\r
+               #endregion\r
+\r
+               #region Util\r
+\r
+               private void reindex(int start) { reindex(start, underlyingsize); }\r
+\r
+\r
+               private void reindex(int start, int end)\r
+               {\r
+                       for (int j = start; j < end; j++)\r
+                               index.Update(new KeyValuePair<T,int>(array[j], j));\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of IndexOf without modification checks.\r
+               /// </summary>\r
+               /// <param name="item">Item to look for</param>\r
+               /// <returns>The index of first occurrence</returns>\r
+               protected override int indexOf(T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item);\r
+\r
+                       if (!index.Find(ref p) || p.value < offset || p.value >= offset + size)\r
+                               return -1;\r
+\r
+                       return p.value - offset;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of LastIndexOf without modification checks.\r
+               /// </summary>\r
+               /// <param name="item">Item to look for</param>\r
+               /// <returns>The index of last occurrence</returns>\r
+               protected override int lastIndexOf(T item) { return indexOf(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of Insert with no modification checks.\r
+               /// <exception cref="ArgumentException"/> if item already in list.\r
+               /// </summary>\r
+               /// <param name="i">Index to insert at</param>\r
+               /// <param name="item">Item to insert</param>\r
+               protected override void insert(int i, T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, offset + i);\r
+\r
+                       if (index.FindOrAdd(ref p))\r
+                               throw new ArgumentException("Item already in indexed list");\r
+\r
+                       base.insert(i, item);\r
+                       reindex(i + 1);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Internal version of RemoveAt with no modification checks.\r
+               /// </summary>\r
+               /// <param name="i">Index to remove at</param>\r
+               /// <returns>The removed item</returns>\r
+               protected override T removeAt(int i)\r
+               {\r
+                       T val = base.removeAt(i);\r
+\r
+                       index.Remove(new KeyValuePair<T,int>(val));\r
+                       reindex(offset + i);\r
+                       return val;\r
+               }\r
+\r
+\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+               /// <summary>\r
+               /// Create a hashed array list with the natural hasher \r
+               /// </summary>\r
+               public HashedArrayList() : this(8) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hashed array list with the natural hasher and specified capacity\r
+               /// </summary>\r
+               /// <param name="cap">The initial capacity</param>\r
+               public HashedArrayList(int cap) : this(cap,HasherBuilder.ByPrototype<T>.Examine()) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hashed array list with an external hasher\r
+               /// </summary>\r
+               /// <param name="hasher">The external hasher</param>\r
+               public HashedArrayList(IHasher<T> hasher) : this(8,hasher) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hashed array list with an external hasher and specified capacity\r
+               /// </summary>\r
+               /// <param name="capacity">The initial capacity</param>\r
+               /// <param name="hasher">The external hasher</param>\r
+               public HashedArrayList(int capacity, IHasher<T> hasher) : base(capacity, hasher)\r
+               {\r
+                       index = new HashSet<KeyValuePair<T,int>>(new KeyValuePairHasher<T,int>(hasher));\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IList<T> Members\r
+\r
+               /// <summary>\r
+               /// Insert into this list all items from an enumerable collection starting \r
+               /// at a particular index.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt; the size of the collection.\r
+               /// <exception cref="InvalidOperationException"/> if one of the items to insert is\r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="i">Index to start inserting at</param>\r
+               /// <param name="items">Items to insert</param>\r
+               [Tested]\r
+               public override void InsertAll(int i, MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+                       if (i < 0 || i > size)\r
+                               throw new IndexOutOfRangeException();\r
+\r
+                       i += offset;\r
+\r
+                       int j = i, toadd;\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               p.key = item;\r
+                               p.value = j;\r
+                               if (!index.FindOrAdd(ref p))    j++;\r
+                       }\r
+\r
+                       toadd = j - i;\r
+                       if (toadd + underlyingsize > array.Length)\r
+                               expand(toadd + underlyingsize, underlyingsize);\r
+\r
+                       if (underlyingsize > i)\r
+                               Array.Copy(array, i, array, j, underlyingsize - i);\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               p.key = item;\r
+                               index.Find(ref p);\r
+                               if (i <= p.value && p.value < i + toadd)\r
+                                       array[p.value] = item;\r
+                       }\r
+\r
+                       addtosize(toadd);\r
+                       reindex(j);\r
+               }\r
+\r
+        internal override void InsertAll<U>(int i, MSG.IEnumerable<U> items) //where U:T\r
+        {\r
+            updatecheck();\r
+            if (i < 0 || i > size)\r
+                throw new IndexOutOfRangeException();\r
+\r
+            i += offset;\r
+\r
+            int j = i, toadd;\r
+            KeyValuePair<T, int> p = new KeyValuePair<T, int>();\r
+\r
+            foreach (T item in items)\r
+            {\r
+                p.key = item;\r
+                p.value = j;\r
+                if (!index.FindOrAdd(ref p)) j++;\r
+            }\r
+\r
+            toadd = j - i;\r
+            if (toadd + underlyingsize > array.Length)\r
+                expand(toadd + underlyingsize, underlyingsize);\r
+\r
+            if (underlyingsize > i)\r
+                Array.Copy(array, i, array, j, underlyingsize - i);\r
+\r
+            foreach (T item in items)\r
+            {\r
+                p.key = item;\r
+                index.Find(ref p);\r
+                if (i <= p.value && p.value < i + toadd)\r
+                    array[p.value] = item;\r
+            }\r
+\r
+            addtosize(toadd);\r
+            reindex(j);\r
+        }\r
+\r
+        /// <summary>\r
+               /// Insert an item right before the first occurrence of some target item.\r
+               /// <exception cref="ArgumentException"/> if target     is not found.\r
+               /// <exception cref="InvalidOperationException"/> if the item to insert is\r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target before which to insert.</param>\r
+               [Tested]\r
+               public override void InsertBefore(T item, T target)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int ind = indexOf(target);\r
+\r
+                       if (ind < 0)\r
+                               throw new ArgumentException("Target item not found");\r
+\r
+                       insert(ind, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item right after the last(???) occurrence of some target item.\r
+               /// <exception cref="ArgumentException"/> if target     is not found.\r
+               /// <exception cref="InvalidOperationException"/> if the item to insert is\r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target after which to insert.</param>\r
+               [Tested]\r
+               public override void InsertAfter(T item, T target)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int ind = indexOf(target);\r
+\r
+                       if (ind < 0)\r
+                               throw new ArgumentException("Target item not found");\r
+\r
+                       insert(ind + 1, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a list view on this list. \r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the view would not fit into\r
+               /// this list.\r
+               /// </summary>\r
+               /// <param name="start">The index in this list of the start of the view.</param>\r
+               /// <param name="count">The size of the view.</param>\r
+               /// <returns>The new list view.</returns>\r
+               [Tested]\r
+               public override IList<T> View(int start, int count)\r
+               {\r
+                       HashedArrayList<T> retval = (HashedArrayList<T>)MemberwiseClone();\r
+\r
+                       retval.underlying = underlying != null ? underlying : this;\r
+                       retval.offset = start;\r
+                       retval.size = count;\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Reverst part of the list so the items are in the opposite sequence order.\r
+               /// <exception cref="ArgumentException"/> if the count is negative.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
+               /// into the list.\r
+               /// </summary>\r
+               /// <param name="start">The index of the start of the part to reverse.</param>\r
+               /// <param name="count">The size of the part to reverse.</param>\r
+               [Tested]\r
+               public override void Reverse(int start, int count)\r
+               {\r
+                       base.Reverse(start, count);\r
+                       reindex(offset + start, offset + start + count);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Sort the items of the list according to a specific sorting order.\r
+               /// </summary>\r
+               /// <param name="c">The comparer defining the sorting order.</param>\r
+               [Tested]\r
+               public override void Sort(IComparer<T> c)\r
+               {\r
+                       base.Sort(c);\r
+                       reindex(offset, offset + size);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Shuffle the items of this list according to a specific random source.\r
+               /// </summary>\r
+               /// <param name="rnd">The random source.</param>\r
+               public override void Shuffle(Random rnd)\r
+               {\r
+                       base.Shuffle(rnd);\r
+                       reindex(offset, offset + size);\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IIndexed<T> Members\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in an index interval.\r
+               /// <exception cref="IndexOutOfRangeException"/>???. \r
+               /// </summary>\r
+               /// <param name="start">The index of the first item to remove.</param>\r
+               /// <param name="count">The number of items to remove.</param>\r
+               [Tested]\r
+               public override void RemoveInterval(int start, int count)\r
+               {\r
+                       updatecheck();\r
+\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
+\r
+                       for (int i = offset + start, end = offset + start + count; i < end; i++)\r
+                       {\r
+                               p.key = array[i];\r
+                               index.Remove(p);\r
+                       }\r
+\r
+                       base.RemoveInterval(start, count);\r
+                       reindex(offset + start);\r
+               }\r
+\r
+               #endregion\r
+        \r
+               #region ISequenced<T> Members\r
+\r
+               int ISequenced<T>.GetHashCode()\r
+               { modifycheck(); return sequencedhashcode(); }\r
+\r
+\r
+               bool ISequenced<T>.Equals(ISequenced<T> that)\r
+               { modifycheck(); return sequencedequals(that); }\r
+\r
+\r
+       #endregion\r
+        \r
+               #region IEditableCollection<T> Members\r
+\r
+               /// <summary>\r
+               /// The value is symbolic indicating the type of asymptotic complexity\r
+               /// in terms of the size of this collection (expected).\r
+               /// </summary>\r
+               /// <value>Speed.Constant</value>\r
+               [Tested]\r
+               public override Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains (an item equivalent to according to the\r
+               /// itemhasher) a particular value.\r
+               /// </summary>\r
+               /// <param name="item">The value to check for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public override bool Contains(T item)\r
+               { modifycheck(); return indexOf(item) >= 0; }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the first copy of a particular item from this collection. \r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public override bool Remove(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int ind = indexOf(item);\r
+\r
+                       if (ind < 0)\r
+                               return false;\r
+\r
+                       removeAt(ind);\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in another collection from this one, taking multiplicities into account.\r
+               /// Matching items will be removed from the front. Current implementation is not optimal.\r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public override void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               p.key = item;\r
+                               if (index.Find(ref p) && offset <= p.value && p.value < offset + size)\r
+                                       index.Remove(p);\r
+                       }\r
+\r
+                       int removed = underlyingsize - index.Count, j = offset;\r
+\r
+                       for (int i = offset; i < underlyingsize; i++)\r
+                       {\r
+                               p.key = array[i];\r
+                               p.value = j;\r
+                               if (index.Update(p)) { array[j++] = p.key; }\r
+                       }\r
+\r
+                       addtosize(-removed);\r
+                       Array.Clear(array, underlyingsize, removed);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from this collection, resetting internal array size.\r
+               /// </summary>\r
+               [Tested]\r
+               public override void Clear()\r
+               {\r
+                       updatecheck();\r
+                       if (underlying == null)\r
+                       {\r
+                               index.Clear();\r
+                               base.Clear();\r
+                       }\r
+                       else\r
+                       {\r
+                               for (int i = offset, end = offset + size; i < end; i++)\r
+                                       index.Remove(new KeyValuePair<T,int>(array[i]));\r
+\r
+                               base.Clear();\r
+                               reindex(offset);\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items not in some other collection from this one.\r
+               /// </summary>\r
+               /// <param name="items">The items to retain.</param>\r
+               [Tested]\r
+               public override void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       HashSet<T> toretain = new HashSet<T>(itemhasher);\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               p.key = item;\r
+                               if (index.Find(ref p) && offset <= p.value && p.value < offset + size)\r
+                                       toretain.Add(item);\r
+                       }\r
+\r
+                       int removed = size - toretain.Count, j = offset;\r
+\r
+                       for (int i = offset; i < offset + size; i++)\r
+                       {\r
+                               p.key = array[i];\r
+                               p.value = j;\r
+                               if (toretain.Contains(p.key))\r
+                               {\r
+                                       index.Update(p);\r
+                                       array[j++] = p.key;\r
+                               }\r
+                               else\r
+                               {\r
+                                       index.Remove(p);\r
+                               }\r
+                       }\r
+\r
+                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+                       addtosize(-removed);\r
+                       reindex(j);\r
+                       Array.Clear(array, underlyingsize, removed);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains all the values in another collection.\r
+               /// </summary>\r
+               /// <param name="items">The </param>\r
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+               [Tested]\r
+               public override bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       modifycheck();\r
+                       foreach (T item in items)\r
+                               if (indexOf(item) < 0)\r
+                                       return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Count the number of items of the collection equal to a particular value.\r
+               /// Returns 0 if and only if the value is not in the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to count.</param>\r
+               /// <returns>The number of copies found (0 or 1).</returns>\r
+               [Tested]\r
+               public override int ContainsCount(T item)\r
+               { modifycheck(); return indexOf(item) >= 0 ? 1 : 0; }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items equal to a given one.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               [Tested]\r
+               public override void RemoveAllCopies(T item) { Remove(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this array list.\r
+               /// </summary>\r
+               /// <returns>True if check does not fail.</returns>\r
+               [Tested]\r
+               public override bool Check()\r
+               {\r
+                       if (!base.Check())\r
+                               return false;\r
+\r
+                       bool retval = true;\r
+\r
+                       if (underlyingsize != index.Count)\r
+                       {\r
+                               Console.WriteLine("size ({0})!= index.Count ({1})", size, index.Count);\r
+                               retval = false;\r
+                       }\r
+\r
+                       for (int i = 0; i < underlyingsize; i++)\r
+                       {\r
+                               KeyValuePair<T,int> p = new KeyValuePair<T,int>(array[i]);\r
+\r
+                               if (!index.Find(ref p))\r
+                               {\r
+                                       Console.WriteLine("Item {1} at {0} not in hashindex", i, array[i]);\r
+                                       retval = false;\r
+                               }\r
+\r
+                               if (p.value != i)\r
+                               {\r
+                                       Console.WriteLine("Item {1} at {0} has hashindex {2}", i, array[i], p.value);\r
+                                       retval = false;\r
+                               }\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+\r
+\r
+               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
+\r
+\r
+               bool ICollection<T>.Equals(ICollection<T> that)\r
+               { return unsequencedequals(that); }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>False, indicating hashed array list has set semantics.</value>\r
+               [Tested]\r
+               public override bool AllowsDuplicates { [Tested]get { return false; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to end of this list if not already in list.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True if item was added</returns>\r
+               [Tested]\r
+               public override bool Add(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, size);\r
+\r
+                       if (index.FindOrAdd(ref p))\r
+                               return false;\r
+\r
+                       base.insert(size, item);\r
+                       reindex(size);\r
+                       return true;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IDirectedEnumerable<T> Members\r
+\r
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+               #endregion\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/arrays/SortedArray.cs b/mcs/class/Mono.C5/C5/arrays/SortedArray.cs
new file mode 100644 (file)
index 0000000..77478fb
--- /dev/null
@@ -0,0 +1,1232 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A collection class implementing a sorted dynamic array data structure.\r
+       /// </summary>\r
+       public class SortedArray<T>: ArrayBase<T>, IIndexedSorted<T>\r
+       {\r
+               #region Features\r
+               /// <summary>\r
+               /// A debugging artifact. To be removed.\r
+               /// </summary>\r
+               [Flags]\r
+               public enum Feature: short\r
+               {\r
+                       /// <summary>\r
+                       /// A debugging artifact. To be removed.\r
+                       /// </summary>\r
+                       Standard = 0\r
+               }\r
+\r
+\r
+               static Feature features = Feature.Standard;\r
+\r
+\r
+               /// <summary>\r
+               /// A debugging artifact. To be removed.\r
+               /// </summary>\r
+               /// <value></value>\r
+               public static Feature Features { get { return features; } }\r
+\r
+               #endregion\r
+               \r
+               #region Fields\r
+\r
+               IComparer<T> comparer;\r
+\r
+               #endregion\r
+               \r
+               #region Util\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <param name="item">The item to search for</param>\r
+               /// <param name="mid">The least index, mid, for which array[mid] >= item</param>\r
+               /// <returns>True if item found</returns>\r
+               private bool binarySearch(T item, out int mid)\r
+               {\r
+                       int bot = 0, top = size;\r
+\r
+                       mid = top / 2;\r
+                       while (top > bot)\r
+                       {\r
+                               int c;\r
+\r
+                               if ((c = comparer.Compare(array[mid], item)) == 0)\r
+                                       return true;\r
+\r
+                               if (c > 0)\r
+                               { top = mid; }\r
+                               else\r
+                               { bot = mid + 1; }\r
+\r
+                               mid = (bot + top) / 2;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               private int indexOf(T item)\r
+               {\r
+                       int ind;\r
+\r
+                       if (binarySearch(item, out ind))\r
+                               return ind;\r
+\r
+                       return -1;\r
+               }\r
+\r
+               #endregion\r
+               \r
+               #region Constructors\r
+\r
+               /// <summary>\r
+               /// Create a dynamic sorted array with a natural comparer\r
+               /// </summary>\r
+               public SortedArray() : this(8) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a dynamic sorted array with a natural comparer\r
+               /// and prescribed initial capacity.\r
+               /// </summary>\r
+               /// <param name="capacity">The capacity</param>\r
+               public SortedArray(int capacity) \r
+                       : this(ComparerBuilder.FromComparable<T>.Examine()) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a dynamic sorted array with an external comparer\r
+               /// </summary>\r
+               /// <param name="c">The comparer</param>\r
+               public SortedArray(IComparer<T> c) \r
+                       : this(8,c) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a dynamic sorted array with an external comparer\r
+               /// and prescribed initial capacity.\r
+               /// </summary>\r
+               /// <param name="capacity">The capacity</param>\r
+               /// <param name="c">The comparer</param>\r
+               public SortedArray(int capacity, IComparer<T> c) \r
+                       : this(capacity, c, HasherBuilder.ByPrototype<T>.Examine()) { }\r
+\r
+               /// <summary>\r
+               /// Create a dynamic sorted array with an external comparer, an external hasher\r
+               /// and prescribed initial capacity.\r
+               /// </summary>\r
+               /// <param name="capacity">The capacity</param>\r
+               /// <param name="c">The comparer</param>\r
+               /// <param name="h">The hasher (compatible)</param>\r
+               public SortedArray(int capacity, IComparer<T> c, IHasher<T> h) \r
+                       : base(capacity, h) { comparer = c; }\r
+\r
+               #endregion\r
+               \r
+               #region IIndexedSorted<T> Members\r
+\r
+               /// <summary>\r
+               /// Determine the number of items at or above a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountFrom(T bot)\r
+               {\r
+                       int lo;\r
+\r
+                       binarySearch(bot, out lo);\r
+                       return size - lo;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountFromTo(T bot, T top)\r
+               {\r
+                       int lo, hi;\r
+\r
+                       binarySearch(bot, out lo);\r
+                       binarySearch(top, out hi);\r
+                       return hi > lo ? hi - lo : 0;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountTo(T top)\r
+               {\r
+                       int hi;\r
+\r
+                       binarySearch(top, out hi);\r
+                       return hi;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items greater than or equal to a supplied value.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeFrom(T bot)\r
+               {\r
+                       int lo;\r
+\r
+                       binarySearch(bot, out lo);\r
+                       return new Range(this, lo, size - lo, true);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items between two supplied values.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)\r
+               {\r
+                       int lo, hi;\r
+\r
+                       binarySearch(bot, out lo);\r
+                       binarySearch(top, out hi);\r
+\r
+                       int sz = hi - lo;\r
+\r
+                       return new Range(this, lo, sz, true);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items less than a supplied value.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeTo(T top)\r
+               {\r
+                       int hi;\r
+\r
+                       binarySearch(top, out hi);\r
+                       return new Range(this, 0, hi, true);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the items of this\r
+               /// indexed sorted collection satisfying a certain predicate.\r
+               /// </summary>\r
+               /// <param name="f">The filter delegate defining the predicate.</param>\r
+               /// <returns>The new indexed sorted collection.</returns>\r
+               [Tested]\r
+               public IIndexedSorted<T> FindAll(Filter<T> f)\r
+               {\r
+                       SortedArray<T> res = new SortedArray<T>(comparer);\r
+                       int j = 0, rescap = res.array.Length;\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                       {\r
+                               T a = array[i];\r
+\r
+                               if (f(a))\r
+                               {\r
+                                       if (j == rescap) res.expand(rescap = 2 * rescap, j);\r
+\r
+                                       res.array[j++] = a;\r
+                               }\r
+                       }\r
+\r
+                       res.size = j;\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the results of\r
+               /// mapping all items of this list.\r
+               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
+               /// the items of this collection (with respect to the two given comparison \r
+               /// relations).\r
+               /// </summary>\r
+               /// <param name="m">The delegate definging the map.</param>\r
+               /// <param name="c">The comparion relation to use for the result.</param>\r
+               /// <returns>The new sorted collection.</returns>\r
+               [Tested]\r
+               public IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c)\r
+               {\r
+                       SortedArray<V> res = new SortedArray<V>(size, c);\r
+\r
+                       if (size > 0)\r
+                       {\r
+                               V oldv = res.array[0] = m(array[0]), newv;\r
+\r
+                               for (int i = 1; i < size; i++)\r
+                               {\r
+                                       if (c.Compare(oldv, newv = res.array[i] = m(array[i])) >= 0)\r
+                                               throw new ArgumentException("mapper not monotonic");\r
+\r
+                                       oldv = newv;\r
+                               }\r
+                       }\r
+\r
+                       res.size = size;\r
+                       return res;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISorted<T> Members\r
+\r
+               /// <summary>\r
+               /// Find the strict predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than or equal to the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the predecessor for.</param>\r
+               /// <returns>The predecessor.</returns>\r
+               [Tested]\r
+               public T Predecessor(T item)\r
+               {\r
+                       int lo;\r
+\r
+                       binarySearch(item, out lo);\r
+                       if (lo == 0)\r
+                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
+\r
+                       return array[lo - 1];\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the strict successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than or equal to the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the successor for.</param>\r
+               /// <returns>The successor.</returns>\r
+               [Tested]\r
+               public T Successor(T item)\r
+               {\r
+                       int hi;\r
+\r
+                       if (binarySearch(item, out hi)) hi++;\r
+\r
+                       if (hi >= size)\r
+                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
+\r
+                       return array[hi];\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak predecessor for.</param>\r
+               /// <returns>The weak predecessor.</returns>\r
+               [Tested]\r
+               public T WeakPredecessor(T item)\r
+               {\r
+                       int lo;\r
+\r
+                       if (!binarySearch(item, out lo)) lo--;\r
+\r
+                       if (lo < 0)\r
+                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
+\r
+                       return array[lo];\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak successor for.</param>\r
+               /// <returns>The weak successor.</returns>\r
+               [Tested]\r
+               public T WeakSuccessor(T item)\r
+               {\r
+                       int hi;\r
+\r
+                       binarySearch(item, out hi);\r
+                       if (hi >= size)\r
+                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
+\r
+                       return array[hi];\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Perform a search in the sorted collection for the ranges in which a\r
+               /// non-decreasing function from the item type to <code>int</code> is\r
+               /// negative, zero respectively positive. If the supplied cut function is\r
+               /// not non-decreasing, the result of this call is undefined.\r
+               /// </summary>\r
+               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
+               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
+               /// the <code>c.CompareTo(T that)</code> method.</param>\r
+               /// <param name="low">Returns the largest item in the collection, where the\r
+               /// cut function is negative (if any).</param>\r
+               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
+               /// on this collection.</param>\r
+               /// <param name="high">Returns the least item in the collection, where the\r
+               /// cut function is positive (if any).</param>\r
+               /// <param name="highIsValid">True if the cut function is positive somewhere\r
+               /// on this collection.</param>\r
+               /// <returns></returns>\r
+               [Tested]\r
+               public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)\r
+               {\r
+                       int lbest = -1, rbest = size;\r
+\r
+                       low = default(T);\r
+                       lowIsValid = false;\r
+                       high = default(T);\r
+                       highIsValid = false;\r
+\r
+                       int bot = 0, top = size, mid, comp = -1, sol;\r
+\r
+                       mid = top / 2;\r
+                       while (top > bot)\r
+                       {\r
+                               if ((comp = c.CompareTo(array[mid])) == 0)\r
+                                       break;\r
+\r
+                               if (comp < 0)\r
+                               { rbest = top = mid; }\r
+                               else\r
+                               { lbest = mid; bot = mid + 1; }\r
+\r
+                               mid = (bot + top) / 2;\r
+                       }\r
+\r
+                       if (comp != 0)\r
+                       {\r
+                               if (lbest >= 0) { lowIsValid = true; low = array[lbest]; }\r
+\r
+                               if (rbest < size) { highIsValid = true; high = array[rbest]; }\r
+\r
+                               return false;\r
+                       }\r
+\r
+                       sol = mid;\r
+                       bot = sol - 1;\r
+\r
+                       //Invariant: c.Compare(array[x]) < 0  when rbest <= x < size \r
+                       //           c.Compare(array[x]) >= 0 when x < bot)\r
+                       //(Assuming c.Compare monotonic)\r
+                       while (rbest > bot)\r
+                       {\r
+                               mid = (bot + rbest) / 2;\r
+                               if (c.CompareTo(array[mid]) < 0)\r
+                               { rbest = mid; }\r
+                               else\r
+                               { bot = mid + 1; }\r
+                       }\r
+\r
+                       if (rbest < size) { highIsValid = true; high = array[rbest]; }\r
+\r
+                       top = sol + 1;\r
+\r
+                       //Invariant: c.Compare(array[x]) > 0  when 0 <= x <= lbest\r
+                       //           c.Compare(array[x]) <= 0 when x>top)\r
+                       //(Assuming c.Compare monotonic)\r
+                       while (top > lbest)\r
+                       {\r
+                               mid = (lbest + top + 1) / 2;\r
+                               if (c.CompareTo(array[mid]) > 0)\r
+                               { lbest = mid; }\r
+                               else\r
+                               { top = mid - 1; }\r
+                       }\r
+\r
+                       if (lbest >= 0) { lowIsValid = true; low = array[lbest]; }\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot)\r
+               { return RangeFrom(bot); }\r
+\r
+\r
+               IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top)\r
+               { return RangeFromTo(bot, top); }\r
+\r
+\r
+               IDirectedEnumerable<T> ISorted<T>.RangeTo(T top)\r
+               { return RangeTo(top); }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a directed collection with the same items as this collection.\r
+               /// </summary>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeAll()\r
+               { return new Range(this, 0, size, true); }\r
+\r
+\r
+               /// <summary>\r
+               /// Add all the items from another collection with an enumeration order that \r
+               /// is increasing in the items.\r
+               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
+               /// not to be in increasing order.\r
+               /// </summary>\r
+               /// <param name="items">The collection to add.</param>\r
+               [Tested]\r
+               public void AddSorted(MSG.IEnumerable<T> items)\r
+               {\r
+                       //Unless items have <=1 elements we would expect it to be\r
+                       //too expensive to do repeated inserts, thus:\r
+                       updatecheck();\r
+\r
+                       int j = 0, i = 0, c = -1, itemcount = EnumerableBase<T>.countItems(items);\r
+                       SortedArray<T> res = new SortedArray<T>(size + itemcount, comparer);\r
+                       T lastitem = default(T);\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               while (i < size && (c = comparer.Compare(array[i], item)) <= 0)\r
+                               {\r
+                                       lastitem = res.array[j++] = array[i++];\r
+                                       if (c == 0)\r
+                                               goto next;\r
+                               }\r
+\r
+                               if (j > 0 && comparer.Compare(lastitem, item) >= 0)\r
+                                       throw new ArgumentException("Argument not sorted");\r
+\r
+                               lastitem = res.array[j++] = item;\r
+                       next :\r
+                               c = -1;\r
+                       }\r
+\r
+                       while (i < size) res.array[j++] = array[i++];\r
+\r
+                       size = j;\r
+                       array = res.array;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection above or at a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeFrom(T low)\r
+               {\r
+                       int lowind;\r
+\r
+                       binarySearch(low, out lowind);\r
+                       if (lowind == size)\r
+                               return;\r
+\r
+                       Array.Clear(array, lowind, size - lowind);\r
+                       size = lowind;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeFromTo(T low, T hi)\r
+               {\r
+                       int lowind, highind;\r
+\r
+                       binarySearch(low, out lowind);\r
+                       binarySearch(hi, out highind);\r
+                       if (highind <= lowind)\r
+                               return;\r
+\r
+                       Array.Copy(array, highind, array, lowind, size - highind);\r
+                       Array.Clear(array, size - highind + lowind, highind - lowind);\r
+                       size -= highind - lowind;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeTo(T hi)\r
+               {\r
+                       int highind;\r
+\r
+                       binarySearch(hi, out highind);\r
+                       if (highind == 0)\r
+                               return;\r
+\r
+                       Array.Copy(array, highind, array, 0, size - highind);\r
+                       Array.Clear(array, size - highind, highind);\r
+                       size = size - highind;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISequenced<T> Members\r
+\r
+               int ISequenced<T>.GetHashCode() { return sequencedhashcode(); }\r
+\r
+\r
+               bool ISequenced<T>.Equals(ISequenced<T> that) { return sequencedequals(that); }\r
+               \r
+               #endregion\r
+\r
+               #region IEditableCollection<T> Members\r
+               /// <summary>\r
+               /// The value is symbolic indicating the type of asymptotic complexity\r
+               /// in terms of the size of this collection (worst-case).\r
+               /// </summary>\r
+               /// <value>Speed.Log</value>\r
+               [Tested]\r
+               public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }\r
+\r
+\r
+               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
+\r
+\r
+               bool ICollection<T>.Equals(ICollection<T> that) \r
+               { return unsequencedequals(that); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains (an item equivalent to according to the\r
+               /// itemhasher) a particular value.\r
+               /// </summary>\r
+               /// <param name="item">The value to check for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public bool Contains(T item)\r
+               {\r
+                       int ind;\r
+\r
+                       return binarySearch(item, out ind);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public bool Find(ref T item)\r
+               {\r
+                       int ind;\r
+\r
+                       if (binarySearch(item, out ind))\r
+                       {\r
+                               item = array[ind];\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               //This should probably just be bool Add(ref T item); !!!\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found. Else, add the item to the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the item was added (hence not found).</returns>\r
+               [Tested]\r
+               public bool FindOrAdd(ref T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int ind;\r
+\r
+                       if (binarySearch(item, out ind))\r
+                       {\r
+                               item = array[ind];\r
+                               return true;\r
+                       }\r
+\r
+                       if (size == array.Length - 1) expand();\r
+\r
+                       Array.Copy(array, ind, array, ind + 1, size - ind);\r
+                       array[ind] = item;\r
+                       size++;\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
+               /// it is implementation dependent if this updates all equivalent copies in\r
+               /// the collection or just one.\r
+               /// </summary>\r
+               /// <param name="item">Value to update.</param>\r
+               /// <returns>True if the item was found and hence updated.</returns>\r
+               [Tested]\r
+               public bool Update(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int ind;\r
+\r
+                       if (binarySearch(item, out ind))\r
+                       {\r
+                               array[ind] = item;\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value; else add the value to the collection. \r
+               /// </summary>\r
+               /// <param name="item">Value to add or update.</param>\r
+               /// <returns>True if the item was found and updated (hence not added).</returns>\r
+               [Tested]\r
+               public bool UpdateOrAdd(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int ind;\r
+\r
+                       if (binarySearch(item, out ind))\r
+                       {\r
+                               array[ind] = item;\r
+                               return true;\r
+                       }\r
+\r
+                       if (size == array.Length - 1) expand();\r
+\r
+                       Array.Copy(array, ind, array, ind + 1, size - ind);\r
+                       array[ind] = item;\r
+                       size++;\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection. If the collection has bag\r
+               /// semantics only one copy equivalent to the supplied item is removed. \r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public bool Remove(T item)\r
+               {\r
+                       int ind;\r
+\r
+                       updatecheck();\r
+                       if (binarySearch(item, out ind))\r
+                       {\r
+                               Array.Copy(array, ind + 1, array, ind, size - ind - 1);\r
+                               array[--size] = default(T);\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection if found. If the collection\r
+               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
+               /// which one is implementation dependent. \r
+               /// If an item was removed, report a binary copy of the actual item removed in \r
+               /// the argument.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove on input.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public bool RemoveWithReturn(ref T item)\r
+               {\r
+                       int ind;\r
+\r
+                       updatecheck();\r
+                       if (binarySearch(item, out ind))\r
+                       {\r
+                               item = array[ind];\r
+                               Array.Copy(array, ind + 1, array, ind, size - ind - 1);\r
+                               array[--size] = default(T);\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in another collection from this one. \r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       //This is O(m*logn) with n bits extra storage\r
+                       //(Not better to collect the m items and sort them)\r
+                       updatecheck();\r
+\r
+                       int[] toremove = new int[(size >>5) + 1];\r
+                       int ind, j = 0;\r
+\r
+                       foreach (T item in items)\r
+                               if (binarySearch(item, out ind))\r
+                                       toremove[ind >>5] |= 1 << (ind & 31);\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                               if ((toremove[i >>5] & (1 << (i & 31))) == 0)\r
+                                       array[j++] = array[i];\r
+\r
+                       Array.Clear(array, j, size - j);\r
+                       size = j;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items not in some other collection from this one. \r
+               /// </summary>\r
+               /// <param name="items">The items to retain.</param>\r
+               [Tested]\r
+               public void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       //This is O(m*logn) with n bits extra storage\r
+                       //(Not better to collect the m items and sort them)\r
+                       updatecheck();\r
+\r
+                       int[] toretain = new int[(size >>5) + 1];\r
+                       int ind, j = 0;\r
+\r
+                       foreach (T item in items)\r
+                               if (binarySearch(item, out ind))\r
+                                       toretain[ind >>5] |= 1 << (ind & 31);\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                               if ((toretain[i >>5] & (1 << (i & 31))) != 0)\r
+                                       array[j++] = array[i];\r
+\r
+                       Array.Clear(array, j, size - j);\r
+                       size = j;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains all the values in another collection.\r
+               /// Multiplicities are not taken into account.\r
+               /// </summary>\r
+               /// <param name="items">The </param>\r
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+               [Tested]\r
+               public bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       int tmp;\r
+\r
+                       foreach (T item in items)\r
+                               if (!binarySearch(item, out tmp))\r
+                                       return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Count the number of items of the collection equal to a particular value.\r
+               /// Returns 0 if and only if the value is not in the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to count.</param>\r
+               /// <returns>The number of copies found (0 or 1).</returns>\r
+               [Tested]\r
+               public int ContainsCount(T item)\r
+               {\r
+                       int tmp;\r
+\r
+                       return binarySearch(item, out tmp) ? 1 : 0;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all (0 or 1) items equivalent to a given value.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               [Tested]\r
+               public void RemoveAllCopies(T item) { Remove(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this collection.\r
+               /// Only avaliable in DEBUG builds???\r
+               /// </summary>\r
+               /// <returns>True if check does not fail.</returns>\r
+               [Tested]\r
+               public override bool Check()\r
+               {\r
+                       bool retval = true;\r
+\r
+                       if (size > array.Length)\r
+                       {\r
+                               Console.WriteLine("Bad size ({0}) > array.Length ({1})", size, array.Length);\r
+                               return false;\r
+                       }\r
+\r
+                       for (int i = 0; i < size; i++)\r
+                       {\r
+                               if ((object)(array[i]) == null)\r
+                               {\r
+                                       Console.WriteLine("Bad element: null at index {0}", i);\r
+                                       return false;\r
+                               }\r
+\r
+                               if (i > 0 && comparer.Compare(array[i], array[i - 1]) <= 0)\r
+                               {\r
+                                       Console.WriteLine("Inversion at index {0}", i);\r
+                                       retval = false;\r
+                               }\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>False since this collection has set semantics</value>\r
+               [Tested]\r
+               public bool AllowsDuplicates { [Tested]get { return false; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to this collection if possible. If this collection has set\r
+               /// semantics, the item will be added if not already in the collection. If\r
+               /// bag semantics, the item will always be added.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True if item was added.</returns>\r
+               [Tested]\r
+               public bool Add(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int ind;\r
+\r
+                       if (binarySearch(item, out ind)) return false;\r
+\r
+                       insert(ind, item);\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add the elements from another collection to this collection. If this\r
+               /// collection has set semantics, only items not already in the collection\r
+               /// will be added.\r
+               /// </summary>\r
+               /// <param name="items">The items to add.</param>\r
+               [Tested]\r
+               public void AddAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       int toadd = EnumerableBase<T>.countItems(items), newsize = array.Length;\r
+\r
+                       while (newsize < size + toadd) { newsize *= 2; }\r
+\r
+                       T[] newarr = new T[newsize];\r
+\r
+                       toadd = 0;\r
+                       foreach (T item in items) newarr[size + toadd++] = item;\r
+\r
+                       Sorting.IntroSort<T>(newarr, size, size + toadd, comparer);\r
+\r
+                       int j = 0, i = 0;\r
+                       T lastitem = default(T);\r
+\r
+                       //The following eliminates duplicates (including duplicates in input)\r
+                       //while merging the old and new collection\r
+                       for (int k = size, klimit = size + toadd; k < klimit; k++)\r
+                       {\r
+                               while (i < size && comparer.Compare(array[i], newarr[k]) <= 0)\r
+                                       lastitem = newarr[j++] = array[i++];\r
+\r
+                               if (j == 0 || comparer.Compare(lastitem, newarr[k]) < 0)\r
+                                       lastitem = newarr[j++] = newarr[k];\r
+                       }\r
+\r
+                       while (i < size) newarr[j++] = array[i++];\r
+\r
+                       Array.Clear(newarr, j, size + toadd - j);\r
+                       size = j;\r
+                       array = newarr;\r
+               }\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. Since this\r
+        /// collection has set semantics, only items not already in the collection\r
+        /// will be added.\r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
+        {\r
+            int toadd = EnumerableBase<U>.countItems(items), newsize = array.Length;\r
+\r
+            while (newsize < size + toadd) { newsize *= 2; }\r
+\r
+            T[] newarr = new T[newsize];\r
+\r
+            toadd = 0;\r
+            foreach (T item in items) newarr[size + toadd++] = item;\r
+\r
+            Sorting.IntroSort<T>(newarr, size, size + toadd, comparer);\r
+\r
+            int j = 0, i = 0;\r
+            T lastitem = default(T);\r
+\r
+            //The following eliminates duplicates (including duplicates in input)\r
+            //while merging the old and new collection\r
+            for (int k = size, klimit = size + toadd; k < klimit; k++)\r
+            {\r
+                while (i < size && comparer.Compare(array[i], newarr[k]) <= 0)\r
+                    lastitem = newarr[j++] = array[i++];\r
+\r
+                if (j == 0 || comparer.Compare(lastitem, newarr[k]) < 0)\r
+                    lastitem = newarr[j++] = newarr[k];\r
+            }\r
+\r
+            while (i < size) newarr[j++] = array[i++];\r
+\r
+            Array.Clear(newarr, j, size + toadd - j);\r
+            size = j;\r
+            array = newarr;\r
+        }\r
+\r
+        #endregion\r
+\r
+               #region IPriorityQueue<T> Members\r
+\r
+               /// <summary>\r
+               /// Find the current least item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The least item.</returns>\r
+               [Tested]\r
+               public T FindMin()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       return array[0];\r
+               }\r
+               \r
+               /// <summary>\r
+               /// Remove the least item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMin()\r
+               {\r
+                       updatecheck();\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       T retval = array[0];\r
+\r
+                       size--;\r
+                       Array.Copy(array, 1, array, 0, size);\r
+                       array[size] = default(T);\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the current largest item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The largest item.</returns>\r
+               [Tested]\r
+               public T FindMax()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       return array[size - 1];\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the largest item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMax()\r
+               {\r
+                       updatecheck();\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       T retval = array[size - 1];\r
+\r
+                       size--;\r
+                       array[size] = default(T);\r
+                       return retval;\r
+               }\r
+\r
+        /// <summary>\r
+        /// The comparer object supplied at creation time for this collection\r
+        /// </summary>\r
+        /// <value>The comparer</value>\r
+        public IComparer<T> Comparer { get { return comparer; } }\r
+\r
+               #endregion\r
+\r
+               #region IIndexed<T> Members\r
+\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <value>The i'th item of this list.</value>\r
+               /// <param name="i">the index to lookup</param>\r
+               [Tested]\r
+               public T this[int i]\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+                               if (i < 0 || i >= size)\r
+                                       throw new IndexOutOfRangeException();\r
+\r
+                               return array[i];\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going forwrds from the start.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of item from start.</returns>\r
+               [Tested]\r
+               public int IndexOf(T item) { return indexOf(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going backwords from the end.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of of item from the end.</returns>\r
+               [Tested]\r
+               public int LastIndexOf(T item){ return indexOf(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the item at a specific position of the list.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <param name="i">The index of the item to remove.</param>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T RemoveAt(int i)\r
+               {\r
+                       if (i < 0 || i >= size)\r
+                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
+\r
+                       updatecheck();\r
+\r
+                       T retval = array[i];\r
+\r
+                       size--;\r
+                       Array.Copy(array, i + 1, array, i, size - i);\r
+                       array[size] = default(T);\r
+                       return retval;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Remove all items in an index interval.\r
+               /// <exception cref="IndexOutOfRangeException"/>???. \r
+               /// </summary>\r
+               /// <param name="start">The index of the first item to remove.</param>\r
+               /// <param name="count">The number of items to remove.</param>\r
+               [Tested]\r
+               public void RemoveInterval(int start, int count)\r
+               {\r
+                       updatecheck();\r
+                       checkRange(start, count);\r
+                       Array.Copy(array, start + count, array, start, size - start - count);\r
+                       size -= count;\r
+                       Array.Clear(array, size, count);\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IDirectedEnumerable<T> Members\r
+\r
+               /// <summary>\r
+               /// Create a collection containing the same items as this collection, but\r
+               /// whose enumerator will enumerate the items backwards. The new collection\r
+               /// will become invalid if the original is modified. Method typicaly used as in\r
+               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
+               /// </summary>\r
+               /// <returns>The backwards collection.</returns>\r
+               [Tested]\r
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\r
+               { return Backwards(); }\r
+\r
+               #endregion\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/hashing/HashBag.cs b/mcs/class/Mono.C5/C5/hashing/HashBag.cs
new file mode 100644 (file)
index 0000000..080da67
--- /dev/null
@@ -0,0 +1,494 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A bag collection based on a hash table of (item,count) pairs. \r
+       /// </summary>\r
+       public class HashBag<T>: CollectionBase<T>, ICollection<T>\r
+       {\r
+               #region Fields\r
+               HashSet<KeyValuePair<T,int>> dict;\r
+               #endregion\r
+\r
+               #region Constructors\r
+               /// <summary>\r
+               /// Create a hash bag with the deafult item hasher.\r
+               /// </summary>\r
+               public HashBag()\r
+               {\r
+                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
+                       dict = new HashSet<KeyValuePair<T,int>>();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hash bag with an external item hasher.\r
+               /// </summary>\r
+               /// <param name="h">The external hasher.</param>\r
+               public HashBag(IHasher<T> h)\r
+               {\r
+                       itemhasher = h;\r
+                       dict = new HashSet<KeyValuePair<T,int>>(new KeyValuePairHasher<T,int>(h));\r
+               }\r
+               #endregion\r
+\r
+               #region IEditableCollection<T> Members\r
+\r
+               /// <summary>\r
+               /// The complexity of the Contains operation\r
+               /// </summary>\r
+               /// <value>Always returns Speed.Constant</value>\r
+               [Tested]\r
+               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }\r
+\r
+\r
+               [Tested]\r
+               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
+\r
+\r
+               [Tested]\r
+               bool ICollection<T>.Equals(ICollection<T> that)\r
+               { return unsequencedequals(that); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item is in the bag \r
+               /// </summary>\r
+               /// <param name="item">The item to look for</param>\r
+               /// <returns>True if bag contains item</returns>\r
+               [Tested]\r
+               public virtual bool Contains(T item)\r
+               { return dict.Contains(new KeyValuePair<T,int>(item, 0)); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a given one) is in the bag and\r
+               /// if so report the actual item object found.\r
+               /// </summary>\r
+               /// <param name="item">On entry, the item to look for.\r
+               /// On exit the item found, if any</param>\r
+               /// <returns>True if bag contains item</returns>\r
+               [Tested]\r
+               public virtual bool Find(ref T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
+\r
+                       if (dict.Find(ref p))\r
+                       {\r
+                               item = p.key;\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a given one) is in the bag and\r
+               /// if so replace the item object in the bag with the supplied one.\r
+               /// </summary>\r
+               /// <param name="item">The item object to update with</param>\r
+               /// <returns>True if item was found (and updated)</returns>\r
+               [Tested]\r
+               public virtual bool Update(T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
+\r
+                       updatecheck();\r
+\r
+                       //Note: we cannot just do dict.Update. There is of course a way\r
+                       //around if we use the implementation of hashset -which we do not want to do.\r
+                       //The hashbag is moreover mainly a proof of concept\r
+                       if (dict.Find(ref p))\r
+                       {\r
+                               p.key = item;\r
+                               dict.Update(p);\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a given one) is in the bag.\r
+               /// If found, report the actual item object in the bag,\r
+               /// else add the supplied one.\r
+               /// </summary>\r
+               /// <param name="item">On entry, the item to look for or add.\r
+               /// On exit the actual object found, if any.</param>\r
+               /// <returns>True if item was found</returns>\r
+               [Tested]\r
+               public virtual bool FindOrAdd(ref T item)\r
+               {\r
+                       updatecheck();\r
+                       if (Find(ref item))\r
+                               return true;\r
+\r
+                       Add(item);\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a supplied one) is in the bag and\r
+               /// if so replace the item object in the set with the supplied one; else\r
+               /// add the supplied one.\r
+               /// </summary>\r
+               /// <param name="item">The item to look for and update or add</param>\r
+               /// <returns>True if item was updated</returns>\r
+               [Tested]\r
+               public virtual bool UpdateOrAdd(T item)\r
+               {\r
+                       updatecheck();\r
+                       if (Update(item))\r
+                               return true;\r
+\r
+                       Add(item);\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one copy af an item from the bag\r
+               /// </summary>\r
+               /// <param name="item">The item to remove</param>\r
+               /// <returns>True if item was (found and) removed </returns>\r
+               [Tested]\r
+               public virtual bool Remove(T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
+\r
+                       updatecheck();\r
+                       if (dict.Find(ref p))\r
+                       {\r
+                               size--;\r
+                               if (p.value == 1)\r
+                                       dict.Remove(p);\r
+                               else\r
+                               {\r
+                                       p.value--;\r
+                                       dict.Update(p);\r
+                               }\r
+\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one copy of an item from the bag, reporting the actual matching item object.\r
+               /// </summary>\r
+               /// <param name="item">On entry the item to remove.\r
+               /// On exit, the actual removed item object.</param>\r
+               /// <returns>True if item was found.</returns>\r
+               [Tested]\r
+               public virtual bool RemoveWithReturn(ref T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
+\r
+                       updatecheck();\r
+                       if (dict.Find(ref p))\r
+                       {\r
+                               item = p.key;\r
+                               size--;\r
+                               if (p.value == 1)\r
+                                       dict.Remove(p);\r
+                               else\r
+                               {\r
+                                       p.value--;\r
+                                       dict.Update(p);\r
+                               }\r
+\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Remove all items in a supplied collection from this bag, counting multiplicities.\r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public virtual void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+                       foreach (T item in items)\r
+                               Remove(item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from the bag, resetting internal table to initial size.\r
+               /// </summary>\r
+               [Tested]\r
+               public virtual void Clear()\r
+               {\r
+                       updatecheck();\r
+                       dict.Clear();\r
+                       size = 0;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items *not* in a supplied collection from this bag,\r
+               /// counting multiplicities.\r
+               /// </summary>\r
+               /// <param name="items">The items to retain</param>\r
+               [Tested]\r
+               public virtual void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       HashBag<T> res = new HashBag<T>(itemhasher);\r
+\r
+                       foreach (T item in items)\r
+                               if (res.ContainsCount(item) < ContainsCount(item))\r
+                                       res.Add(item);\r
+\r
+                       dict = res.dict;\r
+                       size = res.size;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if all items in a supplied collection is in this bag\r
+               /// (counting multiplicities). \r
+               /// </summary>\r
+               /// <param name="items">The items to look for.</param>\r
+               /// <returns>True if all items are found.</returns>\r
+               [Tested]\r
+               public virtual bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       HashBag<T> res = new HashBag<T>(itemhasher);\r
+\r
+                       foreach (T item in items)\r
+                               if (res.ContainsCount(item) < ContainsCount(item))\r
+                                       res.Add(item);\r
+                               else\r
+                                       return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an array containing all items in this bag (in enumeration order).\r
+               /// </summary>\r
+               /// <returns>The array</returns>\r
+               [Tested]\r
+               public override T[] ToArray()\r
+               {\r
+                       T[] res = new T[size];\r
+                       int ind = 0;\r
+\r
+                       foreach (KeyValuePair<T,int> p in dict)\r
+                               for (int i = 0; i < p.value; i++)\r
+                                       res[ind++] = p.key;\r
+\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Count the number of times an item is in this set.\r
+               /// </summary>\r
+               /// <param name="item">The item to look for.</param>\r
+               /// <returns>The count</returns>\r
+               [Tested]\r
+               public virtual int ContainsCount(T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
+\r
+                       if (dict.Find(ref p))\r
+                               return p.value;\r
+\r
+                       return 0;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all copies of item from this set.\r
+               /// </summary>\r
+               /// <param name="item">The item to remove</param>\r
+               [Tested]\r
+               public virtual void RemoveAllCopies(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
+\r
+                       if (dict.Find(ref p))\r
+                       {\r
+                               size -= p.value;\r
+                               dict.Remove(p);\r
+                       }\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ICollection<T> Members\r
+\r
+\r
+               /// <summary>\r
+               /// Copy the items of this bag to part of an array.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if i is negative.\r
+               /// <exception cref="ArgumentException"/> if the array does not have room for the items.\r
+               /// </summary>\r
+               /// <param name="a">The array to copy to</param>\r
+               /// <param name="i">The starting index.</param>\r
+               [Tested]\r
+               public override void CopyTo(T[] a, int i)\r
+               {\r
+                       if (i < 0)\r
+                               throw new ArgumentOutOfRangeException();\r
+\r
+                       if (i + size > a.Length)\r
+                               throw new ArgumentException();\r
+\r
+                       foreach (KeyValuePair<T,int> p in dict)\r
+                               for (int j = 0; j < p.value; j++)\r
+                                       a[i++] = p.key;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+\r
+               /// <summary>\r
+               /// Report if this is a set collection.\r
+               /// </summary>\r
+               /// <value>Always true</value>\r
+               [Tested]\r
+               public virtual bool AllowsDuplicates { [Tested] get { return true; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to this bag.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>Always true</returns>\r
+               [Tested]\r
+               public virtual bool Add(T item)\r
+               {\r
+                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 1);\r
+\r
+                       updatecheck();\r
+                       if (dict.Find(ref p))\r
+                       {\r
+                               p.value++;\r
+                               dict.Update(p);\r
+                       }\r
+                       else\r
+                               dict.Add(p);\r
+\r
+                       size++;\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add all items of a collection to this set.\r
+               /// </summary>\r
+               /// <param name="items">The items to add</param>\r
+               [Tested]\r
+        public virtual void AddAll(MSG.IEnumerable<T> items)\r
+        {\r
+            foreach (T item in items)\r
+                Add(item);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. \r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        public virtual void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
+        {\r
+            foreach (T item in items)\r
+                Add(item);\r
+        }\r
+\r
+        #endregion\r
+\r
+               #region IEnumerable<T> Members\r
+               /// <summary>\r
+               /// Create an enumerator for this bag.\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               [Tested]\r
+               public override MSG.IEnumerator<T> GetEnumerator()\r
+               {\r
+                       int left;\r
+                       int mystamp = stamp;\r
+\r
+                       foreach (KeyValuePair<T,int> p in dict)\r
+                       {\r
+                               left = p.value;\r
+                               while (left > 0)\r
+                               {\r
+                                       if (mystamp != stamp)\r
+                                               throw new InvalidOperationException("Collection was changed");\r
+\r
+                                       left--;\r
+                                       yield return p.key;\r
+                               }\r
+                       }\r
+               }\r
+               #endregion\r
+\r
+               #region Diagnostics\r
+               /// <summary>\r
+               /// Test internal structure of data (invariants)\r
+               /// </summary>\r
+               /// <returns>True if pass</returns>\r
+               [Tested]\r
+               public virtual bool Check()\r
+               {\r
+                       bool retval = dict.Check();\r
+                       int count = 0;\r
+\r
+                       foreach (KeyValuePair<T,int> p in dict)\r
+                               count += p.value;\r
+\r
+                       if (count != size)\r
+                       {\r
+                               Console.WriteLine("count({0}) != size({1})", count, size);\r
+                               retval = false;\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+               #endregion\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/hashing/HashDictionary.cs b/mcs/class/Mono.C5/C5/hashing/HashDictionary.cs
new file mode 100644 (file)
index 0000000..325aee1
--- /dev/null
@@ -0,0 +1,72 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A generic dictionary class based on a hash set class <see cref="T:C5.HashSet!1"/>.\r
+       /// </summary>\r
+       public class HashDictionary<K,V>: DictionaryBase<K,V>, IDictionary<K,V>\r
+       {\r
+               /// <summary>\r
+               /// Create a hash dictionary using a default hasher for the keys.\r
+               /// Initial capacity of internal table will be 16 entries and threshold for \r
+               /// expansion is 66% fill.\r
+               /// </summary>\r
+               public HashDictionary()\r
+               {\r
+                       pairs = new HashSet<KeyValuePair<K,V>>(new KeyValuePairHasher<K,V>());\r
+               }\r
+\r
+               /// <summary>\r
+               /// Create a hash dictionary using a custom hasher for the keys.\r
+               /// Initial capacity of internal table will be 16 entries and threshold for \r
+               /// expansion is 66% fill.\r
+               /// </summary>\r
+               /// <param name="h">The external key hasher</param>\r
+               public HashDictionary(IHasher<K> h)\r
+               {\r
+                       pairs = new HashSet<KeyValuePair<K,V>>(new KeyValuePairHasher<K,V>(h));\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hash dictionary using a custom hasher and prescribing the \r
+               /// initial size of the dictionary and a non-default threshold for internal table expansion.\r
+               /// </summary>\r
+               /// <param name="capacity">The initial capacity. Will be rounded upwards to nearest\r
+               /// power of 2, at least 16.</param>\r
+               /// <param name="fill">The expansion threshold. Must be between 10% and 90%.</param>\r
+               /// <param name="h">The external key hasher</param>\r
+               public HashDictionary(int capacity, double fill, IHasher<K> h)\r
+               {\r
+                       KeyValuePairHasher<K,V> kvph = new KeyValuePairHasher<K,V>(h);\r
+\r
+                       pairs = new HashSet<KeyValuePair<K,V>>(capacity, fill, kvph);\r
+               }\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/hashing/HashTable.cs b/mcs/class/Mono.C5/C5/hashing/HashTable.cs
new file mode 100644 (file)
index 0000000..bc734d9
--- /dev/null
@@ -0,0 +1,1442 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+#define LINEARPROBING\r
+#define REFBUCKETnot\r
+#define SHRINKnot\r
+#define INTERHASHERnot\r
+#define RANDOMINTERHASHER\r
\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A set collection class based on linear hashing\r
+       /// </summary>\r
+       public class HashSet<T>: CollectionBase<T>, ICollection<T>\r
+       {\r
+               #region Feature\r
+               /// <summary>\r
+               /// Enum class to assist printing of compilation alternatives.\r
+               /// </summary>\r
+               [Flags]\r
+               public enum Feature: short\r
+               {\r
+                       /// <summary>\r
+                       /// Nothing\r
+                       /// </summary>\r
+                       Dummy = 0,\r
+                       /// <summary>\r
+                       /// Buckets are of reference type\r
+                       /// </summary>\r
+                       RefTypeBucket = 1,\r
+                       /// <summary>\r
+                       /// Primary buckets are of value type\r
+                       /// </summary>\r
+                       ValueTypeBucket = 2,\r
+                       /// <summary>\r
+                       /// Using linear probing to resolve index clashes\r
+                       /// </summary>\r
+                       LinearProbing = 4,\r
+                       /// <summary>\r
+                       /// Shrink table when very sparsely filled\r
+                       /// </summary>\r
+                       ShrinkTable = 8,\r
+                       /// <summary>\r
+                       /// Use chaining to resolve index clashes\r
+                       /// </summary>\r
+                       Chaining = 16,\r
+                       /// <summary>\r
+                       /// Use hash function on item hash code\r
+                       /// </summary>\r
+                       InterHasher = 32,\r
+                       /// <summary>\r
+                       /// Use a universal family of hash functions on item hash code\r
+                       /// </summary>\r
+                       RandomInterHasher = 64\r
+               }\r
+\r
+\r
+\r
+               static Feature features = Feature.Dummy\r
+#if REFBUCKET\r
+               | Feature.RefTypeBucket\r
+#else\r
+               | Feature.ValueTypeBucket\r
+#endif\r
+#if SHRINK\r
+               | Feature.ShrinkTable\r
+#endif\r
+#if LINEARPROBING\r
+               | Feature.LinearProbing\r
+#else\r
+               | Feature.Chaining\r
+#endif\r
+#if INTERHASHER\r
+               | Feature.InterHasher\r
+#elif RANDOMINTERHASHER\r
+               | Feature.RandomInterHasher\r
+#endif\r
+               ;\r
+\r
+\r
+               /// <summary>\r
+               /// Show which implementation features was chosen at compilation time\r
+               /// </summary>\r
+               public static Feature Features { get { return features; } }\r
+\r
+               #endregion\r
+\r
+               #region Fields\r
+\r
+               int indexmask, bits, bitsc, origbits; //bitsc==32-bits; indexmask==(1<<bits)-1;\r
+\r
+               Bucket[] table;\r
+\r
+#if !REFBUCKET\r
+               bool defaultvalid = false;\r
+\r
+               T defaultitem;\r
+#endif\r
+               double fillfactor = 0.66;\r
+\r
+               int resizethreshhold;\r
+\r
+#if RANDOMINTERHASHER\r
+#if DEBUG\r
+               uint randomhasher = 1529784659;\r
+#else\r
+               uint randomhasher = (2 * (uint)(new Random()).Next() + 1) * 1529784659;\r
+#endif\r
+#endif\r
+\r
+               #endregion\r
+\r
+               #region Bucket nested class(es)\r
+#if REFBUCKET\r
+               class Bucket\r
+               {\r
+                       internal T item;\r
+\r
+                       internal int hashval; //Cache!\r
+\r
+#if LINEARPROBING\r
+                       internal Bucket(T item, int hashval)\r
+                       {\r
+                               this.item = item;\r
+                               this.hashval = hashval;\r
+                       }\r
+#else\r
+                       internal Bucket overflow;\r
+\r
+                       internal Bucket(T item, int hashval, Bucket overflow)\r
+                       {\r
+                               this.item = item;\r
+                               this.hashval = hashval;\r
+                               this.overflow = overflow;\r
+                       }\r
+#endif\r
+               }\r
+#else\r
+               struct Bucket\r
+               {\r
+                       internal T item;\r
+\r
+                       internal int hashval; //Cache!\r
+\r
+#if LINEARPROBING\r
+                       internal Bucket(T item, int hashval)\r
+                       {\r
+                               this.item = item;\r
+                               this.hashval = hashval;\r
+                       }\r
+#else\r
+                       internal OverflowBucket overflow;\r
+\r
+\r
+                       internal Bucket(T item, int hashval)\r
+                       {\r
+                               this.item = item;\r
+                               this.hashval = hashval;\r
+                               this.overflow = OverflowBuckedefault(T);\r
+                       }\r
+#endif\r
+               }\r
+\r
+\r
+#if !LINEARPROBING\r
+               class OverflowBucket\r
+               {\r
+                       internal T item;\r
+\r
+                       internal int hashval; //Cache!\r
+\r
+                       internal OverflowBucket overflow;\r
+\r
+\r
+                       internal OverflowBucket(T item, int hashval, OverflowBucket overflow)\r
+                       {\r
+                               this.item = item;\r
+                               this.hashval = hashval;\r
+                               this.overflow = overflow;\r
+                       }\r
+               }\r
+#endif\r
+#endif\r
+\r
+               #endregion\r
+\r
+               #region Basic Util\r
+\r
+               bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }\r
+\r
+#if !REFBUCKET\r
+               bool isnull(T item) { return itemhasher.Equals(item, default(T)); }\r
+#endif\r
+\r
+               int gethashcode(T item) { return itemhasher.GetHashCode(item); }\r
+\r
+\r
+               int hv2i(int hashval)\r
+               {\r
+#if INTERHASHER\r
+                       //Note: *inverse  mod 2^32 is -1503427877\r
+                       return (int)(((uint)hashval * 1529784659) >>bitsc); \r
+#elif RANDOMINTERHASHER\r
+                       return (int)(((uint)hashval * randomhasher) >>bitsc); \r
+#else\r
+                       return indexmask & hashval;\r
+#endif\r
+               }\r
+\r
+\r
+               void expand()\r
+               {\r
+                       //Console.WriteLine(String.Format("Expand to {0} bits", bits+1));\r
+                       resize(bits + 1);\r
+               }\r
+\r
+\r
+               void shrink()\r
+               {\r
+                       if (bits > 3)\r
+                       {\r
+                               //Console.WriteLine(String.Format("Shrink to {0} bits", bits - 1));\r
+                               resize(bits - 1);\r
+                       }\r
+               }\r
+\r
+\r
+               void resize(int bits)\r
+               {\r
+                       //Console.WriteLine(String.Format("Resize to {0} bits", bits));\r
+                       this.bits = bits;\r
+                       bitsc = 32 - bits;\r
+                       indexmask = (1 << bits) - 1;\r
+\r
+                       Bucket[] newtable = new Bucket[indexmask + 1];\r
+\r
+                       for (int i = 0, s = table.Length; i < s; i++)\r
+                       {\r
+                               Bucket b = table[i];\r
+\r
+#if LINEARPROBING\r
+#if REFBUCKET\r
+                               if (b != null)\r
+                               {\r
+                                       int j = hv2i(b.hashval);\r
+\r
+                                       while (newtable[j] != null) { j = indexmask & (j + 1); }\r
+\r
+                                       newtable[j] = b;\r
+                               }\r
+#else\r
+                               if (!isnull(b.item))\r
+                               {\r
+                                       int j = hv2i(b.hashval);\r
+\r
+                                       while (!isnull(newtable[j].item)) { j = indexmask & (j + 1); }\r
+\r
+                                       newtable[j] = b;\r
+                               }\r
+#endif\r
+#else\r
+#if REFBUCKET\r
+                               while (b != null)\r
+                               {\r
+                                       int j = hv2i(b.hashval);\r
+\r
+                                       newtable[j] = new Bucket(b.item, b.hashval, newtable[j]);\r
+                                       b = b.overflow;\r
+                               }\r
+#else\r
+                               if (!isnull(b.item))\r
+                               {\r
+                                       insert(b.item, b.hashval, newtable);\r
+\r
+                                       OverflowBucket ob = b.overflow;\r
+\r
+                                       while (ob != null)\r
+                                       {\r
+                                               insert(ob.item, ob.hashval, newtable);\r
+                                               ob = ob.overflow;\r
+                                       }\r
+                               }\r
+#endif\r
+#endif\r
+                       }\r
+\r
+                       table = newtable;\r
+                       resizethreshhold = (int)(table.Length * fillfactor);\r
+                       //Console.WriteLine(String.Format("Resize to {0} bits done", bits));\r
+               }\r
+\r
+#if REFBUCKET \r
+#else\r
+#if LINEARPROBING\r
+#else\r
+               //Only for resize!!!\r
+               private void insert(T item, int hashval, Bucket[] t)\r
+               {\r
+                       int i = hv2i(hashval);\r
+                       Bucket b = t[i];\r
+\r
+                       if (!isnull(b.item))\r
+                       {\r
+                               t[i].overflow = new OverflowBucket(item, hashval, b.overflow);\r
+                       }\r
+                       else\r
+                               t[i] = new Bucket(item, hashval);\r
+               }\r
+#endif\r
+#endif\r
+\r
+               private bool searchoradd(ref T item, bool add, bool update)\r
+               {\r
+#if LINEARPROBING\r
+#if REFBUCKET\r
+                       int hashval = gethashcode(item);\r
+                       int i = hv2i(hashval);\r
+                       Bucket b = table[i];\r
+\r
+                       while (b != null)\r
+                       {\r
+                               if (equals(b.item, item))\r
+                               {\r
+                                       if (update)\r
+                                               b.item = item;\r
+                                       else\r
+                                               item = b.item;\r
+\r
+                                       return true;\r
+                               }\r
+\r
+                               b = table[i = indexmask & (i + 1)];\r
+                       }\r
+\r
+                       if (!add) goto notfound;\r
+\r
+                       table[i] = new Bucket(item, hashval);\r
+                       \r
+#else\r
+                       if (isnull(item))\r
+                       {\r
+                               if (defaultvalid)\r
+                               {\r
+                                       if (update)\r
+                                               defaultitem = item;\r
+                                       else\r
+                                               item = defaultitem;\r
+\r
+                                       return true;\r
+                               }\r
+\r
+                               if (!add) goto notfound;\r
+\r
+                               defaultvalid = true;\r
+                               defaultitem = item;\r
+                       }\r
+                       else\r
+                       {\r
+                               int hashval = gethashcode(item);\r
+                               int i = hv2i(hashval);\r
+                               T t = table[i].item;\r
+\r
+                               while (!isnull(t))\r
+                               {\r
+                                       if (equals(t, item))\r
+                                       {\r
+                                               if (update)\r
+                                                       table[i].item = item;\r
+                                               else\r
+                                                       item = t;\r
+\r
+                                               return true;\r
+                                       }\r
+\r
+                                       t = table[i = indexmask & (i + 1)].item;\r
+                               }\r
+\r
+                               if (!add) goto notfound;\r
+\r
+                               table[i] = new Bucket(item, hashval);\r
+                       }\r
+#endif\r
+#else\r
+#if REFBUCKET\r
+                       int hashval = gethashcode(item);\r
+                       int i = hv2i(hashval);\r
+                       Bucket b = table[i], bold = null;\r
+\r
+                       if (b != null)\r
+                       {\r
+                               while (b != null)\r
+                               {\r
+                                       if (equals(b.item, item))\r
+                                       {\r
+                                               if (update)\r
+                                                       b.item = item;\r
+                                               else\r
+                                                       item = b.item;\r
+\r
+                                               return true;\r
+                                       }\r
+\r
+                                       bold = b;\r
+                                       b = b.overflow;\r
+                               }\r
+\r
+                               if (!add) goto notfound;\r
+\r
+                               bold.overflow = new Bucket(item, hashval, null);\r
+                       }\r
+                       else\r
+                       {\r
+                               if (!add) goto notfound;\r
+\r
+                               table[i] = new Bucket(item, hashval, null);\r
+                       }\r
+#else\r
+                       if (isnull(item))\r
+                       {\r
+                               if (defaultvalid)\r
+                               {\r
+                                       if (update)\r
+                                               defaultitem = item;\r
+                                       else\r
+                                               item = defaultitem;\r
+\r
+                                       return true;\r
+                               }\r
+\r
+                               if (!add) goto notfound;\r
+\r
+                               defaultvalid = true;\r
+                               defaultitem = item;\r
+                       }\r
+                       else\r
+                       {\r
+                               int hashval = gethashcode(item);\r
+                               int i = hv2i(hashval);\r
+                               Bucket b = table[i];\r
+\r
+                               if (!isnull(b.item))\r
+                               {\r
+                                       if (equals(b.item, item))\r
+                                       {\r
+                                               if (update)\r
+                                                       table[i].item = item;\r
+                                               else\r
+                                                       item = b.item;\r
+\r
+                                               return true;\r
+                                       }\r
+\r
+                                       OverflowBucket ob = table[i].overflow;\r
+\r
+                                       if (ob == null)\r
+                                       {\r
+                                               if (!add) goto notfound;\r
+\r
+                                               table[i].overflow = new OverflowBucket(item, hashval, null);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               while (ob.overflow != null)\r
+                                               {\r
+                                                       if (equals(item, ob.item))\r
+                                                       {\r
+                                                               if (update)\r
+                                                                       ob.item = item;\r
+                                                               else\r
+                                                                       item = ob.item;\r
+\r
+                                                               return true;\r
+                                                       }\r
+\r
+                                                       ob = ob.overflow;\r
+                                               }\r
+\r
+                                               if (equals(item, ob.item))\r
+                                               {\r
+                                                       if (update)\r
+                                                               ob.item = item;\r
+                                                       else\r
+                                                               item = ob.item;\r
+\r
+                                                       return true;\r
+                                               }\r
+\r
+                                               if (!add) goto notfound;\r
+\r
+                                               ob.overflow = new OverflowBucket(item, hashval, null);\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (!add) goto notfound;\r
+\r
+                                       table[i] = new Bucket(item, hashval);\r
+                               }\r
+                       }\r
+#endif\r
+#endif\r
+                       size++;\r
+                       if (size > resizethreshhold)\r
+                               expand();\r
+               notfound :\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               private bool remove(ref T item)\r
+               {\r
+                       if (size == 0)\r
+                               return false;\r
+#if LINEARPROBING\r
+#if REFBUCKET\r
+                       int hashval = gethashcode(item);\r
+                       int index = hv2i(hashval);\r
+                       Bucket b = table[index];\r
+\r
+                       while (b != null)\r
+                       {\r
+                               if (equals(item, b.item))\r
+                               {\r
+                                       //ref\r
+                                       item = table[index];\r
+                                       table[index] = null;\r
+\r
+                                       //Algorithm R\r
+                                       int j = (index + 1) & indexmask;\r
+\r
+                                       b = table[j];\r
+                                       while (b != null)\r
+                                       {\r
+                                               int k = hv2i(b.hashval);\r
+\r
+                                               if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index))\r
+                                               //if (index > j ? (j < k && k <= index): (k <= index || j < k) )\r
+                                               {\r
+                                                       table[index] = b;\r
+                                                       table[j] = null;\r
+                                                       index = j;\r
+                                               }\r
+\r
+                                               j = (j + 1) & indexmask;\r
+                                               b = table[j];\r
+                                       }\r
+\r
+                                       goto found;\r
+                               }\r
+\r
+                               b = table[index = indexmask & (index + 1)];\r
+                       }\r
+                       return false;\r
+#else\r
+                       if (isnull(item))\r
+                       {\r
+                               if (!defaultvalid)\r
+                                       return false;\r
+\r
+                               //ref\r
+                               item = defaultitem;\r
+                               defaultvalid = false;\r
+                               defaultitem = default(T); //No spaceleaks!\r
+                       }\r
+                       else\r
+                       {\r
+                               int hashval = gethashcode(item);\r
+                               int index = hv2i(hashval);\r
+                               T t = table[index].item;\r
+\r
+                               while (!isnull(t))\r
+                               {\r
+                                       if (equals(item, t))\r
+                                       {\r
+                                               //ref\r
+                                               item = table[index].item;\r
+                                               table[index].item = default(T);\r
+\r
+                                               //algorithm R\r
+                                               int j = (index + 1) & indexmask;\r
+                                               Bucket b = table[j];\r
+\r
+                                               while (!isnull(b.item))\r
+                                               {\r
+                                                       int k = hv2i(b.hashval);\r
+\r
+                                                       if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index))\r
+                                                       {\r
+                                                               table[index] = b;\r
+                                                               table[j].item = default(T);\r
+                                                               index = j;\r
+                                                       }\r
+\r
+                                                       j = (j + 1) & indexmask;\r
+                                                       b = table[j];\r
+                                               }\r
+\r
+                                               goto found;\r
+                                       }\r
+\r
+                                       t = table[index = indexmask & (index + 1)].item;\r
+                               }\r
+\r
+                               return false;\r
+                       }\r
+#endif\r
+                       found :\r
+#else\r
+#if REFBUCKET\r
+                       int hashval = gethashcode(item);\r
+                       int index = hv2i(hashval);\r
+                       Bucket b = table[index], bold;\r
+\r
+                       if (b == null)\r
+                               return false;\r
+\r
+                       if (equals(item, b.item)) {\r
+                               //ref\r
+                               item = b.item;\r
+                               table[index] = b.overflow;\r
+                               }\r
+                       else\r
+                       {\r
+                               bold = b;\r
+                               b = b.overflow;\r
+                               while (b != null && !equals(item, b.item))\r
+                               {\r
+                                       bold = b;\r
+                                       b = b.overflow;\r
+                               }\r
+\r
+                               if (b == null)\r
+                                       return false;\r
+\r
+                               //ref\r
+                               item = b.item;\r
+                               bold.overflow = b.overflow;\r
+                       }\r
+                       \r
+#else\r
+                       if (isnull(item))\r
+                       {\r
+                               if (!defaultvalid)\r
+                                       return false;\r
+\r
+                               //ref\r
+                               item = defaultitem;\r
+                               defaultvalid = false;\r
+                               defaultitem = default(T); //No spaceleaks!\r
+                       }\r
+                       else\r
+                       {\r
+                               int hashval = gethashcode(item);\r
+                               int index = hv2i(hashval);\r
+                               Bucket b = table[index];\r
+                               OverflowBucket ob = b.overflow;\r
+\r
+                               if (equals(item, b.item))\r
+                               {\r
+                                       //ref\r
+                                       item = b.item;\r
+                                       if (ob == null)\r
+                                       {\r
+                                               table[index] = new Bucket();\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               b = new Bucket(ob.item, ob.hashval);\r
+                                               b.overflow = ob.overflow;\r
+                                               table[index] = b;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (ob == null)\r
+                                               return false;\r
+\r
+                                       if (equals(item, ob.item)) \r
+                                       {\r
+                                               //ref\r
+                                               item=ob.item;\r
+                                               table[index].overflow = ob.overflow;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               while (ob.overflow != null)\r
+                                                       if (equals(item, ob.overflow.item))\r
+                                                       {\r
+                                                               //ref\r
+                                                               item = ob.overflow.item;\r
+                                                               break;\r
+                                                       }\r
+                                                       else\r
+                                                               ob = ob.overflow;\r
+\r
+                                               if (ob.overflow == null)\r
+                                                       return false;\r
+\r
+                                               ob.overflow = ob.overflow.overflow;\r
+                                       }\r
+                               }\r
+                       }\r
+#endif\r
+#endif\r
+                       size--;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               private void clear()\r
+               {\r
+                       bits = origbits;\r
+                       bitsc = 32 - bits;\r
+                       indexmask = (1 << bits) - 1;\r
+                       size = 0;\r
+                       table = new Bucket[indexmask + 1];\r
+                       resizethreshhold = (int)(table.Length * fillfactor);\r
+#if !REFBUCKET\r
+                       defaultitem = default(T);\r
+                       defaultvalid = false;\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+               /// <summary>\r
+               /// Create a hash set with natural item hasher and default fill threshold (66%)\r
+               /// and initial table size (16).\r
+               /// </summary>\r
+               public HashSet() \r
+                       : this(HasherBuilder.ByPrototype<T>.Examine()) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hash set with external item hasher and default fill threshold (66%)\r
+               /// and initial table size (16).\r
+               /// </summary>\r
+               /// <param name="itemhasher">The external item hasher</param>\r
+               public HashSet(IHasher<T> itemhasher) \r
+                       : this(16, itemhasher) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hash set with external item hasher and default fill threshold (66%)\r
+               /// </summary>\r
+               /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>\r
+               /// <param name="itemhasher">The external item hasher</param>\r
+               public HashSet(int capacity, IHasher<T> itemhasher) \r
+                       : this(capacity, 0.66, itemhasher) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hash set with external item hasher.\r
+               /// </summary>\r
+               /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>\r
+               /// <param name="fill">Fill threshold (in range 10% to 90%)</param>\r
+               /// <param name="itemhasher">The external item hasher</param>\r
+               public HashSet(int capacity, double fill, IHasher<T> itemhasher)\r
+               {\r
+                       if (fill < 0.1 || fill > 0.9)\r
+                               throw new ArgumentException("Fill outside valid range [0.1, 0.9]");\r
+\r
+                       if (capacity <= 0)\r
+                               throw new ArgumentException("Non-negative capacity ");\r
+\r
+                       this.itemhasher = itemhasher;\r
+                       origbits = 4;\r
+                       while (capacity - 1 >>origbits > 0) origbits++;\r
+\r
+                       clear();\r
+               }\r
+\r
+\r
+\r
+               #endregion\r
+\r
+               #region IEditableCollection<T> Members\r
+\r
+               /// <summary>\r
+               /// The complexity of the Contains operation\r
+               /// </summary>\r
+               /// <value>Always returns Speed.Constant</value>\r
+               [Tested]\r
+               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }\r
+\r
+\r
+               [Tested]\r
+               int ICollection<T>.GetHashCode()\r
+               { return unsequencedhashcode(); }\r
+\r
+\r
+               [Tested]\r
+               bool ICollection<T>.Equals(ICollection<T> that)\r
+               { return unsequencedequals(that); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item is in the set \r
+               /// </summary>\r
+               /// <param name="item">The item to look for</param>\r
+               /// <returns>True if set contains item</returns>\r
+               [Tested]\r
+               public virtual bool Contains(T item) { return searchoradd(ref item, false, false); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a given one) is in the set and\r
+               /// if so report the actual item object found.\r
+               /// </summary>\r
+               /// <param name="item">On entry, the item to look for.\r
+               /// On exit the item found, if any</param>\r
+               /// <returns>True if set contains item</returns>\r
+               [Tested]\r
+               public virtual bool Find(ref T item) { return searchoradd(ref item, false, false); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a given one) is in the set and\r
+               /// if so replace the item object in the set with the supplied one.\r
+               /// </summary>\r
+               /// <param name="item">The item object to update with</param>\r
+               /// <returns>True if item was found (and updated)</returns>\r
+               [Tested]\r
+               public virtual bool Update(T item)\r
+               { updatecheck(); return searchoradd(ref item, false, true); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a given one) is in the set.\r
+               /// If found, report the actual item object in the set,\r
+               /// else add the supplied one.\r
+               /// </summary>\r
+               /// <param name="item">On entry, the item to look for or add.\r
+               /// On exit the actual object found, if any.</param>\r
+               /// <returns>True if item was found</returns>\r
+               [Tested]\r
+               public virtual bool FindOrAdd(ref T item)\r
+               { updatecheck(); return searchoradd(ref item, true, false); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if an item (collection equal to a supplied one) is in the set and\r
+               /// if so replace the item object in the set with the supplied one; else\r
+               /// add the supplied one.\r
+               /// </summary>\r
+               /// <param name="item">The item to look for and update or add</param>\r
+               /// <returns>True if item was updated</returns>\r
+               [Tested]\r
+               public virtual bool UpdateOrAdd(T item)\r
+               { updatecheck(); return searchoradd(ref item, true, true); }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove an item from the set\r
+               /// </summary>\r
+               /// <param name="item">The item to remove</param>\r
+               /// <returns>True if item was (found and) removed </returns>\r
+               [Tested]\r
+               public virtual bool Remove(T item)\r
+               {\r
+                       updatecheck();\r
+                       if (remove(ref item))\r
+                       {\r
+#if SHRINK\r
+                               if (size<resizethreshhold/2 && resizethreshhold>8)\r
+                                       shrink();\r
+#endif\r
+                               return true;\r
+                       }\r
+                       else\r
+                               return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove an item from the set, reporting the actual matching item object.\r
+               /// </summary>\r
+               /// <param name="item">On entry the item to remove.\r
+               /// On exit, the actual removed item object.</param>\r
+               /// <returns>True if item was found.</returns>\r
+               [Tested]\r
+               public virtual bool RemoveWithReturn(ref T item)\r
+               {\r
+                       updatecheck();\r
+                       if (remove(ref item))\r
+                       {\r
+#if SHRINK\r
+                               if (size<resizethreshhold/2 && resizethreshhold>8)\r
+                                       shrink();\r
+#endif\r
+                               return true;\r
+                       }\r
+                       else\r
+                               return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in a supplied collection from this set.\r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public virtual void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       T jtem;\r
+\r
+                       foreach (T item in items)\r
+                       { jtem = item; remove(ref jtem); }\r
+#if SHRINK\r
+                       if (size < resizethreshhold / 2 && resizethreshhold > 16)\r
+                       {\r
+                               int newlength = table.Length;\r
+\r
+                               while (newlength >= 32 && newlength * fillfactor / 2 > size)\r
+                                       newlength /= 2;\r
+\r
+                               resize(newlength - 1);\r
+                       }\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from the set, resetting internal table to initial size.\r
+               /// </summary>\r
+               [Tested]\r
+               public virtual void Clear()\r
+               {\r
+                       updatecheck();\r
+                       clear();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items *not* in a supplied collection from this set.\r
+               /// </summary>\r
+               /// <param name="items">The items to retain</param>\r
+               [Tested]\r
+               public virtual void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       HashSet<T> t = (HashSet<T>)MemberwiseClone();\r
+\r
+                       t.Clear();\r
+\r
+                       //This only works for sets:\r
+                       foreach (T item in items)\r
+                               if (Contains(item))\r
+                               {\r
+                                       T jtem = item;\r
+\r
+                                       t.searchoradd(ref jtem, true, false);\r
+                               }\r
+\r
+                       table = t.table;\r
+                       size = t.size;\r
+#if !REFBUCKET\r
+                       defaultvalid = t.defaultvalid;\r
+                       defaultitem = t.defaultitem;\r
+#endif\r
+                       indexmask = t.indexmask;\r
+                       resizethreshhold = t.resizethreshhold;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if all items in a supplied collection is in this set\r
+               /// (ignoring multiplicities). \r
+               /// </summary>\r
+               /// <param name="items">The items to look for.</param>\r
+               /// <returns>True if all items are found.</returns>\r
+               [Tested]\r
+               public virtual bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       foreach (T item in items)\r
+                               if (!Contains(item))\r
+                                       return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an array containing all items in this set (in enumeration order).\r
+               /// </summary>\r
+               /// <returns>The array</returns>\r
+               [Tested]\r
+               public override T[] ToArray()\r
+               {\r
+                       T[] res = new T[size];\r
+                       int index = 0;\r
+\r
+#if !REFBUCKET\r
+                       if (defaultvalid)\r
+                               res[index++] = defaultitem;\r
+#endif\r
+                       for (int i = 0; i < table.Length; i++)\r
+                       {\r
+                               Bucket b = table[i];\r
+#if LINEARPROBING\r
+#if REFBUCKET\r
+                               if (b != null)\r
+                                       res[index++] = b.item;\r
+#else\r
+                               if (!isnull(b.item))\r
+                                       res[index++] = b.item;\r
+#endif\r
+#else\r
+#if REFBUCKET\r
+                               while (b != null)\r
+                               {\r
+                                       res[index++] = b.item;\r
+                                       b = b.overflow;\r
+                               }\r
+#else\r
+                               if (!isnull(b.item))\r
+                               {\r
+                                       res[index++] = b.item;\r
+\r
+                                       OverflowBucket ob = b.overflow;\r
+\r
+                                       while (ob != null)\r
+                                       {\r
+                                               res[index++] = ob.item;\r
+                                               ob = ob.overflow;\r
+                                       }\r
+                               }\r
+#endif\r
+#endif\r
+                       }\r
+\r
+                       Debug.Assert(size == index);\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Count the number of times an item is in this set (either 0 or 1).\r
+               /// </summary>\r
+               /// <param name="item">The item to look for.</param>\r
+               /// <returns>1 if item is in set, 0 else</returns>\r
+               [Tested]\r
+               public virtual int ContainsCount(T item) { return Contains(item) ? 1 : 0; }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all (at most 1) copies of item from this set.\r
+               /// </summary>\r
+               /// <param name="item">The item to remove</param>\r
+               [Tested]\r
+               public virtual void RemoveAllCopies(T item) { Remove(item); }\r
+\r
+               #endregion\r
+\r
+               #region IEnumerable<T> Members\r
+\r
+               /// <summary>\r
+               /// Create an enumerator for this set.\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               [Tested]\r
+               public override MSG.IEnumerator<T> GetEnumerator()\r
+               {\r
+                       int index = -1;\r
+                       int mystamp = stamp;\r
+                       int len = table.Length;\r
+\r
+#if LINEARPROBING\r
+#if REFBUCKET\r
+                       while (++index < len)\r
+                       {\r
+                               if (mystamp != stamp) throw new InvalidOperationException();\r
+\r
+                               if (table[index] != null) yield table[index].item;\r
+                       }\r
+#else\r
+                       if (defaultvalid)\r
+                               yield return defaultitem;\r
+\r
+                       while (++index < len)\r
+                       {\r
+                               if (mystamp != stamp) throw new InvalidOperationException();\r
+\r
+                               T item = table[index].item;\r
+\r
+                               if (!isnull(item)) yield return item;\r
+                       }\r
+#endif\r
+#else\r
+#if REFBUCKET\r
+                       Bucket b = null;\r
+#else\r
+                       OverflowBucket ob = null;\r
+\r
+                       if (defaultvalid)\r
+                               yield defaultitem;\r
+#endif\r
+                       while (true)\r
+                       {\r
+                               if (mystamp != stamp)\r
+                                       throw new InvalidOperationException();\r
+\r
+#if REFBUCKET\r
+                               if (b == null || b.overflow == null)\r
+                               {\r
+                                       do\r
+                                       {\r
+                                               if (++index >= len) yield break;\r
+                                       } while (table[index] == null);\r
+\r
+                                       b = table[index];\r
+                                       yield b.item;\r
+                               }\r
+                               else\r
+                               {\r
+                                       b = b.overflow;\r
+                                       yield b.item;\r
+                               }\r
+#else\r
+                               if (ob != null && ob.overflow != null)\r
+                               {\r
+                                       ob = ob.overflow;\r
+                                       yield ob.item;\r
+                               }\r
+                               else if (index >= 0 && ob == null && (ob = table[index].overflow) != null)\r
+                               {\r
+                                       yield ob.item;\r
+                               }\r
+                               else\r
+                               {\r
+                                       do\r
+                                       {\r
+                                               if (++index >= len) yield break;\r
+                                       } while (isnull(table[index].item));\r
+\r
+                                       yield table[index].item;\r
+                                       ob = null;\r
+                               }\r
+#endif\r
+                       }\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+               /// <summary>\r
+               /// Report if this is a set collection.\r
+               /// </summary>\r
+               /// <value>Always false</value>\r
+               [Tested]\r
+               public virtual bool AllowsDuplicates { [Tested]get { return false; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to this set.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True if item was added (i.e. not found)</returns>\r
+               [Tested]\r
+               public virtual bool Add(T item)\r
+               {\r
+                       updatecheck();\r
+                       return !searchoradd(ref item, true, false);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add all items of a collection to this set.\r
+               /// </summary>\r
+               /// <param name="items">The items to add</param>\r
+               [Tested]\r
+               public virtual void AddAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+                       foreach (T item in items)\r
+                       {\r
+                               T jtem = item;\r
+\r
+                               searchoradd(ref jtem, true, false);\r
+                       }\r
+               }\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. Since this\r
+        /// collection has set semantics, only items not already in the collection\r
+        /// will be added.\r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        public virtual void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
+        {\r
+            updatecheck();\r
+            foreach (T item in items)\r
+            {\r
+                T jtem = item;\r
+\r
+                searchoradd(ref jtem, true, false);\r
+            }\r
+        }\r
+\r
+\r
+               #endregion\r
+\r
+               #region Diagnostics\r
+\r
+               /// <summary>\r
+               /// Test internal structure of data (invariants)\r
+               /// </summary>\r
+               /// <returns>True if pass</returns>\r
+               [Tested]\r
+               public virtual bool Check()\r
+               {\r
+                       int count = 0;\r
+#if LINEARPROBING\r
+                       int lasthole = table.Length - 1;\r
+\r
+#if REFBUCKET\r
+                       while (lasthole >= 0 && table[lasthole] != null)\r
+#else\r
+                       while (lasthole >= 0 && !isnull(table[lasthole].item))\r
+#endif\r
+                       {\r
+                               lasthole--;\r
+                               count++;\r
+                       }\r
+\r
+                       if (lasthole < 0)\r
+                       {\r
+                               Console.WriteLine("Table is completely filled!");\r
+                               return false;\r
+                       }\r
+\r
+                       for (int cellindex = lasthole + 1, s = table.Length; cellindex < s; cellindex++)\r
+                       {\r
+                               Bucket b = table[cellindex];\r
+                               int hashindex = hv2i(b.hashval);\r
+\r
+                               if (hashindex <= lasthole || hashindex > cellindex)\r
+                               {\r
+                                       Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, lasthole={4}", b.item, b.hashval, hashindex, cellindex, lasthole);\r
+                                       return false;\r
+                               }\r
+                       }\r
+\r
+                       int latesthole = -1;\r
+\r
+                       for (int cellindex = 0; cellindex < lasthole; cellindex++)\r
+                       {\r
+                               Bucket b = table[cellindex];\r
+\r
+#if REFBUCKET\r
+                               if (b != null)\r
+#else\r
+                               if (!isnull(b.item))\r
+#endif\r
+                               {\r
+                                       count++;\r
+\r
+                                       int hashindex = hv2i(b.hashval);\r
+\r
+                                       if (cellindex < hashindex && hashindex <= lasthole)\r
+                                       {\r
+                                               Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole);\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       latesthole = cellindex;\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       for (int cellindex = latesthole + 1; cellindex < lasthole; cellindex++)\r
+                       {\r
+                               Bucket b = table[cellindex];\r
+\r
+#if REFBUCKET\r
+                               if (b != null)\r
+#else\r
+                               if (!isnull(b.item))\r
+#endif\r
+                               {\r
+                                       count++;\r
+\r
+                                       int hashindex = hv2i(b.hashval);\r
+\r
+                                       if (hashindex <= latesthole || cellindex < hashindex)\r
+                                       {\r
+                                               Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole);\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       latesthole = cellindex;\r
+                               }\r
+                       }\r
+\r
+                       return true;\r
+#else\r
+                       bool retval = true;\r
+                       for (int i = 0, s = table.Length; i < s; i++)\r
+                       {\r
+                               int level = 0;\r
+                               Bucket b = table[i];\r
+#if REFBUCKET\r
+                               while (b != null)\r
+                               {\r
+                                       if (i != hv2i(b.hashval))\r
+                                       {\r
+                                               Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);\r
+                                               retval = false;\r
+                                       }\r
+\r
+                                       count++;\r
+                                       level++;\r
+                                       b = b.overflow;\r
+                               }\r
+#else\r
+                               if (!isnull(b.item))\r
+                               {\r
+                                       count++;\r
+                                       if (i != hv2i(b.hashval))\r
+                                       {\r
+                                               Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);\r
+                                               retval = false;\r
+                                       }\r
+\r
+                                       OverflowBucket ob = b.overflow;\r
+\r
+                                       while (ob != null)\r
+                                       {\r
+                                               level++;\r
+                                               count++;\r
+                                               if (i != hv2i(ob.hashval))\r
+                                               {\r
+                                                       Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);\r
+                                                       retval = false;\r
+                                               }\r
+\r
+                                               ob = ob.overflow;\r
+                                       }\r
+                               }\r
+#endif\r
+                       }\r
+\r
+                       if (count != size)\r
+                       {\r
+                               Console.WriteLine("size({0}) != count({1})", size, count);\r
+                               retval = false;\r
+                       }\r
+\r
+                       return retval;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Produce statistics on distribution of bucket sizes. Current implementation is incomplete.\r
+               /// </summary>\r
+               /// <returns>Histogram data.</returns>\r
+               [Tested(via = "Manually")]\r
+               public ISortedDictionary<int,int> BucketSizeDistribution()\r
+               {\r
+                       TreeDictionary<int,int> res = new TreeDictionary<int,int>(new IC());\r
+#if LINEARPROBING\r
+                       return res;\r
+#else\r
+                       for (int i = 0, s = table.Length; i < s; i++)\r
+                       {\r
+                               int count = 0;\r
+#if REFBUCKET\r
+                               Bucket b = table[i];\r
+\r
+                               while (b != null)\r
+                               {\r
+                                       count++;\r
+                                       b = b.overflow;\r
+                               }\r
+#else\r
+                               Bucket b = table[i];\r
+\r
+                               if (!isnull(b.item))\r
+                               {\r
+                                       count = 1;\r
+\r
+                                       OverflowBucket ob = b.overflow;\r
+\r
+                                       while (ob != null)\r
+                                       {\r
+                                               count++;\r
+                                               ob = ob.overflow;\r
+                                       }\r
+                               }\r
+#endif\r
+                               if (res.Contains(count))\r
+                                       res[count]++;\r
+                               else\r
+                                       res[count] = 1;\r
+                       }\r
+\r
+                       return res;\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/heaps/IntervalHeap.cs b/mcs/class/Mono.C5/C5/heaps/IntervalHeap.cs
new file mode 100644 (file)
index 0000000..2ad5589
--- /dev/null
@@ -0,0 +1,570 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using MSG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A priority queue class based on an interval heap data structure.\r
+       /// </summary>\r
+       public class IntervalHeap<T>: CollectionValueBase<T>, IPriorityQueue<T>\r
+       {\r
+               #region Fields\r
+               struct Interval\r
+               {\r
+                       internal T first, last;\r
+\r
+\r
+                       public override string ToString() { return String.Format("[{0}; {1}]", first, last); }\r
+               }\r
+\r
+\r
+\r
+               object syncroot = new object();\r
+\r
+        int stamp;\r
+\r
+        IComparer<T> comparer;\r
+\r
+               Interval[] heap;\r
+\r
+               int size;\r
+               #endregion\r
+\r
+               #region Util\r
+               void heapifyMin(int i)\r
+               {\r
+                       int j = i, minpt = j;\r
+                       T pv = heap[j].first, min = pv;\r
+\r
+                       while (true)\r
+                       {\r
+                               int l = 2 * j + 1, r = l + 1;\r
+                               T lv, rv, other;\r
+\r
+                               if (2 * l < size && comparer.Compare(lv = heap[l].first, min) < 0) { minpt = l; min = lv; }\r
+\r
+                if (2 * r < size && comparer.Compare(rv = heap[r].first, min) < 0) { minpt = r; min = rv; }\r
+\r
+                if (minpt == j)\r
+                                       break;\r
+\r
+                               other = heap[minpt].last;\r
+                               heap[j].first = min;\r
+                if (2 * minpt + 1 < size && comparer.Compare(pv, other) > 0)\r
+                { heap[minpt].last = pv; pv = other; }\r
+\r
+                               min = pv;\r
+                               j = minpt;\r
+                       }\r
+\r
+                       if (minpt != i)\r
+                               heap[minpt].first = min;\r
+               }\r
+\r
+\r
+               void heapifyMax(int i)\r
+               {\r
+                       int j = i, maxpt = j;\r
+                       T pv = heap[j].last, max = pv;\r
+\r
+                       while (true)\r
+                       {\r
+                               int l = 2 * j + 1, r = l + 1;\r
+                               T lv, rv, other;\r
+\r
+                if (2 * l + 1 < size && comparer.Compare(lv = heap[l].last, max) > 0) { maxpt = l; max = lv; }\r
+\r
+                if (2 * r + 1 < size && comparer.Compare(rv = heap[r].last, max) > 0) { maxpt = r; max = rv; }\r
+\r
+                if (maxpt == j)\r
+                                       break;\r
+\r
+                               other = heap[maxpt].first;\r
+                               heap[j].last = max;\r
+                if (comparer.Compare(pv, other) < 0)\r
+                {\r
+                                       heap[maxpt].first = pv;\r
+                                       pv = other;\r
+                               }\r
+\r
+                               max = pv;\r
+                               j = maxpt;\r
+                       }\r
+\r
+                       if (maxpt != i)\r
+                               heap[maxpt].last = max;\r
+               }\r
+\r
+\r
+               void bubbleUpMin(int i)\r
+               {\r
+                       if (i > 0)\r
+                       {\r
+                               T min = heap[i].first, iv = min;\r
+                               int p = (i + 1) / 2 - 1;\r
+\r
+                               while (i > 0)\r
+                               {\r
+                    if (comparer.Compare(iv, min = heap[p = (i + 1) / 2 - 1].first) < 0)\r
+                    {\r
+                                               heap[i].first = min; min = iv;\r
+                                               i = p;\r
+                                       }\r
+                                       else\r
+                                               break;\r
+                               }\r
+\r
+                               heap[i].first = iv;\r
+                       }\r
+               }\r
+\r
+\r
+               void bubbleUpMax(int i)\r
+               {\r
+                       if (i > 0)\r
+                       {\r
+                               T max = heap[i].last, iv = max;\r
+                               int p = (i + 1) / 2 - 1;\r
+\r
+                               while (i > 0)\r
+                               {\r
+                    if (comparer.Compare(iv, max = heap[p = (i + 1) / 2 - 1].last) > 0)\r
+                    {\r
+                                               heap[i].last = max; max = iv;\r
+                                               i = p;\r
+                                       }\r
+                                       else\r
+                                               break;\r
+                               }\r
+\r
+                               heap[i].last = iv;\r
+                       }\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+               /// <summary>\r
+               /// Create an interval heap with natural item comparer and default initial capacity (16)\r
+               /// </summary>\r
+               public IntervalHeap() : this(16) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an interval heap with external item comparer and default initial capacity (16)\r
+               /// </summary>\r
+               /// <param name="c">The external comparer</param>\r
+               public IntervalHeap(IComparer<T> c) : this(c,16) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an interval heap with natural item comparer and prescribed initial capacity\r
+               /// </summary>\r
+               /// <param name="capacity">The initial capacity</param>\r
+               public IntervalHeap(int capacity)  : this(ComparerBuilder.FromComparable<T>.Examine(),capacity) { }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an interval heap with external item comparer and prescribed initial capacity\r
+               /// </summary>\r
+               /// <param name="c">The external comparer</param>\r
+               /// <param name="capacity">The initial capacity</param>\r
+               public IntervalHeap(IComparer<T> c, int capacity)\r
+               {\r
+                       comparer = c;\r
+\r
+                       int length = 1;\r
+\r
+                       while (length < capacity) length <<= 1;\r
+\r
+                       heap = new Interval[length];\r
+               }\r
+               #endregion\r
+\r
+               #region IPriorityQueue<T> Members\r
+\r
+               /// <summary>\r
+               /// Find the current least item of this priority queue.\r
+               /// <exception cref="InvalidOperationException"/> if queue is empty\r
+               /// </summary>\r
+               /// <returns>The least item.</returns>\r
+               [Tested]\r
+               public T FindMin()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Heap is empty");\r
+\r
+                       return heap[0].first;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the least item from this  priority queue.\r
+               /// <exception cref="InvalidOperationException"/> if queue is empty\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMin()\r
+               {\r
+            stamp++;\r
+            if (size == 0)\r
+                throw new InvalidOperationException("Heap is empty");\r
+\r
+                       T retval = heap[0].first;;\r
+                       if (size == 1)\r
+                       {\r
+                               size = 0;\r
+                               heap[0].first = default(T);\r
+                       }\r
+                       else\r
+                       {\r
+                               int ind = (size - 1) / 2;\r
+\r
+                               if (size % 2 == 0)\r
+                               {\r
+                                       heap[0].first = heap[ind].last;\r
+                                       heap[ind].last = default(T);\r
+                               }\r
+                               else\r
+                               {\r
+                                       heap[0].first = heap[ind].first;\r
+                                       heap[ind].first = default(T);\r
+                               }\r
+\r
+                               size--;\r
+                               heapifyMin(0);\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the current largest item of this priority queue.\r
+               /// <exception cref="InvalidOperationException"/> if queue is empty\r
+               /// </summary>\r
+               /// <returns>The largest item.</returns>\r
+               [Tested]\r
+               public T FindMax()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Heap is empty");\r
+                       else if (size == 1)\r
+                               return heap[0].first;\r
+                       else\r
+                               return heap[0].last;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the largest item from this  priority queue.\r
+               /// <exception cref="InvalidOperationException"/> if queue is empty\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMax()\r
+               {\r
+            stamp++;\r
+            if (size == 0)\r
+                throw new InvalidOperationException("Heap is empty");\r
+\r
+                       T retval;\r
+\r
+                       if (size == 1)\r
+                       {\r
+                               size = 0;\r
+                               retval = heap[0].first;\r
+                               heap[0].first = default(T);\r
+                               return retval;\r
+                       }\r
+                       else\r
+                       {\r
+                               retval = heap[0].last;\r
+\r
+                               int ind = (size - 1) / 2;\r
+\r
+                               if (size % 2 == 0)\r
+                               {\r
+                                       heap[0].last = heap[ind].last;\r
+                                       heap[ind].last = default(T);\r
+                               }\r
+                               else\r
+                               {\r
+                                       heap[0].last = heap[ind].first;\r
+                                       heap[ind].first = default(T);\r
+                               }\r
+\r
+                               size--;\r
+                               heapifyMax(0);\r
+                               return retval;\r
+                       }\r
+               }\r
+\r
+\r
+        /// <summary>\r
+        /// The comparer object supplied at creation time for this collection\r
+        /// </summary>\r
+        /// <value>The comparer</value>\r
+        public IComparer<T> Comparer { get { return comparer; } }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True since this collection has bag semantics</value>\r
+               [Tested]\r
+               public bool AllowsDuplicates { [Tested]get { return true; } }\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>The distinguished object to use for locking to synchronize multithreaded access</value>\r
+               [Tested]\r
+               public object SyncRoot { [Tested]get { return syncroot; } }\r
+\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>True if this collection is empty.</value>\r
+               [Tested]\r
+               public bool IsEmpty { [Tested]get { return size == 0; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to this priority queue.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True</returns>\r
+               [Tested]\r
+               public bool Add(T item)\r
+               {\r
+            stamp++;\r
+            if (size == 0)\r
+                       {\r
+                               size = 1;\r
+                               heap[0].first = item;\r
+                               return true;\r
+                       }\r
+\r
+                       if (size == 2 * heap.Length)\r
+                       {\r
+                               Interval[] newheap = new Interval[2 * heap.Length];\r
+\r
+                               Array.Copy(heap, newheap, heap.Length);\r
+                               heap = newheap;\r
+                       }\r
+\r
+                       if (size % 2 == 0)\r
+                       {\r
+                               int i = size / 2, p = (i + 1) / 2 - 1;\r
+                               T tmp;\r
+\r
+                               size++;\r
+                if (comparer.Compare(item, tmp = heap[p].last) > 0)\r
+                {\r
+                                       heap[i].first = tmp;\r
+                                       heap[p].last = item;\r
+                                       bubbleUpMax(p);\r
+                               }\r
+                               else\r
+                               {\r
+                                       heap[i].first = item;\r
+                    if (comparer.Compare(item, heap[p].first) < 0)\r
+                        bubbleUpMin(i);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               int i = size / 2;\r
+                               T other = heap[i].first;\r
+\r
+                               size++;\r
+                if (comparer.Compare(item, other) < 0)\r
+                {\r
+                                       heap[i].first = item;\r
+                                       heap[i].last = other;\r
+                                       bubbleUpMin(i);\r
+                               }\r
+                               else\r
+                               {\r
+                                       heap[i].last = item;\r
+                                       bubbleUpMax(i);\r
+                               }\r
+                       }\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add the elements from another collection to this collection. \r
+               /// </summary>\r
+               /// <param name="items">The items to add.</param>\r
+               [Tested]\r
+               public void AddAll(MSG.IEnumerable<T> items)\r
+               {\r
+            //TODO: avoid incrementing stamp repeatedly\r
+                       foreach (T item in items)\r
+                               Add(item);\r
+               }\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. \r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
+        {\r
+            //TODO: avoid incrementing stamp repeatedly\r
+            foreach (T item in items)\r
+                Add(item);\r
+        }\r
+\r
+               #endregion\r
+\r
+        #region ICollection<T> members\r
+        /// <summary>\r
+        /// \r
+        /// </summary>\r
+        /// <value>The size of this collection</value>\r
+        [Tested]\r
+        public override int Count { [Tested]get { return size; } }\r
+\r
+\r
+        /// <summary>\r
+        /// The value is symbolic indicating the type of asymptotic complexity\r
+        /// in terms of the size of this collection (worst-case or amortized as\r
+        /// relevant).\r
+        /// </summary>\r
+        /// <value>A characterization of the speed of the \r
+        /// <code>Count</code> property in this collection.</value>\r
+        public override Speed CountSpeed { get { return Speed.Constant; } }\r
+\r
+        /// <summary>\r
+        /// Create an enumerator for the collection\r
+        /// <para>Note: the enumerator does *not* enumerate the items in sorted order, \r
+        /// but in the internal table order.</para>\r
+        /// </summary>\r
+        /// <returns>The enumerator(SIC)</returns>\r
+        [Tested]\r
+        public override MSG.IEnumerator<T> GetEnumerator()\r
+        {\r
+            int mystamp = stamp;\r
+            for (int i = 0; i < size; i++)\r
+            {\r
+                if (mystamp != stamp) throw new InvalidOperationException();\r
+                yield return i % 2 == 0 ? heap[i >> 1].first : heap[i >> 1].last;\r
+            }\r
+            yield break;\r
+        }\r
+\r
+\r
+        #endregion\r
+\r
+\r
+               #region Diagnostics\r
+               private bool check(int i, T min, T max)\r
+               {\r
+                       bool retval = true;\r
+                       Interval interval = heap[i];\r
+                       T first = interval.first, last = interval.last;\r
+\r
+                       if (2 * i + 1 == size)\r
+                       {\r
+                if (comparer.Compare(min, first) > 0)\r
+                {\r
+                                       Console.WriteLine("Cell {0}: parent.first({1}) > first({2})  [size={3}]", i, min, first, size);\r
+                                       retval = false;\r
+                               }\r
+\r
+                if (comparer.Compare(first, max) > 0)\r
+                {\r
+                                       Console.WriteLine("Cell {0}: first({1}) > parent.last({2})  [size={3}]", i, first, max, size);\r
+                                       retval = false;\r
+                               }\r
+\r
+                               return retval;\r
+                       }\r
+                       else\r
+                       {\r
+                if (comparer.Compare(min, first) > 0)\r
+                {\r
+                                       Console.WriteLine("Cell {0}: parent.first({1}) > first({2})  [size={3}]", i, min, first, size);\r
+                                       retval = false;\r
+                               }\r
+\r
+                if (comparer.Compare(first, last) > 0)\r
+                {\r
+                                       Console.WriteLine("Cell {0}: first({1}) > last({2})  [size={3}]", i, first, last, size);\r
+                                       retval = false;\r
+                               }\r
+\r
+                if (comparer.Compare(last, max) > 0)\r
+                {\r
+                                       Console.WriteLine("Cell {0}: last({1}) > parent.last({2})  [size={3}]", i, last, max, size);\r
+                                       retval = false;\r
+                               }\r
+\r
+                               int l = 2 * i + 1, r = l + 1;\r
+\r
+                               if (2 * l < size)\r
+                                       retval = retval && check(l, first, last);\r
+\r
+                               if (2 * r < size)\r
+                                       retval = retval && check(r, first, last);\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this collection.\r
+               /// Only avaliable in DEBUG builds???\r
+               /// </summary>\r
+               /// <returns>True if check does not fail.</returns>\r
+               [Tested]\r
+               public bool Check()\r
+               {\r
+                       if (size == 0)\r
+                               return true;\r
+\r
+                       if (size == 1)\r
+                               return (object)(heap[0].first) != null;\r
+\r
+                       return check(0, heap[0].first, heap[0].last);\r
+               }\r
+\r
+               #endregion\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/linkedlists/HashedLinkedLIst.cs b/mcs/class/Mono.C5/C5/linkedlists/HashedLinkedLIst.cs
new file mode 100644 (file)
index 0000000..dab3239
--- /dev/null
@@ -0,0 +1,1091 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+#define LISTORDERnot\r
+#define EXTLISTORDER\r
+using System;\r
+using System.Diagnostics;\r
+using MSG=System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A list collection based on a doubly linked list data structure with \r
+       /// a hash index mapping item to node.\r
+       /// </summary>\r
+       public class HashedLinkedList<T>: LinkedList<T>, IList<T>\r
+       {\r
+               #region Fields\r
+\r
+               HashDictionary<T,Node> dict;\r
+\r
+               //Invariant:  base.underlying == basehashedlist\r
+               HashedLinkedList<T> hashedunderlying;\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+\r
+               void init()\r
+               {\r
+#if LISTORDER || EXTLISTORDER\r
+                       maintaintags = true;\r
+#endif\r
+                       dict = new HashDictionary<T,Node>(itemhasher);\r
+               }\r
+               \r
+\r
+               /// <summary>\r
+               /// Create a hashed linked list with an external item hasher.\r
+               /// </summary>\r
+               /// <param name="itemhasher">The external hasher</param>\r
+               public HashedLinkedList(IHasher<T> itemhasher) : base(itemhasher) { init(); }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a hashed linked list with the natural item hasher.\r
+               /// </summary>\r
+               public HashedLinkedList() : base() { init(); }\r
+\r
+               #endregion\r
+\r
+               #region Util\r
+\r
+               bool contains(T item, out Node node)\r
+               {\r
+                       if (!dict.Find(item,out node))\r
+                               return false;\r
+                       else\r
+                               return insideview(node);\r
+               }\r
+\r
+               \r
+               void insert(Node succ, T item)\r
+               {\r
+                       Node newnode = new Node(item);\r
+\r
+                       if (dict.FindOrAdd(item, ref newnode))\r
+                               throw new ArgumentException("Item already in indexed list");\r
+\r
+                       insertNode(succ, newnode);\r
+               }\r
+\r
+\r
+               private bool dictremove(T item, out Node node)\r
+               {\r
+                       if (hashedunderlying == null)\r
+                       {\r
+                               if (!dict.Remove(item, out node))\r
+                                       return false;\r
+                       }\r
+                       else\r
+                       {\r
+                               //We cannot avoid calling dict twice - have to intersperse the listorder test!\r
+                               if (!contains(item, out node))\r
+                                       return false;\r
+\r
+                               dict.Remove(item);\r
+                       }\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               bool insideview(Node node)\r
+               {\r
+                       if (underlying == null)\r
+                               return true;\r
+\r
+#if LISTORDER\r
+                       if (maintaintags)\r
+                               return (startsentinel.tag < node.tag && (endsentinel.tag == 0 || node.tag < endsentinel.tag));\r
+                       else\r
+#elif EXTLISTORDER\r
+                       if (maintaintags)\r
+                               return (startsentinel.precedes(node) && node.precedes(endsentinel));\r
+                       else\r
+#endif\r
+                       if (2 * size < hashedunderlying.size)\r
+                       {\r
+                               Node cursor = startsentinel.next;\r
+\r
+                               while (cursor != endsentinel)\r
+                               {\r
+                                       if (cursor == node)\r
+                                               return true;\r
+\r
+                                       cursor = cursor.next;\r
+                               }\r
+\r
+                               return false;\r
+                       }\r
+                       else\r
+                       {\r
+                               Node cursor = hashedunderlying.startsentinel.next;\r
+\r
+                               while (cursor != startsentinel.next)\r
+                               {\r
+                                       if (cursor == node)\r
+                                               return false;\r
+\r
+                                       cursor = cursor.next;\r
+                               }\r
+\r
+                               cursor = endsentinel;\r
+                               while (cursor != hashedunderlying.endsentinel)\r
+                               {\r
+                                       if (cursor == node)\r
+                                               return false;\r
+\r
+                                       cursor = cursor.next;\r
+                               }\r
+\r
+                               return true;\r
+                       }\r
+               }\r
+\r
+\r
+               #endregion\r
+\r
+               #region IList<T> Members\r
+\r
+               /// <summary>\r
+               /// On this list, this indexer is read/write.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <value>The i'th item of this list.</value>\r
+               /// <param name="i">The index of the item to fetch or store.</param>\r
+               [Tested]\r
+               public override T this[int i]\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+                               modifycheck();\r
+                               return base[i];\r
+                       }\r
+                       [Tested]\r
+                       set\r
+                       {\r
+                               updatecheck();\r
+\r
+                               Node n = get(i);\r
+\r
+                               if (itemhasher.Equals(value, n.item))\r
+                               {\r
+                                       n.item = value;\r
+                                       dict.Update(value, n);\r
+                               }\r
+                               else if (!dict.FindOrAdd(value, ref n))\r
+                               {\r
+                                       dict.Remove(n.item);\r
+                                       n.item = value;\r
+                               }\r
+                               else\r
+                                       throw new ArgumentException("Item already in indexed list");\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at a specific index location in this list. \r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt; the size of the collection.</summary>\r
+               /// <exception cref="InvalidOperationException"/> if  the item is \r
+               /// already in the list.\r
+               /// <param name="i">The index at which to insert.</param>\r
+               /// <param name="item">The item to insert.</param>\r
+               [Tested]\r
+               public override void Insert(int i, T item)\r
+               {\r
+                       updatecheck();\r
+                       insert(i == size ? endsentinel : get(i), item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert into this list all items from an enumerable collection starting \r
+               /// at a particular index.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt; the size of the collection.\r
+               /// <exception cref="InvalidOperationException"/> if one of the items to insert is\r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="i">Index to start inserting at</param>\r
+               /// <param name="items">Items to insert</param>\r
+               [Tested]\r
+               public override void InsertAll(int i, MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       Node succ, node;\r
+                       int count = 0;\r
+\r
+                       succ = i == size ? endsentinel : get(i);\r
+                       node = succ.prev;\r
+#if LISTORDER\r
+                       //TODO: guard?\r
+                       int taglimit = i == size ? int.MaxValue : succ.tag - 1, thetag = node.tag;\r
+#elif EXTLISTORDER\r
+                       TagGroup taggroup = null;\r
+                       int taglimit = 0, thetag = 0;\r
+\r
+                       if (maintaintags)\r
+                               taggroup = gettaggroup(node, succ, out thetag, out taglimit);\r
+#endif\r
+                       foreach (T item in items)\r
+                       {\r
+                               Node tmp = new Node(item, node, null);\r
+\r
+                               if (!dict.FindOrAdd(item, ref tmp))\r
+                               {\r
+#if LISTORDER\r
+                                       if (maintaintags)\r
+                                               tmp.tag = thetag < taglimit ? ++thetag : thetag;\r
+#elif EXTLISTORDER\r
+                                       if (maintaintags)\r
+                                       {\r
+                                               tmp.tag = thetag < taglimit ? ++thetag : thetag;\r
+                                               tmp.taggroup = taggroup;\r
+                                       }\r
+#endif\r
+                                       node.next = tmp;\r
+                                       count++;\r
+                                       node = tmp;\r
+                               }\r
+                               else\r
+                                       throw new ArgumentException("Item already in indexed list");\r
+                       }\r
+\r
+#if EXTLISTORDER\r
+                       if (maintaintags)\r
+                       {\r
+                               taggroup.count += count;\r
+                               taggroup.first = succ.prev;\r
+                               taggroup.last = node;\r
+                       }\r
+#endif \r
+                       succ.prev = node;\r
+                       node.next = succ;\r
+                       size += count;\r
+                       if (hashedunderlying != null)\r
+                               hashedunderlying.size += count;\r
+#if LISTORDER\r
+                       if (maintaintags && node.tag == node.prev.tag)\r
+                               settag(node);\r
+#elif EXTLISTORDER\r
+                       if (maintaintags)\r
+                       {\r
+                               if (node.tag == node.prev.tag)\r
+                                       splittaggroup(taggroup);\r
+                       }\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item right before the first occurrence of some target item.\r
+               /// <exception cref="ArgumentException"/> if target     is not found\r
+               /// <exception cref="InvalidOperationException"/> if the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target before which to insert.</param>\r
+               [Tested]\r
+               public override void InsertBefore(T item, T target)\r
+               {\r
+                       updatecheck();\r
+\r
+                       Node node;\r
+\r
+                       if (!contains(target, out node))\r
+                               throw new ArgumentException("Target item not found");\r
+\r
+                       insert(node, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item right after the last(???) occurrence of some target item.\r
+               /// <exception cref="ArgumentException"/> if target     is not found\r
+               /// <exception cref="InvalidOperationException"/> if the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               /// <param name="target">The target after which to insert.</param>\r
+               [Tested]\r
+               public override void InsertAfter(T item, T target)\r
+               {\r
+                       updatecheck();\r
+\r
+                       Node node;\r
+\r
+                       if (!contains(target, out node))\r
+                               throw new ArgumentException("Target item not found");\r
+\r
+                       insert(node.next, item);\r
+               }\r
+\r
+\r
+\r
+               /// <summary>\r
+               /// Insert an item at the front of this list.\r
+               /// <exception cref="InvalidOperationException"/> if the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               [Tested]\r
+               public override void InsertFirst(T item)\r
+               {\r
+                       updatecheck();\r
+                       insert(startsentinel.next, item);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Insert an item at the back of this list.\r
+               /// <exception cref="InvalidOperationException"/> if  the item is \r
+               /// already in the list.\r
+               /// </summary>\r
+               /// <param name="item">The item to insert.</param>\r
+               [Tested]\r
+               public override void InsertLast(T item)\r
+               {\r
+                       updatecheck();\r
+                       insert(endsentinel, item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one item from the list: from the front if <code>FIFO</code>\r
+               /// is true, else from the back.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public override T Remove()\r
+               {\r
+                       T retval = base.Remove();\r
+\r
+                       dict.Remove(retval);\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one item from the front of the list.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public override T RemoveFirst()\r
+               {\r
+                       T retval = base.RemoveFirst();\r
+\r
+                       dict.Remove(retval);\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove one item from the back of the list.\r
+               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public override T RemoveLast()\r
+               {\r
+                       T retval = base.RemoveLast();\r
+\r
+                       dict.Remove(retval);\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a list view on this list. \r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the view would not fit into\r
+               /// this list.\r
+               /// </summary>\r
+               /// <param name="start">The index in this list of the start of the view.</param>\r
+               /// <param name="count">The size of the view.</param>\r
+               /// <returns>The new list view.</returns>\r
+               [Tested]\r
+               public override IList<T> View(int start, int count)\r
+               {\r
+                       checkRange(start, count);\r
+                       modifycheck();\r
+\r
+                       HashedLinkedList<T> retval = (HashedLinkedList<T>)MemberwiseClone();\r
+\r
+                       retval.underlying = retval.hashedunderlying = hashedunderlying != null ? hashedunderlying : this;\r
+                       retval.offset = start + offset;\r
+                       retval.startsentinel = start == 0 ? startsentinel : get(start - 1);\r
+                       retval.endsentinel = start + count == size ? endsentinel : get(start + count);\r
+                       retval.size = count;\r
+                       return retval;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Reverst part of the list so the items are in the opposite sequence order.\r
+               /// <exception cref="ArgumentException"/> if the count is negative.\r
+               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
+               /// into the list.\r
+               /// </summary>\r
+               /// <param name="start">The index of the start of the part to reverse.</param>\r
+               /// <param name="count">The size of the part to reverse.</param>\r
+               [Tested]\r
+               public override void Reverse(int start, int count)\r
+               {\r
+                       //Duplicating linkedlist<T> code to minimize cache misses\r
+                       updatecheck();\r
+                       checkRange(start, count);\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       Node a = get(start), b = get(start + count - 1);\r
+\r
+                       for (int i = 0; i < count / 2; i++)\r
+                       {\r
+                               T swap = a.item;a.item = b.item;b.item = swap;\r
+                               dict[a.item] = a;dict[b.item] = b;\r
+                               a = a.next;b = b.prev;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Shuffle the items of this list according to a specific random source.\r
+               /// </summary>\r
+               /// <param name="rnd">The random source.</param>\r
+               public override void Shuffle(Random rnd)\r
+               {\r
+                       updatecheck();\r
+\r
+                       ArrayList<T> a = new ArrayList<T>();\r
+\r
+                       a.AddAll(this);\r
+                       a.Shuffle(rnd);\r
+\r
+                       Node cursor = startsentinel.next;\r
+                       int j = 0;\r
+\r
+                       while (cursor != endsentinel)\r
+                       {\r
+                               dict[cursor.item = a[j++]] = cursor;\r
+                               cursor = cursor.next;\r
+                       }\r
+               }\r
+\r
+               #endregion              \r
+\r
+               #region IIndexed<T> Members\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going forwrds from the start.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of item from start.</returns>\r
+               [Tested]\r
+               public override int IndexOf(T item)\r
+               {\r
+                       Node node;\r
+\r
+                       modifycheck();\r
+                       if (!dict.Find(item, out node))\r
+                               return -1;\r
+#if LISTORDER\r
+                       if (maintaintags && !insideview(node))\r
+                               return -1;\r
+#elif EXTLISTORDER\r
+                       if (maintaintags && !insideview(node))\r
+                               return -1;\r
+#endif\r
+                       return base.IndexOf(item);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going backwords from the end.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of of item from the end.</returns>\r
+               [Tested]\r
+               public override int LastIndexOf(T item) { return IndexOf(item); }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the item at a specific position of the list.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <param name="i">The index of the item to remove.</param>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public override T RemoveAt(int i)\r
+               {\r
+                       T retval = base.RemoveAt(i);\r
+\r
+                       dict.Remove(retval);\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in an index interval.\r
+               /// <exception cref="IndexOutOfRangeException"/>???. \r
+               /// </summary>\r
+               /// <param name="start">The index of the first item to remove.</param>\r
+               /// <param name="count">The number of items to remove.</param>\r
+               [Tested]\r
+               public override void RemoveInterval(int start, int count)\r
+               {\r
+                       updatecheck();\r
+                       checkRange(start, count);\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       Node a, b;\r
+\r
+                       if (start <= size - start - count)\r
+                       {\r
+                               b = a = get(start);\r
+#if EXTLISTORDER\r
+                               Node c = a.prev;\r
+#endif\r
+                               for (int i = 0; i < count; i++)\r
+                               {\r
+                                       dict.Remove(b.item); \r
+#if EXTLISTORDER\r
+                                       if (maintaintags)\r
+                                       {\r
+                                               c.next = b;\r
+                                               b.prev = c;\r
+                                               removefromtaggroup(b);\r
+                                       }\r
+#endif\r
+                                       b = b.next;\r
+                               }\r
+\r
+                               a.prev.next = b;\r
+                               b.prev = a.prev;\r
+                       }\r
+                       else\r
+                       {\r
+                               a = b = get(start + count - 1);\r
+#if EXTLISTORDER\r
+                               Node c = b.next;\r
+#endif\r
+                               for (int i = 0; i < count; i++)\r
+                               {\r
+                                       dict.Remove(a.item); \r
+#if EXTLISTORDER\r
+                                       if (maintaintags)\r
+                                       {\r
+                                               c.prev = a;\r
+                                               a.next = c;\r
+                                               removefromtaggroup(a);\r
+                                       }\r
+#endif\r
+                                       a = a.prev;\r
+                               }\r
+\r
+                               a.next = b.next;\r
+                               b.next.prev = a;\r
+                       }\r
+\r
+                       size -= count;\r
+                       if (hashedunderlying != null)\r
+                               hashedunderlying.size -= count;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISequenced<T> Members\r
+\r
+               int ISequenced<T>.GetHashCode()\r
+               { modifycheck(); return sequencedhashcode(); }\r
+\r
+\r
+               bool ISequenced<T>.Equals(ISequenced<T> that)\r
+               { modifycheck(); return sequencedequals(that); }\r
+\r
+               #endregion\r
+\r
+               #region IEditableCollection<T> Members\r
+\r
+\r
+               /// <summary>\r
+               /// The value is symbolic indicating the type of asymptotic complexity\r
+               /// in terms of the size of this collection (worst-case or amortized as\r
+               /// relevant).\r
+               /// </summary>\r
+               /// <value>Speed.Constant</value>\r
+               [Tested]\r
+               public override Speed ContainsSpeed\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+#if LISTORDER || EXTLISTORDER\r
+                               return hashedunderlying == null || maintaintags ? Speed.Constant : Speed.Linear;\r
+#else\r
+                               return basehashedlist == null ? Speed.Constant : Speed.Linear;\r
+#endif\r
+                       }\r
+               }\r
+\r
+\r
+               int ICollection<T>.GetHashCode()\r
+               { modifycheck(); return unsequencedhashcode(); }\r
+\r
+\r
+               bool ICollection<T>.Equals(ICollection<T> that)\r
+               { modifycheck(); return unsequencedequals(that); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains (an item equivalent to according to the\r
+               /// itemhasher) a particular value.\r
+               /// </summary>\r
+               /// <param name="item">The value to check for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public override bool Contains(T item)\r
+               {\r
+                       Node node;\r
+\r
+                       modifycheck();\r
+                       return contains(item, out node);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public override bool Find(ref T item)\r
+               {\r
+                       Node node;\r
+\r
+                       modifycheck();\r
+                       if (contains(item, out node)) { item = node.item; return true; }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value. \r
+               /// </summary>\r
+               /// <param name="item">Value to update.</param>\r
+               /// <returns>True if the item was found and hence updated.</returns>\r
+               [Tested]\r
+               public override bool Update(T item)\r
+               {\r
+                       Node node;\r
+\r
+                       updatecheck();\r
+                       if (contains(item, out node)) { node.item = item; return true; }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found. Else, add the item to the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the item was found (hence not added).</returns>\r
+               [Tested]\r
+               public override bool FindOrAdd(ref T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       //This is an extended myinsert:\r
+                       Node node = new Node(item);\r
+\r
+                       if (!dict.FindOrAdd(item, ref node))\r
+                       {\r
+                               insertNode(endsentinel, node);\r
+                               return false;\r
+                       }\r
+\r
+                       if (!insideview(node))\r
+                               throw new ArgumentException("Item alredy in indexed list but outside view");\r
+\r
+                       item = node.item;\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value; else add the value to the collection. \r
+               /// </summary>\r
+               /// <param name="item">Value to add or update.</param>\r
+               /// <returns>True if the item was found and updated (hence not added).</returns>\r
+               [Tested]\r
+               public override bool UpdateOrAdd(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       Node node = new Node(item);\r
+\r
+                       /*if (basehashedlist == null)\r
+                       {\r
+                               if (!dict.UpdateOrAdd(item, node))\r
+                                       return false;\r
+                       }\r
+                       else\r
+                       {*/\r
+                               //NOTE: it is hard to do this without double access to the dictionary\r
+                               //in the update case\r
+                               if (dict.FindOrAdd(item, ref node))\r
+                               {\r
+                                       if (!insideview(node))\r
+                                               throw new ArgumentException("Item in indexed list but outside view");\r
+\r
+                                       //dict.Update(item, node);\r
+                                       node.item = item;\r
+                                       return true;\r
+                               }\r
+                       //}\r
+\r
+                       insertNode(endsentinel, node);\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection. \r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public override bool Remove(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       Node node;\r
+\r
+                       if (!dictremove(item, out node))\r
+                               return false;\r
+\r
+                       remove(node);\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection if found. \r
+               /// If an item was removed, report a binary copy of the actual item removed in \r
+               /// the argument.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove on input.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public override bool RemoveWithReturn(ref T item)\r
+               {\r
+                       Node node;\r
+\r
+                       updatecheck();\r
+                       if (!dictremove(item, out node))\r
+                               return false;\r
+\r
+                       item = node.item;\r
+                       remove(node);\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in another collection from this one. \r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public override void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       Node node;\r
+\r
+                       updatecheck();\r
+                       foreach (T item in items)\r
+                               if (dictremove(item, out node))\r
+                                       remove(node);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from this collection.\r
+               /// </summary>\r
+               [Tested]\r
+               public override void Clear()\r
+               {\r
+                       updatecheck();\r
+                       if (hashedunderlying == null)\r
+                               dict.Clear();\r
+                       else\r
+                               foreach (T item in this)\r
+                                       dict.Remove(item);\r
+\r
+                       base.Clear();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items not in some other collection from this one. \r
+               /// </summary>\r
+               /// <param name="items">The items to retain.</param>\r
+               [Tested]\r
+               public override void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+                       if (hashedunderlying == null)\r
+                       {\r
+                               HashDictionary<T,Node> newdict = new HashDictionary<T,Node>(itemhasher);\r
+\r
+                               foreach (T item in items)\r
+                               {\r
+                                       Node node;\r
+\r
+                                       if (dict.Remove(item, out node))\r
+                                               newdict.Add(item, node);\r
+                               }\r
+\r
+                               foreach (KeyValuePair<T,Node> pair in dict)\r
+                               {\r
+                                       Node n = pair.value, p = n.prev, s = n.next; s.prev = p; p.next = s;\r
+#if EXTLISTORDER\r
+                                       if (maintaintags)\r
+                                               removefromtaggroup(n);\r
+#endif\r
+                               }\r
+\r
+                               dict = newdict;\r
+                               size = dict.Count;\r
+                               //For a small number of items to retain it might be faster to \r
+                               //iterate through the list and splice out the chunks not needed\r
+                       }\r
+                       else\r
+                       {\r
+                               HashSet<T> newdict = new HashSet<T>(itemhasher);\r
+\r
+                               foreach (T item in this)\r
+                                       newdict.Add(item);\r
+\r
+                               foreach (T item in items)\r
+                                       newdict.Remove(item);\r
+\r
+                               Node n = startsentinel.next;\r
+\r
+                               while (n != endsentinel)\r
+                               {\r
+                                       if (newdict.Contains(n.item))\r
+                                       {\r
+                                               dict.Remove(n.item);\r
+                                               remove(n);\r
+                                       }\r
+\r
+                                       n = n.next;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains all the values in another collection\r
+               /// Multiplicities\r
+               /// are not taken into account.\r
+               /// </summary>\r
+               /// <param name="items">The </param>\r
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+               [Tested]\r
+               public override bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       Node node;\r
+\r
+                       modifycheck();\r
+                       foreach (T item in items)\r
+                               if (!contains(item, out node))\r
+                                       return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Count the number of items of the collection equal to a particular value.\r
+               /// Returns 0 if and only if the value is not in the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to count.</param>\r
+               /// <returns>The number of copies found.</returns>\r
+               [Tested]\r
+               public override int ContainsCount(T item) { return Contains(item) ? 1 : 0; }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items equivalent to a given value.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               [Tested]\r
+               public override void RemoveAllCopies(T item) { Remove(item); }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <value>False since this collection has set semantics.</value>\r
+               [Tested]\r
+        public override bool AllowsDuplicates { [Tested]get { return false; } }\r
+\r
+\r
+        //This is *not* the same as AddLast!!\r
+               /// <summary>\r
+               /// Add an item to this collection if possible. Since this collection has set\r
+               /// semantics, the item will be added if not already in the collection. \r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True if item was added.</returns>\r
+               [Tested]\r
+               public override bool Add(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       Node node = new Node(item);\r
+\r
+                       if (!dict.FindOrAdd(item, ref node))\r
+                       {\r
+                               insertNode(endsentinel, node);\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               //Note: this is *not* equivalent to InsertRange int this Set situation!!!\r
+               /// <summary>\r
+               /// Add the elements from another collection to this collection.\r
+               /// Only items not already in the collection\r
+               /// will be added.\r
+               /// </summary>\r
+               /// <param name="items">The items to add.</param>\r
+               [Tested]\r
+               public override void AddAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+                       foreach (T item in items)\r
+                       {\r
+                               Node node = new Node(item);\r
+\r
+                               if (!dict.FindOrAdd(item, ref node))\r
+                                       insertNode(endsentinel, node);\r
+                       }\r
+               }\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. \r
+        /// Only items not already in the collection\r
+        /// will be added.\r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        public override void AddAll<U>(MSG.IEnumerable<U> items) //where U:T\r
+        {\r
+            updatecheck();\r
+            foreach (T item in items)\r
+            {\r
+                Node node = new Node(item);\r
+\r
+                if (!dict.FindOrAdd(item, ref node))\r
+                    insertNode(endsentinel, node);\r
+            }\r
+        }\r
+\r
+        #endregion\r
+\r
+               #region IDirectedEnumerable<T> Members\r
+\r
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+\r
+               #endregion\r
+\r
+               #region Diagnostics\r
+               /// <summary>\r
+               /// Check the integrity of the internal data structures of this collection.\r
+               /// Only avaliable in DEBUG builds???\r
+               /// </summary>\r
+               /// <returns>True if check does not fail.</returns>\r
+               [Tested]\r
+               public override bool Check()\r
+               {\r
+                       if (!base.Check())\r
+                               return false;\r
+\r
+                       bool retval = true;\r
+\r
+                       if (hashedunderlying == null)\r
+                       {\r
+                               if (size != dict.Count)\r
+                               {\r
+                                       Console.WriteLine("list.size ({0}) != dict.Count ({1})", size, dict.Count);\r
+                                       retval = false;\r
+                               }\r
+\r
+                               Node n = startsentinel.next, n2;\r
+\r
+                               while (n != endsentinel)\r
+                               {\r
+                                       if (!dict.Find(n.item, out n2))\r
+                                       {\r
+                                               Console.WriteLine("Item in list but not dict: {0}", n.item);\r
+                                               retval = false;\r
+                                       }\r
+                                       else if (n != n2)\r
+                                       {\r
+                                               Console.WriteLine("Wrong node in dict for item: {0}", n.item);\r
+                                               retval = false;\r
+                                       }\r
+\r
+                                       n = n.next;\r
+                               }\r
+                       }\r
+\r
+                       return retval;\r
+               }\r
+               #endregion\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/linkedlists/LinkedList.cs b/mcs/class/Mono.C5/C5/linkedlists/LinkedList.cs
new file mode 100644 (file)
index 0000000..ebb9ae1
--- /dev/null
@@ -0,0 +1,2670 @@
+#if NET_2_0
+/*
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define LISTORDERnot
+#define EXTLISTORDER
+using System;
+using System.Diagnostics;
+using MSG=System.Collections.Generic;
+
+namespace C5
+{
+       /// <summary>
+       /// A list collection class based on a doubly linked list data structure.
+       /// </summary>
+       public class LinkedList<T>: SequencedBase<T>, IList<T>
+       {
+               #region Fields
+               /// <summary>
+               /// IExtensible.Add(T) always does AddLast(T), fIFO determines 
+               /// if T Remove() does RemoveFirst() or RemoveLast()
+               /// </summary>
+               bool fIFO = true;
+
+#if LISTORDER || EXTLISTORDER
+               /// <summary>
+               /// True if we maintain tags for node ordering (false for plain linked list, true for hashed linked list).
+               /// </summary>
+               protected bool maintaintags = false;
+#endif
+
+#if EXTLISTORDER
+               int taggroups;
+#endif
+
+               //Invariant:  startsentinel != null && endsentinel != null
+               //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel
+               //Else:      startsentinel.next == First && endsentinel.prev == Last)
+               /// <summary>
+               /// Node to the left of first node 
+               /// </summary>
+               protected Node startsentinel;
+               /// <summary>
+               /// Node to the right of last node
+               /// </summary>
+               protected Node endsentinel;
+               /// <summary>
+               /// Offset of this view in underlying list
+               /// </summary>
+               protected int offset;
+
+               /// <summary>
+               /// underlying list of theis view (or null)
+               /// </summary>
+               protected LinkedList<T> underlying;
+
+               #endregion
+
+               #region Util
+
+               bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }
+
+
+               /// <summary>
+               /// Check if it is valid to perform updates and increment stamp.
+               /// <exception cref="InvalidOperationException"/> if check fails.
+               /// <br/>This method should be called at the start of any public modifying methods.
+               /// </summary>
+               protected override void updatecheck()
+               {
+                       modifycheck();
+                       base.updatecheck();
+                       if (underlying != null)
+                               underlying.stamp++;
+               }
+
+
+               /// <summary>
+               /// Check if we are a view that the underlyinglist has only been updated through us.
+               /// <exception cref="InvalidOperationException"/> if check fails.
+               /// <br/>
+               /// This method should be called from enumerators etc to guard against 
+               /// modification of the base collection.
+               /// </summary>
+               protected void modifycheck()
+               {
+                       if (underlying != null && stamp != underlying.stamp)
+                               throw new InvalidOperationException("underlying list was modified");
+               }
+
+
+               /// <summary>
+               /// Check that the list has not been updated since a particular time.
+               /// <exception cref="InvalidOperationException"/> if check fails.
+               /// </summary>
+               /// <param name="stamp">The stamp indicating the time.</param>
+               protected override void modifycheck(int stamp)
+               {
+                       modifycheck();
+                       if (this.stamp != stamp)
+                               throw new InvalidOperationException("Collection was modified");
+               }
+
+
+               Node insert(Node succ, T item)
+               {
+                       Node newnode = new Node(item, succ.prev, succ);
+
+                       succ.prev.next = newnode;
+                       succ.prev = newnode;
+                       size++;
+                       if (underlying != null)
+                               underlying.size++;
+
+#if LISTORDER
+                       //TODO: replace with Debug.Assert(!maintaintags)
+                       if (maintaintags)
+                               settag(newnode);
+#elif EXTLISTORDER
+                       if (maintaintags)
+                               settag(newnode);
+#endif
+
+                       return newnode;
+               }
+
+
+               /// <summary>
+               /// Insert a Node before another one. Unchecked internal version.
+               /// </summary>
+               /// <param name="succ">The successor to be</param>
+               /// <param name="newnode">Node to insert</param>
+               protected void insertNode(Node succ, Node newnode)
+               {
+                       newnode.next = succ;
+                       newnode.prev = succ.prev;
+                       succ.prev.next = newnode;
+                       succ.prev = newnode;
+                       size++;
+                       if (underlying != null)
+                               underlying.size++;
+
+#if LISTORDER
+                       if (maintaintags)
+                               settag(newnode);
+#elif EXTLISTORDER
+                       if (maintaintags)
+                               settag(newnode);
+#endif
+               }
+
+
+               /// <summary>
+               /// Remove a node. Unchecked internal version.
+               /// </summary>
+               /// <param name="node">Node to remove</param>
+               /// <returns>The item of the removed node</returns>
+               protected T remove(Node node)
+               {
+                       node.prev.next = node.next;
+                       node.next.prev = node.prev;
+                       size--;
+                       if (underlying != null)
+                               underlying.size--;
+#if EXTLISTORDER
+                       if (maintaintags)
+                               removefromtaggroup(node);
+#endif
+                       return node.item;
+               }
+
+
+
+#if LISTORDER
+               //const int MaxTag = int.MaxValue;
+
+               protected void settag(Node node)
+               {
+                       //Note: the (global) sentinels have tag==0 and all other tags are positive.
+                       Node pred = node.prev, succ = node.next;
+                       if (pred.tag < succ.tag - 1)
+                       {
+                               //Note:
+                               //node.tag-pred.tag = (succ.tag-pred.tag) / 2 > 0
+                //succ.tag-node.tag = succ.tag-pred.tag - (succ.tag-pred.tag) / 2 > 0
+                               node.tag = pred.tag + (succ.tag-pred.tag) / 2;
+                               return;
+                       }
+
+                       if (succ.tag == 0 && pred.tag < int.MaxValue)
+                       {
+                               //Note:
+                               //node.tag-pred.tag = 1 + (int.MaxValue-pred.tag) / 2 > 0
+                               //node.tag <=int.MaxValue
+                               node.tag = pred.tag + 1 + (int.MaxValue - pred.tag) / 2;
+                               return;
+                       }
+
+                       node.tag = node.prev.tag;
+                       redistributetags(node);
+               }
+               
+               private void redistributetags(Node node)
+               {
+                       Node pred = node, succ = node;
+
+                       //Node start = underlying == null ? startsentinel : underlying.startsentinel;
+                       //Node end = underlying == null ? endsentinel : underlying.endsentinel;
+                       double limit = 1, bigt = Math.Pow(size, 1.0/29);//?????
+                       int bits = 1, count = 1, lowmask = 0, himask = 0, target = 0;
+
+                       do
+                       {
+                               bits++;
+                               lowmask = (1 << bits) - 1;
+                               himask = ~lowmask;
+                               target = node.tag & himask;
+                               while (pred.prev.tag > 0 && (pred.prev.tag & himask) == target)
+                               { count++; pred = pred.prev; }
+
+                               while (succ.next.tag > 0 && (succ.next.tag & himask) == target)
+                               { count++; succ = succ.next; }
+
+                               limit *= bigt;
+                       } while (count > limit);
+
+                       //redistibute tags
+                       //Console.WriteLine("Redistributing {0} tags at {1} bits around item {2}", count, bits, node.item);
+
+                       int delta = lowmask / (count+1);
+
+                       for (int i = 1; i <= count; i++)
+                       {
+                               pred.tag = target + i * delta;
+                               //Console.Write("({0} -> {1})", pred.item, pred.tag);
+                               pred = pred.next;
+                       }
+                       //Console.WriteLine("{0}:{1}:{2}/",count,size,Check());
+               }
+#elif EXTLISTORDER
+               const int wordsize = 32;
+
+               const int lobits = 3;
+
+               const int hibits = lobits + 1;
+
+               const int losize = 1 << lobits;
+
+               const int hisize = 1 << hibits;
+
+               const int logwordsize = 5;
+
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="pred"></param>
+               /// <param name="succ"></param>
+               /// <param name="lowbound"></param>
+               /// <param name="highbound"></param>
+               /// <returns></returns>
+               protected TagGroup gettaggroup(Node pred, Node succ, out int lowbound, out int highbound)
+               {
+                       TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
+
+                       if (predgroup == succgroup)
+                       {
+                               lowbound = pred.tag + 1;
+                               highbound = succ.tag - 1;
+                               return predgroup;
+                       }
+                       else if (predgroup.first != null)
+                       {
+                               lowbound = pred.tag + 1;
+                               highbound = int.MaxValue;
+                               return predgroup;
+                       }
+                       else if (succgroup.first != null)
+                       {
+                               lowbound = int.MinValue;
+                               highbound = succ.tag - 1;
+                               return succgroup;
+                       }
+                       else
+                       {
+                               lowbound = int.MinValue;
+                               highbound = int.MaxValue;
+                               return new TagGroup();
+                       }
+               }
+
+
+               /// <summary>
+               /// Put a tag on a node (already inserted in the list). Split taggroups and renumber as 
+               /// necessary.
+               /// </summary>
+               /// <param name="node">The node to tag</param>
+               protected void settag(Node node)
+               {
+                       Node pred = node.prev, succ = node.next;
+                       TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
+
+                       if (predgroup == succgroup)
+                       {
+                               node.taggroup = predgroup;
+                               predgroup.count++;
+                               if (pred.tag + 1 == succ.tag)
+                                       splittaggroup(predgroup);
+                               else
+                                       node.tag = (pred.tag + 1) / 2 + (succ.tag - 1) / 2;
+                       }
+                       else if (predgroup.first != null)
+                       {
+                               node.taggroup = predgroup;
+                               predgroup.last = node;
+                               predgroup.count++;
+                               if (pred.tag == int.MaxValue)
+                                       splittaggroup(predgroup);
+                               else
+                                       node.tag = pred.tag / 2 + int.MaxValue / 2 + 1;
+                       }
+                       else if (succgroup.first != null)
+                       {
+                               node.taggroup = succgroup;
+                               succgroup.first = node;
+                               succgroup.count++;
+                               if (succ.tag == int.MinValue)
+                                       splittaggroup(node.taggroup);
+                               else
+                                       node.tag = int.MinValue / 2 + (succ.tag - 1) / 2;
+                       }
+                       else
+                       {
+                               Debug.Assert(taggroups == 0);
+
+                               TagGroup newgroup = new TagGroup();
+
+                               taggroups = 1;
+                               node.taggroup = newgroup;
+                               newgroup.first = newgroup.last = node;
+                               newgroup.count = 1;
+                               return;
+                       }
+               }
+
+
+               /// <summary>
+               /// Remove a node from its taggroup.
+               /// <br/> When this is called, node must already have been removed from the underlying list
+               /// </summary>
+               /// <param name="node">The node to remove</param>
+               protected void removefromtaggroup(Node node)
+               {
+                       //
+                       TagGroup taggroup = node.taggroup;
+
+                       if (--taggroup.count == 0)
+                       {
+                               taggroups--;
+                               return;
+                       }
+
+                       if (node == taggroup.first)
+                               taggroup.first = node.next;
+
+                       if (node == taggroup.last)
+                               taggroup.last = node.prev;
+
+                       //node.taggroup = null;
+                       if (taggroup.count != losize)
+                               return;
+
+                       TagGroup otg;
+
+                       if ((otg = taggroup.first.prev.taggroup).count <= losize)
+                               taggroup.first = otg.first;
+                       else if ((otg = taggroup.last.next.taggroup).count <= losize)
+                               taggroup.last = otg.last;
+                       else
+                               return;
+
+                       Node n = otg.first;
+
+                       for (int i = 0, length = otg.count; i < length; i++)
+                       {
+                               n.taggroup = taggroup;
+                               n = n.next;
+                       }
+
+                       taggroup.count += otg.count;
+                       taggroups--;
+                       n = taggroup.first;
+
+                       const int ofs = wordsize - hibits;
+
+                       for (int i = 0, count = taggroup.count; i < count; i++)
+                       {
+                               n.tag = (i - losize) << ofs; //(i-8)<<28 
+                               n = n.next;
+                       }
+               }
+
+
+               /// <summary>
+               /// Split a tag group to make rom for more tags.
+               /// </summary>
+               /// <param name="taggroup">The tag group</param>
+               protected void splittaggroup(TagGroup taggroup)
+               {
+                       Node n = taggroup.first;
+                       int ptgt = taggroup.first.prev.taggroup.tag;
+                       int ntgt = taggroup.last.next.taggroup.tag;
+
+                       Debug.Assert(ptgt + 1 <= ntgt - 1);
+
+                       int ofs = wordsize - hibits;
+                       int newtgs = taggroup.count / hisize - 1;
+                       int tgtdelta = (int)((ntgt + 0.0 - ptgt) / (newtgs + 2)), tgtag = ptgt;
+
+                       tgtdelta = tgtdelta == 0 ? 1 : tgtdelta;
+                       for (int j = 0; j < newtgs; j++)
+                       {
+                               TagGroup newtaggroup = new TagGroup();
+
+                               newtaggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta);
+                               newtaggroup.first = n;
+                               newtaggroup.count = hisize;
+                               for (int i = 0; i < hisize; i++)
+                               {
+                                       n.taggroup = newtaggroup;
+                                       n.tag = (i - losize) << ofs; //(i-8)<<28 
+                                       n = n.next;
+                               }
+
+                               newtaggroup.last = n.prev;
+                       }
+
+                       int rest = taggroup.count - hisize * newtgs;
+
+                       taggroup.first = n;
+                       taggroup.count = rest;
+                       taggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta);                                    ofs--;
+                       for (int i = 0; i < rest; i++)
+                       {
+                               n.tag = (i - hisize) << ofs; //(i-16)<<27 
+                               n = n.next;
+                       }
+
+                       taggroup.last = n.prev;
+                       taggroups += newtgs;
+                       if (tgtag == ntgt)
+                               redistributetaggroups(taggroup);
+               }
+
+
+               private void redistributetaggroups(TagGroup taggroup)
+               {
+                       TagGroup pred = taggroup, succ = taggroup, tmp;
+                       double limit = 1, bigt = Math.Pow(taggroups, 1.0 / 30);//?????
+                       int bits = 1, count = 1, lowmask = 0, himask = 0, target = 0;
+
+                       do
+                       {
+                               bits++;
+                               lowmask = (1 << bits) - 1;
+                               himask = ~lowmask;
+                               target = taggroup.tag & himask;
+#if FIXME
+                               while ((tmp = pred.first.prev.taggroup).first != null && (tmp.tag & himask) == target)
+                               { count++; pred = tmp; }
+
+                               while ((tmp = succ.last.next.taggroup).last != null && (tmp.tag & himask) == target)
+                               { count++; succ = tmp; }
+#else
+                               for (tmp = pred.first.prev.taggroup; (tmp.first != null) && ((tmp.tag & himask) == target);)
+                               { count++; pred = tmp; }
+
+                               for (tmp = succ.last.next.taggroup; (tmp.last != null) && ((tmp.tag & himask) == target);)
+                               { count++; succ = tmp; }
+#endif
+
+                               limit *= bigt;
+                       } while (count > limit);
+
+                       //redistibute tags
+                       int lob = pred.first.prev.taggroup.tag, upb = succ.last.next.taggroup.tag;
+                       int delta = upb / (count + 1) - lob / (count + 1);
+
+                       Debug.Assert(delta > 0);
+                       for (int i = 0; i < count; i++)
+                       {
+                               pred.tag = lob + (i + 1) * delta;
+                               pred = pred.last.next.taggroup;
+                       }
+               }
+#endif
+
+               #endregion
+
+               #region Constructors
+               /// <summary>
+               /// Create a linked list with en external item hasher
+               /// </summary>
+               /// <param name="itemhasher">The external hasher</param>
+               public LinkedList(IHasher<T> itemhasher)
+               {
+                       this.itemhasher = itemhasher;
+#if EXTLISTORDER               
+                       startsentinel = new Node(default(T));
+                       endsentinel = new Node(default(T));
+                       startsentinel.next = endsentinel;
+                       endsentinel.prev = startsentinel;
+
+                       //It isused that these are different:
+                       startsentinel.taggroup = new TagGroup();
+                       startsentinel.taggroup.tag = int.MinValue;
+                       startsentinel.taggroup.count = 0;
+                       endsentinel.taggroup = new TagGroup();
+                       endsentinel.taggroup.tag = int.MaxValue;
+                       endsentinel.taggroup.count = 0;
+#else
+                       startsentinel = endsentinel = new Node(default(T));
+                       startsentinel.next = endsentinel.prev = startsentinel;
+#endif
+                       size = stamp = 0;
+               }
+
+
+               /// <summary>
+               /// Create a linked list with the nmatural item hasher
+               /// </summary>
+               public LinkedList() : this(HasherBuilder.ByPrototype<T>.Examine()) { }
+
+               #endregion
+
+               #region Nested classes
+
+               /// <summary>
+               /// An individual cell in the linked list
+               /// </summary>
+               protected class Node
+               {
+                       /// <summary>
+                       /// Previous-node reference
+                       /// </summary>
+                       public Node prev;
+
+                       /// <summary>
+                       /// Next-node reference
+                       /// </summary>
+                       public Node next;
+
+                       /// <summary>
+                       /// Node item
+                       /// </summary>
+                       public T item;
+#if LISTORDER
+                       internal int tag;
+#elif EXTLISTORDER
+                       internal int tag;
+
+                       internal TagGroup taggroup;
+
+
+                       internal bool precedes(Node that)
+                       {
+                               //Debug.Assert(taggroup != null, "taggroup field null");
+                               //Debug.Assert(that.taggroup != null, "that.taggroup field null");
+                               int t1 = taggroup.tag;
+                               int t2 = that.taggroup.tag;
+
+                               return t1 < t2 ? true : t1 > t2 ? false : tag < that.tag;
+                       }
+#endif
+                       /// <summary>
+                       /// Create node
+                       /// </summary>
+                       /// <param name="item">Item to insert</param>
+                       [Tested]
+                       public Node(T item)
+                       {
+                               this.item = item;
+                       }
+
+
+                       /// <summary>
+                       /// Create node, specifying predecessor and successor
+                       /// </summary>
+                       /// <param name="item"></param>
+                       /// <param name="prev"></param>
+                       /// <param name="next"></param>
+                       [Tested]
+                       public Node(T item, Node prev, Node next)
+                       {
+                               this.item = item; this.prev = prev; this.next = next;
+                       }
+
+
+                       /// <summary>
+                       /// Pretty print node
+                       /// </summary>
+                       /// <returns>Formatted node</returns>
+                       public override string ToString()
+                       {
+#if LISTORDER || EXTLISTORDER
+                               return String.Format("Node: (item={0}, tag={1})", item, tag);
+#else
+                               return String.Format("Node(item={0})", item);
+#endif
+                       }
+               }
+
+#if EXTLISTORDER               
+               /// <summary>
+               /// A group of nodes with the same high tag. Purpose is to be
+               /// able to tell the sequence order of two nodes without having to scan through
+               /// the list.
+               /// </summary>
+               protected class TagGroup
+               {
+                       internal int tag, count;
+
+                       internal Node first, last;
+
+
+                       /// <summary>
+                       /// Pretty print a tag group
+                       /// </summary>
+                       /// <returns>Formatted tag group</returns>
+                       public override string ToString()
+                       { return String.Format("TagGroup(tag={0}, cnt={1}, fst={2}, lst={3})", tag, count, first, last); }
+               }
+#endif
+
+               #endregion 
+
+               #region Range nested class
+
+               class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>
+               {
+                       int start, count, stamp;
+
+                       LinkedList<T> list;
+
+                       bool forwards;
+
+
+                       internal Range(LinkedList<T> list, int start, int count, bool forwards)
+                       {
+                               this.list = list;this.stamp = list.stamp;
+                               this.start = start;this.count = count;this.forwards = forwards;
+                       }
+
+
+                       [Tested]
+                       public override int Count { [Tested]get { list.modifycheck(stamp); return count; } }
+
+
+            public override Speed CountSpeed { get { list.modifycheck(stamp); return Speed.Constant; } }
+
+            [Tested]
+                       public override MSG.IEnumerator<T> GetEnumerator()
+                       {
+                               int togo = count;
+
+                               list.modifycheck(stamp);
+                               if (togo == 0)
+                                       yield break;
+
+                               Node cursor = forwards ? list.get(start) : list.get(start + count - 1);
+
+                               yield return cursor.item;
+                               while (--togo > 0)
+                               {
+                                       cursor = forwards ? cursor.next : cursor.prev;
+                                       list.modifycheck(stamp);
+                                       yield return cursor.item;
+                               }
+                       }
+
+
+                       [Tested]
+                       public IDirectedCollectionValue<T> Backwards()
+                       {
+                               list.modifycheck(stamp);
+
+                               Range b = (Range)MemberwiseClone();
+
+                               b.forwards = !forwards;
+                               return b;
+                       }
+
+
+                       [Tested]
+                       IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+
+                       [Tested]
+                       public EnumerationDirection Direction
+                       {
+                               [Tested]
+                               get
+                               { return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards; }
+                       }
+               }
+
+
+               #endregion
+
+               #region IList<T> Members
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> if this list is empty.
+               /// </summary>
+               /// <value>The first item in this list.</value>
+               [Tested]
+               public virtual T First
+               {
+                       [Tested]
+                       get
+                       {
+                               modifycheck();
+                               if (size == 0)
+                                       throw new InvalidOperationException("List is empty");
+
+                               return startsentinel.next.item;
+                       }
+               }
+
+
+               /// <summary>
+               /// <exception cref="InvalidOperationException"/> if this list is empty.
+               /// </summary>
+               /// <value>The last item in this list.</value>
+               [Tested]
+               public virtual T Last
+               {
+                       [Tested]
+                       get
+                       {
+                               modifycheck();
+                               if (size == 0)
+                                       throw new InvalidOperationException("List is empty");
+
+                               return endsentinel.prev.item;
+                       }
+               }
+
+
+               /// <summary>
+               /// Since <code>Add(T item)</code> always add at the end of the list,
+               /// this describes if list has FIFO or LIFO semantics.
+               /// </summary>
+               /// <value>True if the <code>Remove()</code> operation removes from the
+               /// start of the list, false if it removes from the end.</value>
+               [Tested]
+               public bool FIFO
+               {
+                       [Tested]
+                       get { modifycheck(); return fIFO; }
+                       [Tested]
+                       set { updatecheck(); fIFO = value; }
+               }
+
+
+               /// <summary>
+               /// On this list, this indexer is read/write.
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+               /// &gt;= the size of the collection.
+               /// </summary>
+               /// <value>The i'th item of this list.</value>
+               /// <param name="index">The index of the item to fetch or store.</param>
+               [Tested]
+               public virtual T this[int index]
+               {
+                       [Tested]
+                       get { modifycheck(); return get(index).item; }
+                       [Tested]
+                       set { updatecheck(); get(index).item = value; }
+               }
+
+
+               /// <summary>
+               /// Return the node at position n
+               /// </summary>
+               /// <param name="n"></param>
+               /// <returns></returns>
+               protected Node get(int n)
+               {
+                       if (n < 0 || n >= size)
+                               throw new IndexOutOfRangeException();
+                       else if (n < size / 2)
+                       {              // Closer to front
+                               Node node = startsentinel;
+
+                               for (int i = 0; i <= n; i++)
+                                       node = node.next;
+
+                               return node;
+                       }
+                       else
+                       {                            // Closer to end
+                               Node node = endsentinel;
+
+                               for (int i = size; i > n; i--)
+                                       node = node.prev;
+
+                               return node;
+                       }
+               }
+
+
+               /// <summary>
+               /// Insert an item at a specific index location in this list. 
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+               /// &gt; the size of the collection.</summary>
+               /// <param name="i">The index at which to insert.</param>
+               /// <param name="item">The item to insert.</param>
+               [Tested]
+               public virtual void Insert(int i, T item)
+               {
+                       updatecheck();
+                       insert(i == size ? endsentinel : get(i), item);
+               }
+
+
+               /// <summary>
+               /// Insert into this list all items from an enumerable collection starting 
+               /// at a particular index.
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+               /// &gt; the size of the collection.
+               /// </summary>
+               /// <param name="i">Index to start inserting at</param>
+               /// <param name="items">Items to insert</param>
+               [Tested]
+               public virtual void InsertAll(int i, MSG.IEnumerable<T> items)
+               {
+                       updatecheck();
+
+                       Node succ, node;
+                       int count = 0;
+
+                       succ = i == size ? endsentinel : get(i);
+                       node = succ.prev;
+#if LISTORDER
+                       //TODO: replace with Debug.Assert(!maintaintags)
+                       int taglimit = i == size ? int.MaxValue : succ.tag - 1, thetag = node.tag;
+#elif EXTLISTORDER
+                       TagGroup taggroup = null;
+                       int taglimit = 0, thetag = 0;
+
+                       if (maintaintags)
+                               taggroup = gettaggroup(node, succ, out thetag, out taglimit);
+#endif
+                       foreach (T item in items)
+                       {
+                               Node tmp = new Node(item, node, null);
+#if LISTORDER
+                               //TODO: remove
+                               if (maintaintags)
+                                       tmp.tag = thetag < taglimit ? ++thetag : thetag;
+#elif EXTLISTORDER
+                               if (maintaintags)
+                               {
+                                       tmp.tag = thetag < taglimit ? ++thetag : thetag;
+                                       tmp.taggroup = taggroup;
+                               }
+#endif
+                               node.next = tmp;
+                               count++;
+                               node = tmp;
+                       }
+#if EXTLISTORDER
+                       if (maintaintags)
+                       {
+                               taggroup.count += count;
+                               taggroup.first = succ.prev;
+                               taggroup.last = node;
+                       }
+#endif 
+                       succ.prev = node;
+                       node.next = succ;
+                       size += count;
+                       if (underlying != null)
+                               underlying.size += count;
+#if LISTORDER
+                       //TODO: remove 
+                       if (maintaintags && node.tag == node.prev.tag)
+                               settag(node);
+#elif EXTLISTORDER
+                       if (maintaintags)
+                       {
+                               if (node.tag == node.prev.tag)
+                                       splittaggroup(taggroup);
+                       }
+#endif
+               }
+
+
+               /// <summary>
+               /// Insert an item right before the first occurrence of some target item.
+               /// <exception cref="ArgumentException"/> if target     is not found
+               /// </summary>
+               /// <param name="item">The item to insert.</param>
+               /// <param name="target">The target before which to insert.</param>
+               [Tested]
+               public virtual void InsertBefore(T item, T target)
+               {
+                       updatecheck();
+
+                       Node node = startsentinel.next;
+                       int i = 0;
+
+                       if (!find(target, ref node, ref i))
+                               throw new ArgumentException("Target item not found");
+
+                       insert(node, item);
+               }
+
+
+               /// <summary>
+               /// Insert an item right after the last(???) occurrence of some target item.
+               /// <exception cref="ArgumentException"/> if target     is not found
+               /// </summary>
+               /// <param name="item">The item to insert.</param>
+               /// <param name="target">The target after which to insert.</param>
+               [Tested]
+               public virtual void InsertAfter(T item, T target)
+               {
+                       updatecheck();
+
+                       Node node = endsentinel.prev;
+                       int i = size - 1;
+
+                       if (!dnif(target, ref node, ref i))
+                               throw new ArgumentException("Target item not found");
+
+                       insert(node.next, item);
+               }
+
+
+               /// <summary>
+               /// Insert an item at the front of this list.
+               /// </summary>
+               /// <param name="item">The item to insert.</param>
+               [Tested]
+               public virtual void InsertFirst(T item)
+               {
+                       updatecheck();
+                       insert(startsentinel.next, item);
+               }
+
+               /// <summary>
+               /// Insert an item at the back of this list.
+               /// </summary>
+               /// <param name="item">The item to insert.</param>
+               [Tested]
+               public virtual void InsertLast(T item)
+               {
+                       updatecheck();
+                       insert(endsentinel, item);
+               }
+
+
+               /// <summary>
+               /// Create a new list consisting of the results of mapping all items of this
+               /// list.
+               /// </summary>
+               /// <param name="mapper">The delegate definging the map.</param>
+               /// <returns>The new list.</returns>
+               [Tested]
+        public IList<V> Map<V>(Mapper<T, V> mapper)
+        {
+            modifycheck();
+
+            LinkedList<V> retval = new LinkedList<V>();
+            return map<V>(mapper, retval);
+        }
+
+        /// <summary>
+        /// Create a new list consisting of the results of mapping all items of this
+        /// list. The new list will use a specified hasher for the item type.
+        /// </summary>
+        /// <typeparam name="V">The type of items of the new list</typeparam>
+        /// <param name="mapper">The delegate defining the map.</param>
+        /// <param name="hasher">The hasher to use for the new list</param>
+        /// <returns>The new list.</returns>
+        public IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher)
+        {
+            modifycheck();
+
+            LinkedList<V> retval = new LinkedList<V>(hasher);
+            return map<V>(mapper, retval);
+        }
+
+        private IList<V> map<V>(Mapper<T, V> mapper, LinkedList<V> retval)
+        {
+            Node cursor = startsentinel.next;
+            LinkedList<V>.Node mcursor = retval.startsentinel;
+
+#if LISTORDER
+                       //TODO: replace with Debug.Assert(!retval.maintaintags)
+                       double tagdelta = int.MaxValue / (size + 1.0);
+                       int count = 1;
+#elif EXTLISTORDER
+            double tagdelta = int.MaxValue / (size + 1.0);
+            int count = 1;
+            LinkedList<V>.TagGroup taggroup = null;
+
+            if (retval.maintaintags)
+            {
+                taggroup = new LinkedList<V>.TagGroup();
+                retval.taggroups = 1;
+                taggroup.count = size;
+            }
+#endif
+            while (cursor != endsentinel)
+            {
+                mcursor.next = new LinkedList<V>.Node(mapper(cursor.item), mcursor, null);
+                cursor = cursor.next;
+                mcursor = mcursor.next;
+#if LISTORDER
+                               //TODO: remove
+                               if (retval.maintaintags) mcursor.tag = (int)(tagdelta * count++);
+#elif EXTLISTORDER
+                if (retval.maintaintags)
+                {
+                    mcursor.taggroup = taggroup;
+                    mcursor.tag = (int)(tagdelta * count++);
+                }
+#endif
+            }
+
+            retval.endsentinel.prev = mcursor;
+            mcursor.next = retval.endsentinel;
+            retval.size = size; return retval;
+        }
+
+
+        /// <summary>
+               /// Remove one item from the list: from the front if <code>FIFO</code>
+               /// is true, else from the back.
+               /// <exception cref="InvalidOperationException"/> if this list is empty.
+               /// </summary>
+               /// <returns>The removed item.</returns>
+               [Tested]
+               public virtual T Remove()
+               {
+                       return fIFO ? RemoveFirst() : RemoveLast();
+               }
+
+
+               /// <summary>
+               /// Remove one item from the front of the list.
+               /// <exception cref="InvalidOperationException"/> if this list is empty.
+               /// </summary>
+               /// <returns>The removed item.</returns>
+               [Tested]
+               public virtual T RemoveFirst()
+               {
+                       updatecheck();
+                       if (size == 0)
+                throw new InvalidOperationException("List is empty");
+
+            T item = startsentinel.next.item;
+
+                       if (size == 1)
+                               clear();
+                       else
+                               remove(startsentinel.next);
+
+                       return item;
+               }
+
+
+               /// <summary>
+               /// Remove one item from the back of the list.
+               /// <exception cref="InvalidOperationException"/> if this list is empty.
+               /// </summary>
+               /// <returns>The removed item.</returns>
+               [Tested]
+               public virtual T RemoveLast()
+               {
+                       updatecheck();
+                       if (size == 0)
+                throw new InvalidOperationException("List is empty");
+
+            Node toremove = endsentinel.prev;
+                       T item = toremove.item;
+
+                       if (size == 1)
+                               clear();
+                       else
+                               remove(toremove);
+
+                       return item;
+               }
+
+
+               /// <summary>
+               /// Create a list view on this list. 
+        /// <exception cref="ArgumentOutOfRangeException"/> if the start or count is negative
+        /// <exception cref="ArgumentException"/> if the range does not fit within list.
+        /// </summary>
+        /// <param name="start">The index in this list of the start of the view.</param>
+               /// <param name="count">The size of the view.</param>
+               /// <returns>The new list view.</returns>
+               [Tested]
+               public virtual IList<T> View(int start, int count)
+               {
+                       modifycheck();
+                       checkRange(start, count);
+
+                       LinkedList<T> retval = (LinkedList<T>)MemberwiseClone();
+
+                       retval.underlying = underlying != null ? underlying : this;
+                       retval.offset = offset + start;
+                       retval.size = count;
+                       retval.startsentinel = start == 0 ? startsentinel : get(start - 1);
+                       retval.endsentinel = start + count == size ? endsentinel : get(start + count);
+#if DEBUG
+                       Check();
+#endif
+                       return retval;
+               }
+
+
+               /// <summary>
+               /// Null if this list is not a view.
+               /// </summary>
+        /// <value>Underlying list for view.</value>
+        [Tested]
+        public IList<T> Underlying { [Tested]get { modifycheck(); return underlying; } }
+
+
+        /// <summary>
+               /// </summary>
+               /// <value>Offset for this list view or 0 for a underlying list.</value>
+               [Tested]
+               public int Offset { [Tested]get { modifycheck(); return offset; } }
+
+
+               /// <summary>
+               /// Slide this list view along the underlying list.
+               /// <exception cref="InvalidOperationException"/> if this list is not a view.
+               /// <exception cref="ArgumentOutOfRangeException"/> if the operation
+               /// would bring either end of the view outside the underlying list.
+               /// </summary>
+               /// <param name="offset">The signed amount to slide: positive to slide
+               /// towards the end.</param>
+               [Tested]
+               public void Slide(int offset)
+               {
+                       modifycheck();
+                       if (underlying == null)
+                               throw new InvalidOperationException("List not a view");
+
+                       if (offset + this.offset < 0 || offset + this.offset + size > underlying.size)
+                               throw new ArgumentOutOfRangeException();
+
+                       if (offset == 0) return;
+
+                       if (offset > 0)
+                               for (int i = 0; i < offset; i++)
+                               {
+                                       endsentinel = endsentinel.next;
+                                       startsentinel = startsentinel.next;
+                               }
+                       else
+                               for (int i = 0; i < -offset; i++)
+                               {
+                                       endsentinel = endsentinel.prev;
+                                       startsentinel = startsentinel.prev;
+                               }
+
+                       this.offset += offset;
+               }
+
+
+               /// <summary>
+               /// Slide this list view along the underlying list, changing its size.
+               /// <exception cref="InvalidOperationException"/> if this list is not a view.
+               /// <exception cref="ArgumentOutOfRangeException"/> if the operation
+               /// would bring either end of the view outside the underlying list.
+               /// </summary>
+               /// <param name="offset">The signed amount to slide: positive to slide
+               /// towards the end.</param>
+               /// <param name="size">The new size of the view.</param>
+               [Tested]
+               public void Slide(int offset, int size)
+               {
+                       modifycheck();
+                       if (underlying == null)
+                               throw new InvalidOperationException("List not a view");
+
+                       if (offset + this.offset < 0 || offset + this.offset + size > underlying.size)
+                               throw new ArgumentOutOfRangeException();
+
+                       Node node = startsentinel;
+
+                       if (offset > 0)
+                               for (int i = 0; i < offset; i++)
+                                       node = node.next;
+                       else
+                               for (int i = 0; i < -offset; i++)
+                                       node = node.prev;
+
+                       startsentinel = node;
+
+                       int enddelta = offset + size - this.size;
+
+                       node = endsentinel;
+                       if (enddelta > 0)
+                               for (int i = 0; i < enddelta; i++)
+                                       node = node.next;
+                       else
+                               for (int i = 0; i < -enddelta; i++)
+                                       node = node.prev;
+
+                       endsentinel = node;
+                       this.size = size;
+                       this.offset += offset;
+               }
+
+
+               /// <summary>
+               /// Reverse the list so the items are in the opposite sequence order.
+               /// </summary>
+               [Tested]
+               public void Reverse() { Reverse(0, size); }
+
+
+               //Question: should we swap items or move nodes around?
+               //The first seems much more efficient unless the items are value types 
+               //with a large memory footprint.
+               //(Swapping will do count*3/2 T assignments, linking around will do 
+               // 4*count ref assignments; note that ref assignments are more expensive 
+               //than copying non-ref bits)
+               /// <summary>
+               /// Reverst part of the list so the items are in the opposite sequence order.
+               /// <exception cref="ArgumentException"/> if the count is negative.
+               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit
+               /// into the list.
+               /// </summary>
+               /// <param name="start">The index of the start of the part to reverse.</param>
+               /// <param name="count">The size of the part to reverse.</param>
+               [Tested]
+               public virtual void Reverse(int start, int count)
+               {
+                       updatecheck();
+                       checkRange(start, count);
+                       if (count == 0)
+                               return;
+
+                       Node a = get(start), b = get(start + count - 1);
+
+                       for (int i = 0; i < count / 2; i++)
+                       {
+                               T swap = a.item;a.item = b.item;b.item = swap;
+#if LISTORDER
+                               //Do nothing!
+#elif EXTLISTORDER
+                               //Neither
+#endif
+                               a = a.next;b = b.prev;
+                       }
+               }
+
+
+               /// <summary>
+               /// Check if this list is sorted according to a specific sorting order.
+               /// </summary>
+               /// <param name="c">The comparer defining the sorting order.</param>
+               /// <returns>True if the list is sorted, else false.</returns>
+               [Tested]
+               public bool IsSorted(IComparer<T> c)
+               {
+                       modifycheck();
+                       if (size <= 1)
+                               return true;
+
+                       Node node = startsentinel.next;
+                       T prevItem = node.item;
+
+                       node = node.next;
+                       while (node != endsentinel)
+                       {
+                               if (c.Compare(prevItem, node.item) > 0)
+                                       return false;
+                               else
+                               {
+                                       prevItem = node.item;
+                                       node = node.next;
+                               }
+                       }
+
+                       return true;
+               }
+
+
+               // Sort the linked list using mergesort
+               /// <summary>
+               /// Sort the items of the list according to a specific sorting order.
+               /// The sorting is stable.
+               /// </summary>
+               /// <param name="c">The comparer defining the sorting order.</param>
+               [Tested]
+               public void Sort(IComparer<T> c)
+               {
+                       updatecheck();
+
+                       // Build a linked list of non-empty runs.
+                       // The prev field in first node of a run points to next run's first node
+                       if (size == 0)
+                               return;
+
+#if EXTLISTORDER
+                       if (maintaintags && underlying != null)
+                       {
+                               Node cursor = startsentinel.next;
+
+                               while (cursor != endsentinel)
+                               {
+                                       cursor.taggroup.count--;
+                                       cursor = cursor.next;
+                               }
+                       }
+#endif
+                       Node runTail = startsentinel.next;
+                       Node prevNode = startsentinel.next;
+
+                       endsentinel.prev.next = null;
+                       while (prevNode != null)
+                       {
+                               Node node = prevNode.next;
+
+                               while (node != null && c.Compare(prevNode.item, node.item) <= 0)
+                               {
+                                       prevNode = node;
+                                       node = prevNode.next;
+                               }
+
+                               // Completed a run; prevNode is the last node of that run
+                               prevNode.next = null;   // Finish the run
+                               runTail.prev = node;    // Link it into the chain of runs
+                               runTail = node;
+                               if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0)
+                                       endsentinel.prev = prevNode;    // Update last pointer to point to largest
+
+                               prevNode = node;                // Start a new run
+                       }
+
+                       // Repeatedly merge runs two and two, until only one run remains
+                       while (startsentinel.next.prev != null)
+                       {
+                               Node run = startsentinel.next;
+                               Node newRunTail = null;
+
+                               while (run != null && run.prev != null)
+                               { // At least two runs, merge
+                                       Node nextRun = run.prev.prev;
+                                       Node newrun = mergeRuns(run, run.prev, c);
+
+                                       if (newRunTail != null)
+                                               newRunTail.prev = newrun;
+                                       else
+                                               startsentinel.next = newrun;
+
+                                       newRunTail = newrun;
+                                       run = nextRun;
+                               }
+
+                               if (run != null) // Add the last run, if any
+                                       newRunTail.prev = run;
+                       }
+
+                       endsentinel.prev.next = endsentinel;
+                       startsentinel.next.prev = startsentinel;
+
+                       //assert invariant();
+                       //assert isSorted();
+#if LISTORDER
+                       if (maintaintags)
+                       {
+                               int span = (endsentinel.tag > 0 ? endsentinel.tag - 1 : int.MaxValue) - startsentinel.tag;
+
+                               Debug.Assert(span >= size);
+
+                               double tagdelta = span / (size + 0.0);
+                               int count = 1;
+                               Node cursor = startsentinel.next;
+
+                               while (cursor != endsentinel)
+                               {
+                                       cursor.tag = startsentinel.tag + (int)(tagdelta * count++);
+                                       cursor = cursor.next;
+                               }
+                       }
+#elif EXTLISTORDER
+                       if (maintaintags)
+                       {
+                               Node cursor = startsentinel.next, end = endsentinel;
+                               int tag, taglimit;
+                               TagGroup t = gettaggroup(startsentinel, endsentinel, out tag, out taglimit);
+                               int tagdelta = taglimit / (size + 1) - tag / (size + 1);
+
+                               tagdelta = tagdelta == 0 ? 1 : tagdelta;
+                               if (underlying == null)
+                                       taggroups = 1;
+
+                               while (cursor != end)
+                               {
+                                       tag = tag + tagdelta > taglimit ? taglimit : tag + tagdelta;
+                                       cursor.tag = tag;
+                                       t.count++;
+                                       cursor = cursor.next;
+                               }
+
+                               if (tag == taglimit)
+                                       splittaggroup(t);
+                       }
+#endif
+               }
+
+
+               private static Node mergeRuns(Node run1, Node run2, IComparer<T> c)
+               {
+                       //assert run1 != null && run2 != null;
+                       Node prev;
+                       bool prev1;     // is prev from run1?
+
+                       if (c.Compare(run1.item, run2.item) <= 0)
+                       {
+                               prev = run1;
+                               prev1 = true;
+                               run1 = run1.next;
+                       }
+                       else
+                       {
+                               prev = run2;
+                               prev1 = false;
+                               run2 = run2.next;
+                       }
+
+                       Node start = prev;
+
+                       //assert start != null;
+                       start.prev = null;
+                       while (run1 != null && run2 != null)
+                       {
+                               if (prev1)
+                               {
+                                       //assert prev.next == run1;
+                                       //Comparable run2item = (Comparable)run2.item;
+                                       while (run1 != null && c.Compare(run2.item, run1.item) >= 0)
+                                       {
+                                               prev = run1;
+                                               run1 = prev.next;
+                                       }
+
+                                       if (run1 != null)
+                                       { // prev.item <= run2.item < run1.item; insert run2
+                                               prev.next = run2;
+                                               run2.prev = prev;
+                                               prev = run2;
+                                               run2 = prev.next;
+                                               prev1 = false;
+                                       }
+                               }
+                               else
+                               {
+                                       //assert prev.next == run2;
+                                       //Comparable run1item = (Comparable)run1.item;
+                                       while (run2 != null && c.Compare(run1.item, run2.item) > 0)
+                                       {
+                                               prev = run2;
+                                               run2 = prev.next;
+                                       }
+
+                                       if (run2 != null)
+                                       { // prev.item < run1.item <= run2.item; insert run1
+                                               prev.next = run1;
+                                               run1.prev = prev;
+                                               prev = run1;
+                                               run1 = prev.next;
+                                               prev1 = true;
+                                       }
+                               }
+                       }
+
+                       //assert !(run1 != null && prev1) && !(run2 != null && !prev1);
+                       if (run1 != null)
+                       { // last run2 < all of run1; attach run1 at end
+                               prev.next = run1;
+                               run1.prev = prev;
+                       }
+                       else if (run2 != null)
+                       { // last run1 
+                               prev.next = run2;
+                               run2.prev = prev;
+                       }
+
+                       return start;
+               }
+
+
+               /// <summary>
+               /// Randonmly shuffle the items of this list. 
+               /// </summary>
+               public virtual void Shuffle() { Shuffle(new C5Random()); }
+
+
+               /// <summary>
+               /// Shuffle the items of this list according to a specific random source.
+               /// </summary>
+               /// <param name="rnd">The random source.</param>
+               public virtual void Shuffle(Random rnd)
+               {
+                       updatecheck();
+
+                       ArrayList<T> a = new ArrayList<T>();
+
+                       a.AddAll(this);
+                       a.Shuffle(rnd);
+
+                       Node cursor = startsentinel.next;
+                       int j = 0;
+
+                       while (cursor != endsentinel)
+                       {
+                               cursor.item = a[j++];
+                               cursor = cursor.next;
+                       }
+               }
+
+               #endregion
+
+               #region IIndexed<T> Members
+
+
+               /// <summary>
+               /// <exception cref="IndexOutOfRangeException"/>.
+               /// </summary>
+               /// <value>The directed collection of items in a specific index interval.</value>
+               /// <param name="start">The low index of the interval (inclusive).</param>
+        /// <param name="count">The size of the range.</param>
+        [Tested]
+        public IDirectedCollectionValue<T> this[int start, int count]
+               {
+                       [Tested]
+                       get
+                       {
+                               modifycheck();
+                               checkRange(start, count);
+                               return new Range(this, start, count, true);
+                       }
+               }
+
+
+               /// <summary>
+               /// Searches for an item in the list going forwrds from the start.
+               /// </summary>
+               /// <param name="item">Item to search for.</param>
+               /// <returns>Index of item from start.</returns>
+               [Tested]
+               public virtual int IndexOf(T item)
+               {
+                       modifycheck();
+
+                       Node node = startsentinel.next;
+                       int index = 0;
+
+                       if (find(item, ref node, ref index))
+                               return index;
+                       else
+                               return -1;
+               }
+
+
+               /// <summary>
+               /// Searches for an item in the list going backwords from the end.
+               /// </summary>
+               /// <param name="item">Item to search for.</param>
+               /// <returns>Index of of item from the end.</returns>
+               [Tested]
+               public virtual int LastIndexOf(T item)
+               {
+                       modifycheck();
+
+                       Node node = endsentinel.prev;
+                       int index = size - 1;
+
+                       if (dnif(item, ref node, ref index))
+                               return index;
+                       else
+                               return -1;
+               }
+
+
+               private bool find(T item, ref Node node, ref int index)
+               {
+                       while (node != endsentinel)
+                       {
+                               //if (item.Equals(node.item))
+                               if (itemhasher.Equals(item, node.item))
+                                       return true;
+
+                               index++;
+                               node = node.next;
+                       }
+
+                       return false;
+               }
+
+
+               private bool dnif(T item, ref Node node, ref int index)
+               {
+                       while (node != startsentinel)
+                       {
+                               //if (item.Equals(node.item))
+                               if (itemhasher.Equals(item, node.item))
+                                       return true;
+
+                               index--;
+                               node = node.prev;
+                       }
+
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Remove the item at a specific position of the list.
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+               /// &gt;= the size of the collection.
+               /// </summary>
+               /// <param name="i">The index of the item to remove.</param>
+               /// <returns>The removed item.</returns>
+               [Tested]
+               public virtual T RemoveAt(int i)
+               {
+                       updatecheck();
+                       return remove(get(i));
+               }
+
+
+               /// <summary>
+               /// Remove all items in an index interval.
+               /// <exception cref="IndexOutOfRangeException"/>???. 
+               /// </summary>
+               /// <param name="start">The index of the first item to remove.</param>
+               /// <param name="count">The number of items to remove.</param>
+               [Tested]
+               public virtual void RemoveInterval(int start, int count)
+               {
+                       updatecheck();
+                       checkRange(start, count);
+                       if (count == 0)
+                               return;
+
+                       //for small count: optimize
+                       //make an optimal get(int i, int j, ref Node ni, ref Node nj)?
+                       Node a = get(start), b = get(start + count - 1);
+#if EXTLISTORDER
+                       if (maintaintags)
+                       {
+                               Node c = a;
+                               TagGroup t = a.taggroup;
+
+                               while (c.taggroup == t && c != b.next)
+                               {
+                                       removefromtaggroup(c);
+                                       c = c.next;
+                               }
+
+                               if (c != b.next)
+                               {
+                                       Debug.Assert(b.taggroup != t);
+                                       c = b;
+                                       t = b.taggroup;
+                                       while (c.taggroup == t)
+                                       {
+                                               removefromtaggroup(c);
+                                               c = c.prev;
+                                       }
+                               }
+                       }
+#endif
+                       a.prev.next = b.next;
+                       b.next.prev = a.prev;
+                       if (underlying != null)
+                               underlying.size -= count;
+
+                       size -= count;
+               }
+
+               
+               #endregion
+
+               #region ISequenced<T> Members
+
+               [Tested]
+               int ISequenced<T>.GetHashCode() { modifycheck(); return sequencedhashcode(); }
+
+
+               [Tested]
+               bool ISequenced<T>.Equals(ISequenced<T> that)
+               { modifycheck(); return sequencedequals(that); }
+
+               #endregion
+
+               #region IDirectedCollection<T> Members
+
+               /// <summary>
+               /// Create a collection containing the same items as this collection, but
+               /// whose enumerator will enumerate the items backwards. The new collection
+               /// will become invalid if the original is modified. Method typicaly used as in
+               /// <code>foreach (T x in coll.Backwards()) {...}</code>
+               /// </summary>
+               /// <returns>The backwards collection.</returns>
+               [Tested]
+               public IDirectedCollectionValue<T> Backwards()
+               { return this[0, size].Backwards(); }
+
+               #endregion
+
+               #region IDirectedEnumerable<T> Members
+
+               [Tested]
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+               
+               #endregion
+
+               #region IEditableCollection<T> Members
+
+               /// <summary>
+               /// The value is symbolic indicating the type of asymptotic complexity
+               /// in terms of the size of this collection (worst-case or amortized as
+               /// relevant).
+               /// </summary>
+               /// <value>Speed.Linear</value>
+               [Tested]
+               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Linear; } }
+
+
+               [Tested]
+               int ICollection<T>.GetHashCode()
+               { modifycheck(); return unsequencedhashcode(); }
+
+
+               [Tested]
+               bool ICollection<T>.Equals(ICollection<T> that)
+               { modifycheck(); return unsequencedequals(that); }
+
+
+               /// <summary>
+               /// Check if this collection contains (an item equivalent to according to the
+               /// itemhasher) a particular value.
+               /// </summary>
+               /// <param name="item">The value to check for.</param>
+               /// <returns>True if the items is in this collection.</returns>
+               [Tested]
+               public virtual bool Contains(T item)
+               {
+                       modifycheck();
+
+                       Node node = startsentinel.next;
+
+                       while (node != endsentinel)
+                       {
+                               if (itemhasher.Equals(item, node.item))
+                                       return true;
+
+                               node = node.next;
+                       }
+
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Check if this collection contains an item equivalent according to the
+               /// itemhasher to a particular value. If so, return in the ref argument (a
+               /// binary copy of) the actual value found.
+               /// </summary>
+               /// <param name="item">The value to look for.</param>
+               /// <returns>True if the items is in this collection.</returns>
+               [Tested]
+               public virtual bool Find(ref T item)
+               {
+                       modifycheck();
+
+                       Node node = startsentinel.next;
+
+                       while (node != endsentinel)
+                       {
+                               if (equals(item, node.item))
+                               {
+                                       item = node.item;
+                                       return true;
+                               }
+
+                               node = node.next;
+                       }
+
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Check if this collection contains an item equivalent according to the
+               /// itemhasher to a particular value. If so, update the item in the collection 
+               /// to with a binary copy of the supplied value. Will update a single item.
+               /// </summary>
+               /// <param name="item">Value to update.</param>
+               /// <returns>True if the item was found and hence updated.</returns>
+               [Tested]
+               public virtual bool Update(T item)
+               {
+                       updatecheck();
+
+                       Node node = startsentinel.next;
+
+                       while (node != endsentinel)
+                       {
+                               if (equals(item, node.item))
+                               {
+                                       node.item = item;
+                                       return true;
+                               }
+
+                               node = node.next;
+                       }
+
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Check if this collection contains an item equivalent according to the
+               /// itemhasher to a particular value. If so, return in the ref argument (a
+               /// binary copy of) the actual value found. Else, add the item to the collection.
+               /// </summary>
+               /// <param name="item">The value to look for.</param>
+               /// <returns>True if the item was found (hence not added).</returns>
+               [Tested]
+               public virtual bool FindOrAdd(ref T item)
+               {
+                       updatecheck();
+                       if (Find(ref item))
+                               return true;
+
+                       Add(item);
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Check if this collection contains an item equivalent according to the
+               /// itemhasher to a particular value. If so, update the item in the collection 
+               /// to with a binary copy of the supplied value; else add the value to the collection. 
+               /// </summary>
+               /// <param name="item">Value to add or update.</param>
+               /// <returns>True if the item was updated (hence not added).</returns>
+               [Tested]
+               public virtual bool UpdateOrAdd(T item)
+               {
+                       updatecheck();
+                       if (Update(item))
+                               return true;
+
+                       Add(item);
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Remove a particular item from this collection. Since the collection has bag
+               /// semantics only one copy equivalent to the supplied item is removed. 
+               /// </summary>
+               /// <param name="item">The value to remove.</param>
+               /// <returns>True if the item was found (and removed).</returns>
+               [Tested]
+               public virtual bool Remove(T item)
+               {
+                       updatecheck();
+
+                       Node node = startsentinel.next;
+
+                       while (node != endsentinel)
+                       {
+                               if (itemhasher.Equals(item, node.item))
+                               {
+                                       remove(node);
+                                       return true;
+                               }
+
+                               node = node.next;
+                       }
+
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Remove a particular item from this collection if found (only one copy). 
+               /// If an item was removed, report a binary copy of the actual item removed in 
+               /// the argument.
+               /// </summary>
+               /// <param name="item">The value to remove on input.</param>
+               /// <returns>True if the item was found (and removed).</returns>
+               [Tested]
+               public virtual bool RemoveWithReturn(ref T item)
+               {
+                       updatecheck();
+
+                       Node node = startsentinel.next;
+
+                       while (node != endsentinel)
+                       {
+                               if (itemhasher.Equals(item, node.item))
+                               {
+                                       item = node.item;
+                                       remove(node);
+                                       return true;
+                               }
+
+                               node = node.next;
+                       }
+
+                       return false;
+               }
+
+
+               /// <summary>
+               /// Remove all items in another collection from this one, take multiplicities into account.
+               /// </summary>
+               /// <param name="items">The items to remove.</param>
+               [Tested]
+               public virtual void RemoveAll(MSG.IEnumerable<T> items)
+               {
+                       //Use an auxiliary hashbag should speed from O(n*m) to O(n+m) but use more memory
+                       updatecheck();
+                       if (size == 0)
+                               return;
+
+                       bool[] paired = new bool[size];
+                       int index, toretain = size;
+                       Node node;
+
+                       foreach (T item in items)
+                       {
+                               node = startsentinel.next;
+                               index = 0;
+                               while (node != endsentinel)
+                               {
+                                       if (itemhasher.Equals(item, node.item) && !paired[index])
+                                       {
+                                               if (--toretain == 0)
+                                               {
+                                                       clear();
+                                                       return;
+                                               }
+
+                                               paired[index] = true;
+                                               goto cont;
+                                       }
+
+                                       node = node.next;
+                                       index++;
+                               }
+                       cont :
+
+                               ;
+                       }
+
+                       if (toretain == size)
+                               return;
+
+                       if (underlying != null)
+                               underlying.size -= size - toretain;
+
+                       node = startsentinel.next;
+                       size = toretain;
+                       index = 0;
+                       while (paired[index])
+                       {
+#if EXTLISTORDER
+                               if (maintaintags) removefromtaggroup(node);
+#endif
+                               node = node.next;
+                               index++;
+                       }
+
+                       if (index > 0)
+                       {
+                               startsentinel.next = node;
+                               node.prev = startsentinel;
+                       }
+
+                       while (true)
+                       {
+                               while (--toretain > 0 && !paired[++index])
+                                       node = node.next;
+
+                               Node localend = node;
+
+                               if (toretain == 0)
+                               {
+#if EXTLISTORDER
+                                       node = node.next;
+                                       while (node != endsentinel)
+                                       {
+                                               if (maintaintags) removefromtaggroup(node);
+
+                                               node = node.next;
+                                       }
+#endif
+                                       //fixup at end
+                                       endsentinel.prev = localend;
+                                       localend.next = endsentinel;
+                                       break;
+                               }
+
+                               node = node.next;
+                               while (paired[index])
+                               {
+#if EXTLISTORDER
+                                       if (maintaintags) removefromtaggroup(node);
+#endif
+                                       node = node.next;
+                                       index++;
+                               }
+
+                               localend.next = node;
+                               node.prev = localend;
+                       }
+               }
+
+
+               /// <summary>
+               /// Remove all items from this collection.
+               /// </summary>
+               [Tested]
+               public virtual void Clear()
+               {
+                       updatecheck();
+                       clear();
+               }
+
+
+               void clear()
+               {
+#if EXTLISTORDER
+                       if (maintaintags)
+                       {
+                               if (underlying != null)
+                               {
+                                       Node n = startsentinel.next;
+
+                                       while (n != endsentinel)
+                                       {
+                                               n.next.prev = startsentinel;
+                                               startsentinel.next = n.next;
+                                               removefromtaggroup(n);
+                                               n = n.next;
+                                       }
+                               }
+                               else
+                               {
+                                       taggroups = 0;
+                               }
+                       }
+#endif
+                       endsentinel.prev = startsentinel;
+                       startsentinel.next = endsentinel;
+                       if (underlying != null)
+                               underlying.size -= size;
+
+                       size = 0;
+               }
+
+
+               /// <summary>
+               /// Remove all items not in some other collection from this one, take multiplicities into account.
+               /// </summary>
+               /// <param name="items">The items to retain.</param>
+               [Tested]
+               public virtual void RetainAll(MSG.IEnumerable<T> items)
+               {
+                       updatecheck();
+                       if (size == 0)
+                               return;
+
+                       bool[] paired = new bool[size];
+                       int index, pairs = 0;
+                       Node node;
+
+                       foreach (T item in items)
+                       {
+                               node = startsentinel.next;
+                               index = 0;
+                               while (node != endsentinel)
+                               {
+                                       if (itemhasher.Equals(item, node.item) && !paired[index])
+                                       {
+                                               if (++pairs == size)
+                                                       return;
+
+                                               paired[index] = true;
+                                               goto cont;
+                                       }
+
+                                       node = node.next;
+                                       index++;
+                               }
+                       cont :
+
+                               ;
+                       }
+
+                       if (pairs == 0)
+                       {
+                               clear();
+                               return;
+                       }
+
+                       if (underlying != null)
+                               underlying.size -= size - pairs;
+
+                       node = startsentinel.next;
+                       size = pairs;
+                       index = 0;
+                       while (!paired[index])
+                       {
+#if EXTLISTORDER
+                               if (maintaintags) removefromtaggroup(node);
+#endif
+                               node = node.next;
+                               index++;
+                       }
+
+                       if (index > 0)
+                       {
+                               startsentinel.next = node;
+                               node.prev = startsentinel;
+                       }
+
+                       while (true)
+                       {
+                               while (--pairs > 0 && paired[++index])
+                                       node = node.next;
+
+                               Node localend = node;
+
+                               if (pairs == 0)
+                               {
+#if EXTLISTORDER
+                                       node = node.next;
+                                       while (node != endsentinel)
+                                       {
+                                               if (maintaintags) removefromtaggroup(node);
+
+                                               node = node.next;
+                                       }
+#endif
+                                       endsentinel.prev = localend;
+                                       localend.next = endsentinel;
+                                       break;
+                               }
+
+                               node = node.next;
+                               while (!paired[index])
+                               {
+#if EXTLISTORDER
+                                       if (maintaintags) removefromtaggroup(node);
+#endif
+                                       node = node.next;
+                                       index++;
+                               }
+
+                               localend.next = node;
+                               node.prev = localend;
+                       }
+               }
+
+
+               /// <summary>
+               /// Check if this collection contains all the values in another collection
+               /// with respect to multiplicities.
+               /// </summary>
+               /// <param name="items">The </param>
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+               [Tested]
+               public virtual bool ContainsAll(MSG.IEnumerable<T> items)
+               {
+                       modifycheck();
+
+                       bool[] paired = new bool[size];
+
+                       foreach (T item in items)
+                       {
+                               int index = 0;
+                               Node node = startsentinel.next;
+
+                               while (node != endsentinel)
+                               {
+                                       if (itemhasher.Equals(item, node.item) && !paired[index])
+                                       {
+                                               paired[index] = true;
+                                               goto cont;
+                                       }
+
+                                       node = node.next;
+                                       index++;
+                               }
+
+                               return false;
+                       cont :
+                               ;
+                       }
+
+                       return true;
+               }
+
+
+               /// <summary>
+               /// Create a new list consisting of the items of this list satisfying a 
+               /// certain predicate.
+               /// </summary>
+               /// <param name="filter">The filter delegate defining the predicate.</param>
+               /// <returns>The new list.</returns>
+               [Tested]
+               public IList<T> FindAll(Filter<T> filter)
+               {
+                       LinkedList<T> retval = new LinkedList<T>();
+
+                       modifycheck();
+
+                       Node cursor = startsentinel.next;
+                       Node mcursor = retval.startsentinel;
+
+#if LISTORDER
+                       double tagdelta = int.MaxValue / (size + 1.0);
+#elif EXTLISTORDER
+                       double tagdelta = int.MaxValue / (size + 1.0);
+                       int count = 1;
+                       TagGroup taggroup = null;
+
+                       if (retval.maintaintags)
+                       {
+                               taggroup = new TagGroup();
+                               retval.taggroups = 1;
+                       }
+#endif
+                       while (cursor != endsentinel)
+                       {
+                               if (filter(cursor.item))
+                               {
+                                       mcursor.next = new Node(cursor.item, mcursor, null);
+                                       mcursor = mcursor.next;
+                                       retval.size++;
+#if LISTORDER
+                                       if (retval.maintaintags)
+                                               mcursor.tag = (int)(retval.size * tagdelta);
+#elif EXTLISTORDER
+                                       if (retval.maintaintags)
+                                       {
+                                               mcursor.taggroup = taggroup;
+                                               mcursor.tag = (int)(tagdelta * count++);
+                                       }
+#endif
+                               }
+
+                               cursor = cursor.next;
+                       }
+
+#if EXTLISTORDER       
+                       if (retval.maintaintags)
+                               taggroup.count = retval.size;
+#endif
+                       retval.endsentinel.prev = mcursor;
+                       mcursor.next = retval.endsentinel;
+                       return retval;
+               }
+
+
+               /// <summary>
+               /// Count the number of items of the collection equal to a particular value.
+               /// Returns 0 if and only if the value is not in the collection.
+               /// </summary>
+               /// <param name="item">The value to count.</param>
+               /// <returns>The number of copies found.</returns>
+               [Tested]
+               public virtual int ContainsCount(T item)
+               {
+                       int retval = 0;
+
+                       modifycheck();
+
+                       Node node = startsentinel.next;
+
+                       while (node != endsentinel)
+                       {
+                               if (itemhasher.Equals(node.item, item))
+                                       retval++;
+
+                               node = node.next;
+                       }
+
+                       return retval;
+               }
+
+
+               /// <summary>
+               /// Remove all items equivalent to a given value.
+               /// </summary>
+               /// <param name="item">The value to remove.</param>
+               [Tested]
+               public virtual void RemoveAllCopies(T item)
+               {
+                       updatecheck();
+
+                       int removed = 0;
+                       Node node = startsentinel.next;
+
+                       while (node != endsentinel)
+                       {
+                               //Here we could loop to collect more matching adjacent nodes in one 
+                               //splice, but with some overhead for the general case.
+                               //se retailall for an example
+                               //if (node.item.Equals(item))
+                               if (itemhasher.Equals(node.item, item))
+                               {
+                                       removed++;
+                                       node.prev.next = node.next;
+                                       node.next.prev = node.prev;
+#if EXTLISTORDER
+                                       if (maintaintags)
+                                               removefromtaggroup(node);
+#endif
+                               }
+
+                               node = node.next;
+                       }
+
+                       if (removed > 0)
+                       {
+                               size -= removed;
+                               if (underlying != null)
+                                       underlying.size -= removed;
+                       }
+
+                       return;
+               }
+               #endregion
+
+               #region ICollection<T> Members
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <value>The number of items in this collection</value>
+               [Tested]
+               public override int Count { [Tested]get { modifycheck(); return size; } }
+
+               #endregion
+
+               #region IEnumerable<T> Members
+               /// <summary>
+               /// Create an enumerator for the collection
+               /// </summary>
+               /// <returns>The enumerator</returns>
+               [Tested]
+               public override MSG.IEnumerator<T> GetEnumerator()
+               {
+                       Node cursor = startsentinel.next;
+                       int startstamp = this.stamp;
+
+                       while (cursor != endsentinel)
+                       {
+                               modifycheck(startstamp);
+                               yield return cursor.item;
+                               cursor = cursor.next;
+                       }
+               }
+
+               #endregion
+
+               #region ISink<T> Members
+               /// <summary>
+               /// Add an item to this collection if possible. 
+               /// </summary>
+               /// <param name="item">The item to add.</param>
+               /// <returns>True.</returns>
+               [Tested]
+               public virtual bool Add(T item)
+               {
+                       updatecheck();
+                       insert(endsentinel, item);
+                       return true;
+               }
+
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <value>True since this collection has bag semantics.</value>
+               [Tested]
+               public virtual bool AllowsDuplicates { [Tested]get { return true; } }
+
+
+               /// <summary>
+               /// Add the elements from another collection to this collection. 
+               /// </summary>
+               /// <param name="items">The items to add.</param>
+               [Tested]
+               public virtual void AddAll(MSG.IEnumerable<T> items) { InsertAll(size, items); }
+
+        /// <summary>
+        /// Add the elements from another collection with a more specialized item type 
+        /// to this collection. 
+        /// </summary>
+        /// <typeparam name="U">The type of items to add</typeparam>
+        /// <param name="items">The items to add</param>
+        public virtual void AddAll<U>(MSG.IEnumerable<U> items) where U : T
+        {
+            //TODO: implement
+        }
+
+
+               #endregion
+
+        #region IStack<T> Members
+
+        /// <summary>
+        /// Push an item to the top of the stack.
+        /// </summary>
+        /// <param name="item">The item</param>
+        [Tested]
+        public void Push(T item)
+        {
+            Add(item);
+        }
+
+        /// <summary>
+        /// Pop the item at the top of the stack from the stack.
+        /// </summary>
+        /// <returns>The popped item.</returns>
+        [Tested]
+        public T Pop()
+        {
+            return RemoveLast();
+        }
+
+         #endregion
+
+        #region IQueue<T> Members
+
+        /// <summary>
+        /// Enqueue an item at the back of the queue. 
+        /// </summary>
+        /// <param name="item">The item</param>
+        [Tested]
+        public void EnQueue(T item)
+        {
+            Add(item);
+        }
+
+        /// <summary>
+        /// Dequeue an item from the front of the queue.
+        /// </summary>
+        /// <returns>The item</returns>
+        [Tested]
+        public T DeQueue()
+        {
+            return RemoveFirst();
+        }
+
+         #endregion
+        
+        #region Diagnostic
+
+        /// <summary>
+               /// Check the sanity of this list
+               /// </summary>
+               /// <returns>true if sane</returns>
+               [Tested]
+               public virtual bool Check()
+               {
+                       bool retval = true;
+
+                       if (underlying != null && underlying.stamp != stamp)
+                       {
+                               Console.WriteLine("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp);
+                               retval = false;
+                       }
+
+                       if (startsentinel == null)
+                       {
+                               Console.WriteLine("startsentinel == null");
+                               retval = false;
+                       }
+
+                       if (endsentinel == null)
+                       {
+                               Console.WriteLine("endsentinel == null");
+                               retval = false;
+                       }
+
+                       if (size == 0)
+                       {
+                               if (startsentinel != null && startsentinel.next != endsentinel)
+                               {
+                                       Console.WriteLine("size == 0 but startsentinel.next != endsentinel");
+                                       retval = false;
+                               }
+
+                               if (endsentinel != null && endsentinel.prev != startsentinel)
+                               {
+                                       Console.WriteLine("size == 0 but endsentinel.prev != startsentinel");
+                                       retval = false;
+                               }
+                       }
+
+                       if (startsentinel == null)
+                               return retval;
+
+                       int count = 0;
+                       Node node = startsentinel.next, prev = startsentinel;
+#if EXTLISTORDER
+                       int taggroupsize = 0, oldtaggroupsize = losize + 1, seentaggroups = 0;
+                       TagGroup oldtg = null;
+
+                       if (maintaintags && underlying == null)
+                       {
+                               TagGroup tg = startsentinel.taggroup;
+
+                               if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MinValue)
+                               {
+                                       Console.WriteLine("Bad startsentinel tag group: {0}", tg);
+                                       retval = false;
+                               }
+
+                               tg = endsentinel.taggroup;
+                               if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MaxValue)
+                               {
+                                       Console.WriteLine("Bad endsentinel tag group: {0}", tg);
+                                       retval = false;
+                               }
+                       }
+#endif
+                       while (node != endsentinel)
+                       {
+                               count++;
+                               if (node.prev != prev)
+                               {
+                                       Console.WriteLine("Bad backpointer at node {0}", count);
+                                       retval = false;
+                               }
+#if LISTORDER
+                               if (maintaintags && node.prev.tag >= node.tag)
+                               {
+                                       Console.WriteLine("node.prev.tag ({0}) >= node.tag ({1}) at index={2} item={3} ", node.prev.tag, node.tag, count, node.item);
+                                       retval = false;
+                               }
+#elif EXTLISTORDER
+                               if (maintaintags && underlying == null)
+                               {
+                                       if (!node.prev.precedes(node))
+                                       {
+                                               Console.WriteLine("node.prev.tag ({0}, {1}) >= node.tag ({2}, {3}) at index={4} item={5} ", node.prev.taggroup.tag, node.prev.tag, node.taggroup.tag, node.tag, count, node.item);
+                                               retval = false;
+                                       }
+
+                                       if (node.taggroup != oldtg)
+                                       {
+                                               if (oldtg != null)
+                                               {
+                                                       if (oldtg.count != taggroupsize)
+                                                       {
+                                                               Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
+                                                               retval = false;
+                                                       }
+
+                                                       if (oldtaggroupsize <= losize && taggroupsize <= losize)
+                                                       {
+                                                               Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
+                                                               retval = false;
+                                                       }
+
+                                                       oldtaggroupsize = taggroupsize;
+                                               }
+
+                                               seentaggroups++;
+                                               oldtg = node.taggroup;
+                                               taggroupsize = 1;
+                                       }
+                                       else
+                                       {
+                                               taggroupsize++;
+                                       }
+                               }
+#endif
+                               prev = node;
+                               node = node.next;
+                               if (node == null)
+                               {
+                                       Console.WriteLine("Null next pointer at node {0}", count);
+                                       return false;
+                               }
+                       }
+
+#if EXTLISTORDER
+                       if (maintaintags && underlying == null && size > 0)
+                       {
+                               oldtg = node.prev.taggroup;
+                               if (oldtg != null)
+                               {
+                                       if (oldtg.count != taggroupsize)
+                                       {
+                                               Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
+                                               retval = false;
+                                       }
+
+                                       if (oldtaggroupsize <= losize && taggroupsize <= losize)
+                                       {
+                                               Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
+                                               retval = false;
+                                       }
+                               }
+
+                               if (seentaggroups != taggroups)
+                               {
+                                       Console.WriteLine("seentaggroups ({0}) != taggroups ({1}) (at size {2})", seentaggroups, taggroups, size);
+                                       retval = false;
+                               }
+                       }
+#endif
+                       if (count != size)
+                       {
+                               Console.WriteLine("size={0} but enumeration gives {1} nodes ", size, count);
+                               retval = false;
+                       }
+
+                       return retval;
+               }
+
+               #endregion      
+       }
+}
+#endif
diff --git a/mcs/class/Mono.C5/C5/trees/RedBlackTree.cs b/mcs/class/Mono.C5/C5/trees/RedBlackTree.cs
new file mode 100644 (file)
index 0000000..daca84a
--- /dev/null
@@ -0,0 +1,4329 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+#define MAINTAIN_SIZE\r
+#define MAINTAIN_RANKnot\r
+#define MAINTAIN_HEIGHTnot\r
+#define BAGnot\r
+#define NCP\r
+\r
+#define MAINTAIN_EXTREMAnot\r
+#define TRACE_IDnot\r
+\r
+#if BAG\r
+#if !MAINTAIN_SIZE\r
+#error  BAG defined without MAINTAIN_SIZE!\r
+#endif\r
+#endif\r
+\r
+\r
+using System;\r
+using MSG = System.Collections.Generic;\r
+using SC = System.Collections;\r
+\r
+// NOTE NOTE NOTE NOTE\r
+// This source file is used to produce both TreeSet<T> and TreeBag<T>\r
+// It should be copied to a file called TreeBag.cs in which all code mentions of \r
+// TreeSet is changed to TreeBag and the preprocessor symbol BAG is defined.\r
+// NOTE: there may be problems with documentation comments.\r
+\r
+namespace C5\r
+{\r
+#if BAG\r
+       /// <summary>\r
+       /// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics,\r
+       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. (<see cref="T:C5.TreeSet!1"/> for an \r
+       /// implementation with set semantics).\r
+       /// <br/>\r
+       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
+       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
+       /// be external and supplied by the user in the constructor.\r
+       /// <br/>\r
+       /// Each distinct item is only kept in one place in the tree - together with the number\r
+       /// of times it is a member of the bag. Thus, if two items that are equal according\r
+       /// </summary>\r
+#else\r
+       /// <summary>\r
+       /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics,\r
+       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. <see cref="T:C5.TreeBag!1"/> for a version \r
+       /// with bag semantics. <see cref="T:C5.TreeDictionary!2"/> for a sorted dictionary \r
+       /// based on this tree implementation.\r
+       /// <p>\r
+       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
+       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
+       /// be external and supplied by the user in the constructor.</p>\r
+       ///\r
+       /// <p><i>TODO: describe performance here</i></p>\r
+       /// <p><i>TODO: discuss persistence and its useful usage modes. Warn about the space\r
+       /// leak possible with other usage modes.</i></p>\r
+       /// </summary>\r
+#endif\r
+       public class TreeSet<T>: SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>\r
+       {\r
+               #region Feature\r
+               /// <summary>\r
+               /// A debugging aid for making the selected compilation alternatives \r
+               /// available to the user. (To be removed when selection is finally fixed\r
+               /// for production version).\r
+               /// </summary>\r
+               [Flags]\r
+               public enum Feature: short\r
+               {\r
+                       /// <summary>\r
+                       /// Nothing\r
+                       /// </summary>\r
+                       Dummy = 0,\r
+                       /// <summary>\r
+                       /// Node copy persistence as explained in <a href="litterature.htm#Tarjan1">Tarjan1</a>\r
+                       /// </summary>\r
+                       NodeCopyPersistence = 2,\r
+                       /// <summary>\r
+                       /// Maintain sub tree sizes\r
+                       /// </summary>\r
+                       Sizes = 4,\r
+                       /// <summary>\r
+                       /// Maintain precise node heights\r
+                       /// </summary>\r
+                       Heights = 8,\r
+                       /// <summary>\r
+                       /// Maintain node ranks (~ black height)\r
+                       /// </summary>\r
+                       Ranks = 16,\r
+                       /// <summary>\r
+                       /// Maintain unique ids on tree nodes.\r
+                       /// </summary>\r
+                       Traceid = 32\r
+               }\r
+\r
+\r
+\r
+               static Feature features = Feature.Dummy\r
+#if NCP\r
+               | Feature.NodeCopyPersistence\r
+#endif\r
+#if MAINTAIN_RANK\r
+                       |Feature.Ranks\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                       |Feature.Heights\r
+#endif\r
+#if MAINTAIN_SIZE\r
+               | Feature.Sizes\r
+#endif\r
+#if TRACE_ID\r
+               | Feature.Traceid\r
+#endif\r
+               ;\r
+\r
+\r
+               /// <summary>\r
+               /// A debugging aid for making the selected compilation alternatives \r
+               /// available to the user. (To be removed when selection is finally fixed\r
+               /// for production version).\r
+               /// </summary>\r
+               public static Feature Features { get { return features; } }\r
+\r
+               #endregion\r
+\r
+               #region Fields\r
+\r
+               IComparer<T> comparer;\r
+\r
+               Node root;\r
+\r
+               int blackdepth = 0;\r
+\r
+               //We double these stacks for the iterative add and remove on demand\r
+               private int[] dirs = new int[2];\r
+\r
+               private Node[] path = new Node[2];\r
+#if NCP\r
+               private bool isSnapShot = false;\r
+\r
+               private SnapData snapdata;\r
+\r
+               private int generation;\r
+\r
+               private int maxsnapid = -1;\r
+\r
+#endif\r
+#if MAINTAIN_EXTREMA\r
+               T min, max;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+               private short depth = 0;\r
+#endif\r
+               #endregion\r
+\r
+               #region Util\r
+\r
+               /// <summary>\r
+               /// Fetch the left child of n taking node-copying persistence into\r
+               /// account if relevant. \r
+               /// </summary>\r
+               /// <param name="n"></param>\r
+               /// <returns></returns>\r
+               private Node left(Node n)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                       {\r
+#if SEPARATE_EXTRA\r
+                               Node.Extra e = n.extra;\r
+\r
+                               if (e != null && e.lastgeneration >= treegen && e.leftnode)\r
+                                       return e.oldref;\r
+#else\r
+                               if (n.lastgeneration >= generation && n.leftnode)\r
+                                       return n.oldref;\r
+#endif\r
+                       }\r
+#endif\r
+                       return n.left;\r
+               }\r
+\r
+\r
+               private Node right(Node n)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                       {\r
+#if SEPARATE_EXTRA\r
+                               Node.Extra e = n.extra;\r
+\r
+                               if (e != null && e.lastgeneration >= treegen && !e.leftnode)\r
+                                       return e.oldref;\r
+#else\r
+                               if (n.lastgeneration >= generation && !n.leftnode)\r
+                                       return n.oldref;\r
+#endif\r
+                       }\r
+#endif\r
+                       return n.right;\r
+               }\r
+\r
+\r
+               //This method should be called by methods that use the internal \r
+               //traversal stack, unless certain that there is room enough\r
+               private void stackcheck()\r
+               {\r
+                       while (dirs.Length < 2 * blackdepth)\r
+                       {\r
+                               dirs = new int[2 * dirs.Length];\r
+                               path = new Node[2 * dirs.Length];\r
+                       }\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Node nested class\r
+                       \r
+\r
+               /// <summary>\r
+               /// The type of node in a Red-Black binary tree\r
+               /// </summary>\r
+               class Node\r
+               {\r
+                       public bool red = true;\r
+\r
+                       public T item;\r
+\r
+                       public Node left;\r
+\r
+                       public Node right;\r
+\r
+#if MAINTAIN_SIZE\r
+                       public int size = 1;\r
+#endif\r
+\r
+#if BAG\r
+                       public int items = 1;\r
+#endif\r
+\r
+#if MAINTAIN_HEIGHT\r
+                       public short height; \r
+#endif\r
+\r
+#if MAINTAIN_RANK\r
+                       public short rank = 1;\r
+#endif\r
+\r
+#if TRACE_ID\r
+                       public int id = sid++;\r
+                       public static int sid = 0;\r
+#endif\r
+\r
+#if NCP\r
+                       public int generation;\r
+#if SEPARATE_EXTRA\r
+                       internal class Extra\r
+                       {\r
+                               public int lastgeneration;\r
+\r
+                               public Node oldref;\r
+\r
+                               public bool leftnode;\r
+\r
+                               //public Node next;\r
+                       }\r
+\r
+                       public Extra extra;\r
+\r
+#else\r
+                       public int lastgeneration = -1;\r
+\r
+                       public Node oldref;\r
+\r
+                       public bool leftnode;\r
+#endif\r
+\r
+                       /// <summary>\r
+                       /// Update a child pointer\r
+                       /// </summary>\r
+                       /// <param name="cursor"></param>\r
+                       /// <param name="leftnode"></param>\r
+                       /// <param name="child"></param>\r
+                       /// <param name="maxsnapid"></param>\r
+                       /// <param name="generation"></param>\r
+                       /// <returns>True if node was *copied*</returns>\r
+                       internal static bool update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation)\r
+                       {\r
+                               Node oldref = leftnode ? cursor.left : cursor.right;\r
+\r
+                               if (child == oldref)\r
+                                       return false;\r
+\r
+                               bool retval = false;\r
+\r
+                               if (cursor.generation <= maxsnapid)\r
+                               { \r
+#if SEPARATE_EXTRA\r
+                                       if (cursor.extra == null)\r
+                                       {\r
+                                               Extra extra = cursor.extra = new Extra();       \r
+\r
+                                               extra.leftnode = leftnode;\r
+                                               extra.lastgeneration = maxsnapid;\r
+                                               extra.oldref = oldref;\r
+                                       }\r
+                                       else if (cursor.extra.leftnode != leftnode || cursor.extra.lastgeneration < maxsnapid)\r
+#else\r
+                                       if (cursor.lastgeneration == -1)\r
+                                       {\r
+                                               cursor.leftnode = leftnode;\r
+                                               cursor.lastgeneration = maxsnapid;\r
+                                               cursor.oldref = oldref;\r
+                                       }\r
+                                       else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid)\r
+#endif\r
+                                       {\r
+                                               CopyNode(ref cursor, maxsnapid, generation);\r
+                                               retval = true;\r
+                                       }\r
+                               }\r
+\r
+                               if (leftnode)\r
+                                       cursor.left = child;\r
+                               else\r
+                                       cursor.right = child;\r
+\r
+                               return retval;\r
+                       }\r
+\r
+\r
+                       //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will \r
+                       //always be used in the old copy of cursor. Therefore, after \r
+                       //making the clone, we should update the old copy by restoring\r
+                       //the child pointer and setting extra to null.\r
+                       //OTOH then we cannot clean up unused Extra objects unless we link\r
+                       //them together in a doubly linked list.\r
+                       public static bool CopyNode(ref Node cursor, int maxsnapid, int generation)\r
+                       {\r
+                               if (cursor.generation <= maxsnapid)\r
+                               {\r
+                                       cursor = (Node)(cursor.MemberwiseClone());\r
+                                       cursor.generation = generation;\r
+#if SEPARATE_EXTRA\r
+                                       cursor.extra = null;\r
+#else\r
+                                       cursor.lastgeneration = -1;\r
+#endif\r
+#if TRACE_ID\r
+                                       cursor.id = sid++;\r
+#endif\r
+                                       return true;\r
+                               }\r
+                               else\r
+                                       return false;\r
+                       }\r
+\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+                       \r
+               /// <summary>\r
+               /// Create a red-black tree collection with natural comparer and item hasher.\r
+               /// </summary>\r
+               public TreeSet()\r
+               {\r
+                       comparer = ComparerBuilder.FromComparable<T>.Examine();\r
+                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a red-black tree collection with an external comparer (and natural item hasher,\r
+               /// assumed consistent).\r
+               /// </summary>\r
+               /// <param name="c">The external comparer</param>\r
+               public TreeSet(IComparer<T> c)\r
+               {\r
+                       comparer = c;\r
+                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a red-black tree collection with an external comparer aand an external\r
+               /// item hasher, assumed consistent.\r
+               /// </summary>\r
+               /// <param name="c">The external comparer</param>\r
+               /// <param name="h">The external item hasher</param>\r
+               public TreeSet(IComparer<T> c, IHasher<T> h)\r
+               {\r
+                       comparer = c;\r
+                       itemhasher = h;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region TreeSet.Enumerator nested class\r
+\r
+               /// <summary>\r
+               /// An enumerator for a red-black tree collection. Based on an explicit stack\r
+               /// of subtrees waiting to be enumerated. Currently only used for the tree set \r
+               /// enumerators (tree bag enumerators use an iterator block based enumerator).\r
+               /// </summary>\r
+               public class Enumerator: MSG.IEnumerator<T>\r
+               {\r
+                       #region Private Fields\r
+                       TreeSet<T> tree;\r
+\r
+                       bool valid = false;\r
+\r
+                       int stamp;\r
+\r
+                       T current;\r
+\r
+                       Node cursor;\r
+\r
+                       Node[] path; // stack of nodes\r
+\r
+                       int level = 0;\r
+                       #endregion\r
+                       /// <summary>\r
+                       /// Create a tree enumerator\r
+                       /// </summary>\r
+                       /// <param name="tree">The red-black tree to enumerate</param>\r
+                       public Enumerator(TreeSet<T> tree)\r
+                       {\r
+                               this.tree = tree;\r
+                               stamp = tree.stamp;\r
+                               path = new Node[2 * tree.blackdepth];\r
+                               cursor = new Node();\r
+                               cursor.right = tree.root;\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
+                       /// </summary>\r
+                       /// <value>The current item of the enumerator.</value>\r
+                       [Tested]\r
+                       public T Current\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       if (valid)\r
+                                               return current;\r
+                                       else\r
+                                               throw new InvalidOperationException();\r
+                               }\r
+                       }\r
+\r
+\r
+                       //Maintain a stack of nodes that are roots of\r
+                       //subtrees not completely exported yet. Invariant:\r
+                       //The stack nodes together with their right subtrees\r
+                       //consists of exactly the items we have not passed\r
+                       //yet (the top of the stack holds current item).\r
+                       /// <summary>\r
+                       /// Move enumerator to next item in tree, or the first item if\r
+                       /// this is the first call to MoveNext. \r
+                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
+                       /// </summary>\r
+                       /// <returns>True if enumerator is valid now</returns>\r
+                       [Tested]\r
+                       public bool MoveNext()\r
+                       {\r
+                               tree.modifycheck(stamp);\r
+                               if (cursor.right != null)\r
+                               {\r
+                                       path[level] = cursor = cursor.right;\r
+                                       while (cursor.left != null)\r
+                                               path[++level] = cursor = cursor.left;\r
+                               }\r
+                               else if (level == 0)\r
+                                       return valid = false;\r
+                               else\r
+                                       cursor = path[--level];\r
+\r
+                               current = cursor.item;\r
+                               return valid = true;\r
+                       }\r
+\r
+\r
+                       #region IDisposable Members for Enumerator\r
+\r
+                       bool disposed;\r
+\r
+\r
+                       /// <summary>\r
+                       /// Call Dispose(true) and then suppress finalization of this enumerator.\r
+                       /// </summary>\r
+                       [Tested]\r
+                       public void Dispose()\r
+                       {\r
+                               Dispose(true);\r
+                               GC.SuppressFinalize(this);\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Remove the internal data (notably the stack array).\r
+                       /// </summary>\r
+                       /// <param name="disposing">True if called from Dispose(),\r
+                       /// false if called from the finalizer</param>\r
+                       protected virtual void Dispose(bool disposing)\r
+                       {\r
+                               if (!disposed)\r
+                               {\r
+                                       if (disposing)\r
+                                       {\r
+                                       }\r
+\r
+                                       current = default(T);\r
+                                       cursor = null;\r
+                                       path = null;\r
+                                       disposed = true;\r
+                               }\r
+                       }\r
+\r
+                       void SC.IEnumerator.Reset ()\r
+                       {\r
+                               throw new NotImplementedException ();\r
+                       }\r
+\r
+                       object SC.IEnumerator.Current {\r
+                               get {\r
+                                       return Current;\r
+                               }\r
+                       }\r
+\r
+                       /// <summary>\r
+                       /// Finalizer for enumeratir\r
+                       /// </summary>\r
+                       ~Enumerator()\r
+                       {\r
+                               Dispose(false);\r
+                       }\r
+                       #endregion\r
+\r
+               }\r
+#if NCP\r
+               /// <summary>\r
+               /// An enumerator for a snapshot of a node copy persistent red-black tree\r
+               /// collection.\r
+               /// </summary>\r
+               public class SnapEnumerator: MSG.IEnumerator<T>\r
+               {\r
+                       #region Private Fields\r
+                       TreeSet<T> tree;\r
+\r
+                       bool valid = false;\r
+\r
+                       int stamp;\r
+#if BAG\r
+                       int togo;\r
+#endif\r
+\r
+                       T current;\r
+\r
+                       Node cursor;\r
+\r
+                       Node[] path; // stack of nodes\r
+\r
+                       int level;\r
+                       #endregion\r
+\r
+                       /// <summary>\r
+                       /// Creta an enumerator for a snapshot of a node copy persistent red-black tree\r
+                       /// collection\r
+                       /// </summary>\r
+                       /// <param name="tree">The snapshot</param>\r
+                       public SnapEnumerator(TreeSet<T> tree)\r
+                       {\r
+                               this.tree = tree;\r
+                               stamp = tree.stamp;\r
+                               path = new Node[2 * tree.blackdepth];\r
+                               cursor = new Node();\r
+                               cursor.right = tree.root;\r
+                       }\r
+\r
+\r
+                       #region MSG.IEnumerator<T> Members\r
+\r
+                       /// <summary>\r
+                       /// Move enumerator to next item in tree, or the first item if\r
+                       /// this is the first call to MoveNext. \r
+                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
+                       /// </summary>\r
+                       /// <returns>True if enumerator is valid now</returns>\r
+                       [Tested]\r
+                       public bool MoveNext()\r
+                       {\r
+                               tree.modifycheck(stamp);//???\r
+\r
+#if BAG\r
+                               if (--togo>0)\r
+                                       return true;\r
+#endif\r
+                               Node next = tree.right(cursor);\r
+\r
+                               if (next != null)\r
+                               {\r
+                                       path[level] = cursor = next;\r
+                                       next = tree.left(cursor);\r
+                                       while (next != null)\r
+                                       {\r
+                                               path[++level] = cursor = next;\r
+                                               next = tree.left(cursor);\r
+                                       }\r
+                               }\r
+                               else if (level == 0)\r
+                                       return valid = false;\r
+                               else\r
+                                       cursor = path[--level];\r
+\r
+#if BAG\r
+                               togo = cursor.items;\r
+#endif\r
+                               current = cursor.item;\r
+                               return valid = true;\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
+                       /// </summary>\r
+                       /// <value>The current value of the enumerator.</value>\r
+                       [Tested]\r
+                       public T Current\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       if (valid)\r
+                                               return current;\r
+                                       else\r
+                                               throw new InvalidOperationException();\r
+                               }\r
+                       }\r
+\r
+                       #endregion\r
+\r
+                       void SC.IEnumerator.Reset ()\r
+                       {\r
+                               throw new NotImplementedException ();\r
+                       }\r
+\r
+                       object SC.IEnumerator.Current {\r
+                               get {\r
+                                       return Current;\r
+                               }\r
+                       }\r
+\r
+                       #region IDisposable Members\r
+\r
+                       [Tested]\r
+                       void System.IDisposable.Dispose()\r
+                       {\r
+                               tree = null;\r
+                               valid = false;\r
+                               current = default(T);\r
+                               cursor = null;\r
+                               path = null;\r
+                       }\r
+\r
+                       #endregion\r
+               }\r
+#endif\r
+               #endregion\r
+\r
+               #region IEnumerable<T> Members\r
+\r
+               private MSG.IEnumerator<T> getEnumerator(Node node, int origstamp)\r
+               {\r
+                       if (node == null)\r
+                               yield break;\r
+\r
+                       if (node.left != null)\r
+                       {\r
+                               MSG.IEnumerator<T> child = getEnumerator(node.left, origstamp);\r
+\r
+                               while (child.MoveNext())\r
+                               {\r
+                                       modifycheck(origstamp);\r
+                                       yield return child.Current;\r
+                               }\r
+                       }\r
+#if BAG\r
+                       int togo = node.items;\r
+                       while (togo-- > 0)\r
+                       {\r
+                               modifycheck(origstamp);\r
+                               yield return node.item;\r
+                       }\r
+#else\r
+                       modifycheck(origstamp);\r
+                       yield return node.item;\r
+#endif\r
+                       if (node.right != null)\r
+                       {\r
+                               MSG.IEnumerator<T> child = getEnumerator(node.right, origstamp);\r
+\r
+                               while (child.MoveNext())\r
+                               {\r
+                                       modifycheck(origstamp);\r
+                                       yield return child.Current;\r
+                               }\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an enumerator for this tree\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               [Tested]\r
+               public override MSG.IEnumerator<T> GetEnumerator()\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               return new SnapEnumerator(this);\r
+#endif\r
+#if BAG\r
+                       return getEnumerator(root,stamp);\r
+#else\r
+                       return new Enumerator(this);\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+                       \r
+               /// <summary>\r
+               /// Add item to tree. If already there, return the found item in the second argument.\r
+               /// </summary>\r
+               /// <param name="item">Item to add</param>\r
+        /// <param name="founditem">item found</param>\r
+        /// <param name="update">whether item in node should be updated</param>\r
+        /// <param name="wasfound">true if found in bag, false if not found or tre is a set</param>\r
+        /// <returns>True if item was added</returns>\r
+        bool addIterative(T item, ref T founditem, bool update, out bool wasfound)\r
+        {\r
+            wasfound = false;\r
+            if (root == null)\r
+                       {\r
+                               root = new Node();\r
+                               root.red = false;\r
+                               blackdepth = 1;\r
+#if MAINTAIN_EXTREMA\r
+                               root.item = min = max = item;\r
+#else\r
+                               root.item = item;\r
+#endif\r
+#if NCP\r
+                               root.generation = generation;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = 0;\r
+#endif\r
+                               return true;\r
+                       }\r
+\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (true)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp == 0)\r
+                               {\r
+                    founditem = cursor.item;\r
+\r
+#if BAG\r
+                    wasfound = true;\r
+#if NCP\r
+                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                                       cursor.items++;\r
+                                       cursor.size++;\r
+                                       if (update)\r
+                                               cursor.item = item;\r
+\r
+                                       update = true;\r
+\r
+#else\r
+                    if (update)\r
+                    {\r
+#if NCP\r
+                        Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                        cursor.item = item;\r
+                    }\r
+#endif\r
+\r
+                    while (level-- > 0)\r
+                    {\r
+                        if (update)\r
+                                               {\r
+                                                       Node kid = cursor;\r
+\r
+                                                       cursor = path[level];\r
+#if NCP\r
+                                                       Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
+#endif\r
+#if BAG\r
+                                                       cursor.size++;\r
+#endif\r
+                                               }\r
+\r
+                                               path[level] = null;\r
+                                       }\r
+#if BAG\r
+                                       return true;\r
+#else\r
+                                       if (update)\r
+                                               root = cursor;\r
+\r
+                                       return false;\r
+#endif\r
+                               }\r
+\r
+                               //else\r
+                               Node child = comp > 0 ? cursor.left : cursor.right;\r
+\r
+                               if (child == null)\r
+                               {\r
+                                       child = new Node();\r
+                                       child.item = item;\r
+#if NCP\r
+                                       child.generation = generation;\r
+                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
+#else\r
+                                       if (comp > 0) { cursor.left = child; }\r
+                                       else { cursor.right = child; }\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                                       cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                                       dirs[level] = comp;\r
+                                       break;\r
+                               }\r
+                               else\r
+                               {\r
+                                       dirs[level] = comp;\r
+                                       path[level++] = cursor;\r
+                                       cursor = child;\r
+                               }\r
+                       }\r
+\r
+                       //We have just added the red node child to "cursor"\r
+                       while (cursor.red)\r
+                       {\r
+                               //take one step up:\r
+                               Node child = cursor;\r
+\r
+                               cursor = path[--level];\r
+                               path[level] = null;\r
+#if NCP\r
+                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                               cursor.size++;\r
+#endif\r
+                               int comp = dirs[level];\r
+                               Node childsibling = comp > 0 ? cursor.right : cursor.left;\r
+\r
+                               if (childsibling != null && childsibling.red)\r
+                               {\r
+                                       //Promote\r
+#if MAINTAIN_RANK\r
+                                       cursor.rank++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                                       child.red = false;\r
+#if NCP\r
+                                       Node.update(ref cursor, comp < 0, childsibling, maxsnapid, generation);\r
+#endif\r
+                                       childsibling.red = false;\r
+\r
+                                       //color cursor red & take one step up the tree unless at root\r
+                                       if (level == 0)\r
+                                       {\r
+                                               root = cursor;\r
+                                               blackdepth++;\r
+                                               return true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               cursor.red = true;\r
+#if NCP\r
+                                               child = cursor;\r
+                                               cursor = path[--level];\r
+                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+                                               path[level] = null;\r
+#if MAINTAIN_SIZE\r
+                                               cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       //ROTATE!!!\r
+                                       int childcomp = dirs[level + 1];\r
+\r
+                                       cursor.red = true;\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               if (childcomp > 0)\r
+                                               {//zagzag\r
+#if NCP\r
+                                                       Node.update(ref cursor, true, child.right, maxsnapid, generation);\r
+                                                       Node.update(ref child, false, cursor, maxsnapid, generation);\r
+#else\r
+                                                       cursor.left = child.right;\r
+                                                       child.right = cursor;\r
+#endif\r
+                                                       cursor = child;\r
+                                               }\r
+                                               else\r
+                                               {//zagzig\r
+                                                       Node badgrandchild = child.right;\r
+#if NCP\r
+                                                       Node.update(ref cursor, true, badgrandchild.right, maxsnapid, generation);\r
+                                                       Node.update(ref child, false, badgrandchild.left, maxsnapid, generation);\r
+                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
+#else\r
+                                                       cursor.left = badgrandchild.right;\r
+                                                       child.right = badgrandchild.left;\r
+#endif\r
+                                                       badgrandchild.left = child;\r
+                                                       badgrandchild.right = cursor;\r
+                                                       cursor = badgrandchild;\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {//comp < 0\r
+                                               if (childcomp < 0)\r
+                                               {//zigzig\r
+#if NCP\r
+                                                       Node.update(ref cursor, false, child.left, maxsnapid, generation);\r
+                                                       Node.update(ref child, true, cursor, maxsnapid, generation);\r
+#else\r
+                                                       cursor.right = child.left;\r
+                                                       child.left = cursor;\r
+#endif\r
+                                                       cursor = child;\r
+                                               }\r
+                                               else\r
+                                               {//zigzag\r
+                                                       Node badgrandchild = child.left;\r
+#if NCP\r
+                                                       Node.update(ref cursor, false, badgrandchild.left, maxsnapid, generation);\r
+                                                       Node.update(ref child, true, badgrandchild.right, maxsnapid, generation);\r
+                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
+#else\r
+                                                       cursor.right = badgrandchild.left;\r
+                                                       child.left = badgrandchild.right;\r
+#endif\r
+                                                       badgrandchild.right = child;\r
+                                                       badgrandchild.left = cursor;\r
+                                                       cursor = badgrandchild;\r
+                                               }\r
+                                       }\r
+\r
+                                       cursor.red = false;\r
+\r
+#if MAINTAIN_SIZE\r
+                                       Node n;\r
+\r
+#if BAG\r
+                                       n = cursor.right;\r
+                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
+                                       n = cursor.left;\r
+                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
+                                       cursor.size += n.size + cursor.items;\r
+#else\r
+                                       n = cursor.right;\r
+                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
+                                       n = cursor.left;\r
+                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
+                                       cursor.size += n.size + 1;\r
+#endif\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor.right);\r
+                                       fixheight(cursor.left);\r
+                                       fixheight(cursor);\r
+#endif\r
+                                       if (level == 0)\r
+                                       {\r
+                                               root = cursor;\r
+                                               return true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               child = cursor;\r
+                                               cursor = path[--level];\r
+                                               path[level] = null;\r
+#if NCP\r
+                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#else\r
+                                               if (dirs[level] > 0)\r
+                                                       cursor.left = child;\r
+                                               else\r
+                                                       cursor.right = child;\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                                               cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(cursor);\r
+#endif\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+#if NCP\r
+                       bool stillmore = true;\r
+#endif\r
+                       while (level > 0)\r
+                       {\r
+                               Node child = cursor;\r
+\r
+                               cursor = path[--level];\r
+                               path[level] = null;\r
+#if NCP\r
+                               if (stillmore)\r
+                                       stillmore = Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                               cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               fixheight(cursor);\r
+#endif\r
+                       }\r
+\r
+                       root = cursor;\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to this collection if possible. If this collection has set\r
+               /// semantics, the item will be added if not already in the collection. If\r
+               /// bag semantics, the item will always be added.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True if item was added.</returns>\r
+               [Tested]\r
+               public bool Add(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       //Note: blackdepth of the tree is set inside addIterative\r
+                       T j = default(T);\r
+            bool tmp;\r
+\r
+            if (addIterative(item, ref j, false, out tmp))\r
+                       {\r
+                               size++;\r
+#if MAINTAIN_EXTREMA\r
+                               if (Compare(item, min) < 0)\r
+                                       min = item;\r
+                               else if (Compare(item, max) > 0)\r
+                                       max = item;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = root.height;\r
+#endif\r
+                               return true;\r
+                       }\r
+                       else\r
+                               return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add the elements from another collection to this collection. If this\r
+               /// collection has set semantics, only items not already in the collection\r
+               /// will be added.\r
+               /// </summary>\r
+               /// <param name="items">The items to add.</param>\r
+               [Tested]\r
+               public void AddAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       int c = 0;\r
+                       T j = default(T);\r
+            bool tmp;\r
+\r
+            updatecheck();\r
+                       foreach (T i in items)\r
+                               if (addIterative(i, ref j, false, out tmp)) c++;\r
+\r
+                       size += c;\r
+               }\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. If this\r
+        /// collection has set semantics, only items not already in the collection\r
+        /// will be added.\r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
+        {\r
+            int c = 0;\r
+            T j = default(T);\r
+            bool tmp;\r
+\r
+            updatecheck();\r
+            foreach (T i in items)\r
+                if (addIterative(i, ref j, false, out tmp)) c++;\r
+\r
+            size += c;\r
+        }\r
+\r
+\r
+        /// <summary>\r
+               /// Add all the items from another collection with an enumeration order that \r
+               /// is increasing in the items. <para>The idea is that the implementation may use\r
+               /// a faster algorithm to merge the two collections.</para>\r
+               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
+               /// not to be in increasing order.\r
+               /// </summary>\r
+               /// <param name="items">The collection to add.</param>\r
+               [Tested]\r
+               public void AddSorted(MSG.IEnumerable<T> items)\r
+               {\r
+                       if (size > 0)\r
+                               AddAll(items);\r
+                       else\r
+                       {\r
+                               updatecheck();\r
+                               addSorted(items, true);\r
+                       }\r
+               }\r
+\r
+               #region add-sorted helpers\r
+               \r
+               //Create a RB tree from x+2^h-1  (x < 2^h, h>=1) nodes taken from a\r
+               //singly linked list of red nodes using only the right child refs.\r
+               //The x nodes at depth h+1 will be red, the rest black.\r
+               //(h is the blackdepth of the resulting tree)\r
+               static Node maketreer(ref Node rest, int blackheight, int maxred, int red)\r
+               {\r
+                       if (blackheight == 1)\r
+                       {\r
+                               Node top = rest;\r
+\r
+                               rest = rest.right;\r
+                               if (red > 0)\r
+                               {\r
+                                       top.right = null;\r
+                                       rest.left = top;\r
+                                       top = rest;\r
+#if BAG\r
+                                       top.size += top.left.size;\r
+#elif MAINTAIN_SIZE\r
+                                       top.size = 1 + red;\r
+#endif\r
+                                       rest = rest.right;\r
+                                       red--;\r
+                               }\r
+\r
+                               if (red > 0)\r
+                               {\r
+#if BAG\r
+                                       top.size += rest.size;\r
+#endif\r
+                                       top.right = rest;\r
+                                       rest = rest.right;\r
+                                       top.right.right = null;\r
+                               }\r
+                               else\r
+                                       top.right = null;\r
+\r
+                               top.red = false;\r
+                               return top;\r
+                       }\r
+                       else\r
+                       {\r
+                               maxred >>=1;\r
+\r
+                               int lred = red > maxred ? maxred : red;\r
+                               Node left = maketreer(ref rest, blackheight - 1, maxred, lred);\r
+                               Node top = rest;\r
+\r
+                               rest = rest.right;\r
+                               top.left = left;\r
+                               top.red = false;\r
+#if MAINTAIN_RANK\r
+                               top.rank = (short)blackheight;\r
+#endif\r
+                               top.right = maketreer(ref rest, blackheight - 1, maxred, red - lred);\r
+#if BAG\r
+                               top.size = top.items + top.left.size + top.right.size;\r
+#elif MAINTAIN_SIZE\r
+                               top.size = (maxred << 1) - 1 + red;\r
+#endif\r
+                               return top;\r
+                       }\r
+               }\r
+\r
+\r
+               void addSorted(MSG.IEnumerable<T> items, bool safe)\r
+               {\r
+                       MSG.IEnumerator<T> e = items.GetEnumerator();;\r
+                       if (size > 0)\r
+                               throw new ApplicationException("This can't happen");\r
+\r
+                       if (!e.MoveNext())\r
+                               return;\r
+\r
+                       //To count theCollect \r
+                       Node head = new Node(), tail = head;\r
+                       int z = 1;\r
+                       T lastitem = tail.item = e.Current;\r
+#if BAG\r
+                       int ec=0;\r
+#endif\r
+\r
+                       while (e.MoveNext())\r
+                       {\r
+#if BAG\r
+                               T thisitem = e.Current;\r
+                               int comp = comparer.Compare(lastitem, thisitem);\r
+                               if (comp>0)\r
+                                       throw new ArgumentException("Argument not sorted");\r
+                               if (comp == 0)\r
+                               {\r
+                                       tail.items++;\r
+                                       ec++;\r
+                               }\r
+                               else\r
+                               {\r
+                                       tail.size = tail.items;\r
+                                       z++;\r
+                                       tail.right = new Node();\r
+                                       tail = tail.right;\r
+                                       lastitem = tail.item = thisitem;\r
+#if NCP\r
+                                       tail.generation = generation;\r
+#endif\r
+                               }\r
+#else\r
+                               z++;\r
+                               tail.right = new Node();\r
+                               tail = tail.right;\r
+                               tail.item = e.Current;\r
+                               if (safe)\r
+                               {\r
+                                       if (comparer.Compare(lastitem, tail.item) >= 0)\r
+                                               throw new ArgumentException("Argument not sorted");\r
+\r
+                                       lastitem = tail.item;\r
+                               }\r
+#if NCP\r
+                               tail.generation = generation;\r
+#endif\r
+#endif\r
+                       }\r
+#if BAG\r
+                       tail.size = tail.items;\r
+#endif                         \r
+                       int blackheight = 0, red = z, maxred = 1;\r
+\r
+                       while (maxred <= red)\r
+                       {\r
+                               red -= maxred;\r
+                               maxred <<= 1;\r
+                               blackheight++;\r
+                       }\r
+\r
+                       root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);\r
+                       blackdepth = blackheight;\r
+                       size = z;\r
+#if BAG\r
+                       size += ec;\r
+#endif                         \r
+                       return;\r
+               }\r
+\r
+               #endregion\r
+\r
+#if BAG\r
+               /// <summary></summary>\r
+               /// <value>True since this collection has bag semantics.</value>\r
+               [Tested]\r
+               public bool AllowsDuplicates { [Tested]get { return true; } }\r
+#else\r
+               /// <summary></summary>\r
+               /// <value>False since this tree has set semantics.</value>\r
+               [Tested]\r
+               public bool AllowsDuplicates { [Tested]get { return false; } }\r
+#endif\r
+\r
+               #endregion\r
+\r
+               #region IEditableCollection<T> Members\r
+                       \r
+\r
+               /// <summary>\r
+               /// The value is symbolic indicating the type of asymptotic complexity\r
+               /// in terms of the size of this collection (worst-case or amortized as\r
+               /// relevant).\r
+               /// </summary>\r
+               /// <value>Speed.Log</value>\r
+               [Tested]\r
+               public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }\r
+\r
+\r
+               [Tested]\r
+               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
+\r
+\r
+               [Tested]\r
+               bool ICollection<T>.Equals(ICollection<T> that)\r
+               { return unsequencedequals(that); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains (an item equivalent to according to the\r
+               /// itemhasher) a particular value.\r
+               /// </summary>\r
+               /// <param name="item">The value to check for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public bool Contains(T item)\r
+               {\r
+                       Node next; int comp = 0;\r
+\r
+                       next = root;\r
+                       while (next != null)\r
+                       {\r
+                comp = comparer.Compare(next.item, item);\r
+                if (comp == 0)\r
+                                       return true;\r
+\r
+                               next = comp < 0 ? right(next) : left(next);\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               //Variant for dictionary use\r
+               //Will return the actual matching item in the ref argument.\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public bool Find(ref T item)\r
+               {\r
+                       Node next; int comp = 0;\r
+\r
+                       next = root;\r
+                       while (next != null)\r
+                       {\r
+                comp = comparer.Compare(next.item, item);\r
+                if (comp == 0)\r
+                               {\r
+                                       item = next.item;\r
+                                       return true;\r
+                               }\r
+\r
+                               next = comp < 0 ? right(next) : left(next);\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find or add the item to the tree. If the tree does not contain\r
+               /// an item equivalent to this item add it, else return the exisiting\r
+               /// one in the ref argument. \r
+               ///\r
+               /// </summary>\r
+               /// <param name="item"></param>\r
+               /// <returns>True if item was found</returns>\r
+               [Tested]\r
+               public bool FindOrAdd(ref T item)\r
+               {\r
+                       updatecheck();\r
+            bool wasfound;\r
+\r
+            //Note: blackdepth of the tree is set inside addIterative\r
+                       if (addIterative(item, ref item, false, out wasfound))\r
+                       {\r
+                               size++;\r
+#if MAINTAIN_EXTREMA\r
+                               if (Compare(item, min) < 0)\r
+                                       min = item;\r
+                               else if (Compare(item, max) > 0)\r
+                                       max = item;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = root.height;\r
+#endif\r
+                               return wasfound;\r
+                       }\r
+                       else\r
+                               return true;\r
+\r
+               }\r
+\r
+\r
+               //For dictionary use. \r
+               //If found, the matching entry will be updated with the new item.\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
+               /// this updates all equivalent copies in\r
+               /// the collection.\r
+               /// </summary>\r
+               /// <param name="item">Value to update.</param>\r
+               /// <returns>True if the item was found and hence updated.</returns>\r
+               [Tested]\r
+               public bool Update(T item)\r
+               {\r
+                       updatecheck();\r
+#if NCP\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+#endif\r
+                       Node cursor = root;\r
+                       int comp = 0;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                comp = comparer.Compare(cursor.item, item);\r
+                if (comp == 0)\r
+                               {\r
+#if NCP\r
+                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                                       cursor.item = item;\r
+#if NCP\r
+                                       while (level > 0)\r
+                                       {\r
+                                               Node child = cursor;\r
+\r
+                                               cursor = path[--level];\r
+                                               path[level] = null;\r
+#if NCP\r
+                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#else\r
+                                               if (Node.CopyNode(maxsnapid, ref cursor, generation))\r
+                                               {\r
+                                                       if (dirs[level] > 0)\r
+                                                               cursor.left = child;\r
+                                                       else\r
+                                                               cursor.right = child;\r
+                                               }\r
+#endif\r
+                                       }\r
+\r
+                                       root = cursor;\r
+#endif\r
+                                       return true;\r
+                               }\r
+#if NCP\r
+                               dirs[level] = comp;\r
+                               path[level++] = cursor;\r
+#endif\r
+                               cursor = comp < 0 ? cursor.right : cursor.left;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value; else add the value to the collection. \r
+               ///\r
+               /// <p>NOTE: the bag implementation is currently wrong!</p>\r
+               /// </summary>\r
+               /// <param name="item">Value to add or update.</param>\r
+               /// <returns>True if the item was found and updated (hence not added).</returns>\r
+               [Tested]\r
+               public bool UpdateOrAdd(T item)\r
+               {\r
+                       updatecheck();\r
+            bool wasfound;\r
+\r
+            //Note: blackdepth of the tree is set inside addIterative\r
+                       if (addIterative(item, ref item, true, out wasfound))\r
+                       {\r
+                               size++;\r
+#if MAINTAIN_EXTREMA\r
+                               if (Compare(item, min) < 0)\r
+                                       min = item;\r
+                               else if (Compare(item, max) > 0)\r
+                                       max = item;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = root.height;\r
+#endif\r
+                               return wasfound;\r
+                       }\r
+                       else\r
+                               return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection. If the collection has bag\r
+               /// semantics only one copy equivalent to the supplied item is removed. \r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public bool Remove(T item)\r
+               {\r
+                       updatecheck();\r
+                       if (root == null)\r
+                               return false;\r
+\r
+                       return removeIterative(ref item, false);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection if found. If the collection\r
+               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
+               /// which one is implementation dependent. \r
+               /// If an item was removed, report a binary copy of the actual item removed in \r
+               /// the argument.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove on input.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public bool RemoveWithReturn(ref T item)\r
+               {\r
+                       updatecheck();\r
+                       if (root == null)\r
+                               return false;\r
+\r
+                       return removeIterative(ref item, false);\r
+               }\r
+\r
+\r
+               private bool removeIterative(ref T item, bool all)\r
+               {\r
+                       //Stage 1: find item\r
+                       stackcheck();\r
+\r
+                       int level = 0, comp;\r
+                       Node cursor = root;\r
+\r
+                       while (true)\r
+                       {\r
+                comp = comparer.Compare(cursor.item, item);\r
+                if (comp == 0)\r
+                               {\r
+                                       item = cursor.item;\r
+#if BAG\r
+                                       if (!all && cursor.items > 1)\r
+                                       {\r
+#if NCP\r
+                                               Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                                               cursor.items--;\r
+                                               cursor.size--;\r
+                                               while (level-- > 0)\r
+                                               {\r
+                                                       Node kid = cursor;\r
+\r
+                                                       cursor = path[level];\r
+#if NCP\r
+                                                       Node.update(ref cursor, dirs[level] > 0,  kid,maxsnapid,generation);\r
+#endif\r
+                                                       cursor.size--;\r
+                                                       path[level] = null;\r
+                                               }\r
+                                               size--;\r
+                                               return true;\r
+                                       }\r
+#endif\r
+                                       break;\r
+                               }\r
+\r
+                               Node child = comp > 0 ? cursor.left : cursor.right;\r
+\r
+                               if (child == null)\r
+                                       return false;\r
+\r
+                               dirs[level] = comp;\r
+                               path[level++] = cursor;\r
+                               cursor = child;\r
+                       }\r
+\r
+                       return removeIterativePhase2(cursor, level);\r
+               }\r
+\r
+\r
+               private bool removeIterativePhase2(Node cursor, int level)\r
+               {\r
+                       if (size == 1)\r
+                       {\r
+                               clear();\r
+                               return true;\r
+                       }\r
+\r
+#if MAINTAIN_EXTREMA\r
+                       if (Compare(cursor.item, min) == 0)\r
+                               min = cursor.right != null ? cursor.right.item : path[level - 1].item;\r
+                       else if (Compare(cursor.item, max) == 0)\r
+                               max = cursor.left != null ? cursor.left.item : path[level - 1].item;\r
+#endif\r
+#if BAG\r
+                       int removedcount = cursor.items;\r
+                       size -= removedcount;\r
+#else\r
+                       //We are certain to remove one node:\r
+                       size--;\r
+#endif\r
+                       //Stage 2: if item's node has no null child, find predecessor\r
+                       int level_of_item = level;\r
+\r
+                       if (cursor.left != null && cursor.right != null)\r
+                       {\r
+                               dirs[level] = 1;\r
+                               path[level++] = cursor;\r
+                               cursor = cursor.left;\r
+                               while (cursor.right != null)\r
+                               {\r
+                                       dirs[level] = -1;\r
+                                       path[level++] = cursor;\r
+                                       cursor = cursor.right;\r
+                               }\r
+#if NCP\r
+                               Node.CopyNode(ref path[level_of_item], maxsnapid, generation);\r
+#endif\r
+                               path[level_of_item].item = cursor.item;\r
+#if BAG\r
+                               path[level_of_item].items = cursor.items;\r
+#endif\r
+                       }\r
+\r
+                       //Stage 3: splice out node to be removed\r
+                       Node newchild = cursor.right == null ? cursor.left : cursor.right;\r
+                       bool demote_or_rotate = newchild == null && !cursor.red;\r
+\r
+                       //assert newchild.red \r
+                       if (newchild != null)\r
+                       {\r
+                               newchild.red = false;\r
+                       }\r
+\r
+                       if (level == 0)\r
+                       {\r
+                               root = newchild;\r
+#if MAINTAIN_HEIGHT\r
+                               depth = 0;\r
+#endif\r
+                               return true;\r
+                       }\r
+\r
+                       level--;\r
+                       cursor = path[level];\r
+                       path[level] = null;\r
+\r
+                       int comp = dirs[level];\r
+                       Node childsibling;\r
+#if NCP\r
+                       Node.update(ref cursor, comp > 0, newchild, maxsnapid, generation);\r
+#else\r
+                       if (comp > 0)\r
+                               cursor.left = newchild;\r
+                       else\r
+                               cursor.right = newchild;\r
+#endif\r
+                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
+#if BAG\r
+                       cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                       cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                       fixheight(cursor);\r
+#endif\r
+\r
+                       //Stage 4: demote till we must rotate\r
+                       Node farnephew = null, nearnephew = null;\r
+\r
+                       while (demote_or_rotate)\r
+                       {\r
+                               if (childsibling.red)\r
+                                       break; //rotate 2+?\r
+\r
+                               farnephew = comp > 0 ? childsibling.right : childsibling.left;\r
+                               if (farnephew != null && farnephew.red)\r
+                                       break; //rotate 1b\r
+\r
+                               nearnephew = comp > 0 ? childsibling.left : childsibling.right;\r
+                               if (nearnephew != null && nearnephew.red)\r
+                                       break; //rotate 1c\r
+\r
+                               //demote cursor\r
+                               childsibling.red = true;\r
+#if MAINTAIN_RANK\r
+                               cursor.rank--;\r
+#endif\r
+                               if (level == 0)\r
+                               {\r
+                                       cursor.red = false;\r
+                                       blackdepth--;\r
+#if MAINTAIN_HEIGHT\r
+                                       depth = root.height;\r
+#endif\r
+#if NCP\r
+                                       root = cursor;\r
+#endif\r
+                                       return true;\r
+                               }\r
+                               else if (cursor.red)\r
+                               {\r
+                                       cursor.red = false;\r
+                                       demote_or_rotate = false;\r
+                                       break; //No rotation\r
+                               }\r
+                               else\r
+                               {\r
+                                       Node child = cursor;\r
+\r
+                                       cursor = path[--level];\r
+                                       path[level] = null;\r
+                                       comp = dirs[level];\r
+                                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
+#if NCP\r
+                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
+#endif\r
+#if BAG\r
+                                       cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                       }\r
+\r
+                       //Stage 5: rotate \r
+                       if (demote_or_rotate)\r
+                       {\r
+                               //At start:\r
+                               //parent = cursor (temporary for swapping nodes)\r
+                               //childsibling is the sibling of the updated child (x)\r
+                               //cursor is always the top of the subtree\r
+                               Node parent = cursor;\r
+\r
+                               if (childsibling.red)\r
+                               {//Case 2 and perhaps more. \r
+                                       //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null \r
+                                       //(and black). The grandnephews are children of nearnephew\r
+                                       Node neargrandnephew, fargrandnephew;\r
+\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               nearnephew = childsibling.left;\r
+                                               farnephew = childsibling.right;\r
+                                               neargrandnephew = nearnephew.left;\r
+                                               fargrandnephew = nearnephew.right;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               nearnephew = childsibling.right;\r
+                                               farnephew = childsibling.left;\r
+                                               neargrandnephew = nearnephew.right;\r
+                                               fargrandnephew = nearnephew.left;\r
+                                       }\r
+\r
+                                       if (fargrandnephew != null && fargrandnephew.red)\r
+                                       {//Case 2+1b\r
+#if NCP\r
+                                               Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
+\r
+                                               //The end result of this will always be e copy of parent\r
+                                               Node.update(ref parent, comp < 0, neargrandnephew, maxsnapid, generation);\r
+                                               Node.update(ref childsibling, comp > 0, nearnephew, maxsnapid, generation);\r
+#endif\r
+                                               if (comp > 0)\r
+                                               {\r
+                                                       nearnephew.left = parent;\r
+                                                       parent.right = neargrandnephew;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       nearnephew.right = parent;\r
+                                                       parent.left = neargrandnephew;\r
+                                               }\r
+\r
+                                               cursor = childsibling;\r
+                                               childsibling.red = false;\r
+                                               nearnephew.red = true;\r
+                                               fargrandnephew.red = false;\r
+#if MAINTAIN_RANK\r
+                                               nearnephew.rank++;\r
+                                               parent.rank--;\r
+#endif\r
+#if BAG\r
+                                               cursor.size = parent.size;\r
+                                               nearnephew.size = cursor.size - cursor.items - farnephew.size;\r
+                                               parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size;\r
+#elif MAINTAIN_SIZE\r
+                                               cursor.size = parent.size;\r
+                                               nearnephew.size = cursor.size - 1 - farnephew.size;\r
+                                               parent.size = nearnephew.size - 1 - fargrandnephew.size;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(parent);\r
+                                               fixheight(nearnephew);\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                                       else if (neargrandnephew != null && neargrandnephew.red)\r
+                                       {//Case 2+1c\r
+#if NCP\r
+                                               Node.CopyNode(ref neargrandnephew, maxsnapid, generation);\r
+#endif\r
+                                               if (comp > 0)\r
+                                               {\r
+#if NCP\r
+                                                       Node.update(ref childsibling, true, neargrandnephew, maxsnapid, generation);\r
+                                                       Node.update(ref nearnephew, true, neargrandnephew.right, maxsnapid, generation);\r
+                                                       Node.update(ref parent, false, neargrandnephew.left, maxsnapid, generation);\r
+#else\r
+                                                       childsibling.left = neargrandnephew;\r
+                                                       nearnephew.left = neargrandnephew.right;\r
+                                                       parent.right = neargrandnephew.left;\r
+#endif\r
+                                                       neargrandnephew.left = parent;\r
+                                                       neargrandnephew.right = nearnephew;\r
+                                               }\r
+                                               else\r
+                                               {\r
+#if NCP\r
+                                                       Node.update(ref childsibling, false, neargrandnephew, maxsnapid, generation);\r
+                                                       Node.update(ref nearnephew, false, neargrandnephew.left, maxsnapid, generation);\r
+                                                       Node.update(ref parent, true, neargrandnephew.right, maxsnapid, generation);\r
+#else\r
+                                                       childsibling.right = neargrandnephew;\r
+                                                       nearnephew.right = neargrandnephew.left;\r
+                                                       parent.left = neargrandnephew.right;\r
+#endif\r
+                                                       neargrandnephew.right = parent;\r
+                                                       neargrandnephew.left = nearnephew;\r
+                                               }\r
+\r
+                                               cursor = childsibling;\r
+                                               childsibling.red = false;\r
+#if MAINTAIN_RANK\r
+                                               neargrandnephew.rank++;\r
+                                               parent.rank--;\r
+#endif\r
+#if BAG\r
+                                               cursor.size = parent.size;\r
+                                               parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                               nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
+                                               neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size;\r
+#elif MAINTAIN_SIZE\r
+                                               cursor.size = parent.size;\r
+                                               parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                               nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
+                                               neargrandnephew.size = 1 + parent.size + nearnephew.size;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(parent);\r
+                                               fixheight(nearnephew);\r
+                                               fixheight(neargrandnephew);\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                                       else\r
+                                       {//Case 2 only\r
+#if NCP\r
+                                               Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
+                                               Node.update(ref childsibling, comp > 0, parent, maxsnapid, generation);\r
+#else\r
+                                               if (comp > 0)\r
+                                               {\r
+                                                       childsibling.left = parent;\r
+                                                       parent.right = nearnephew;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       childsibling.right = parent;\r
+                                                       parent.left = nearnephew;\r
+                                               }\r
+#endif\r
+                                               cursor = childsibling;\r
+                                               childsibling.red = false;\r
+                                               nearnephew.red = true;\r
+#if MAINTAIN_RANK\r
+                                               parent.rank--;\r
+#endif\r
+#if BAG\r
+                                               cursor.size = parent.size;\r
+                                               parent.size -= farnephew.size + cursor.items;\r
+#elif MAINTAIN_SIZE\r
+                                               cursor.size = parent.size;\r
+                                               parent.size -= farnephew.size + 1;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(parent);\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                               }\r
+                               else if (farnephew != null && farnephew.red)\r
+                               {//Case 1b\r
+                                       nearnephew = comp > 0 ? childsibling.left : childsibling.right;         \r
+#if NCP\r
+                                       Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
+                                       Node.CopyNode(ref childsibling, maxsnapid, generation);\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               childsibling.left = parent;\r
+                                               childsibling.right = farnephew;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               childsibling.right = parent;\r
+                                               childsibling.left = farnephew;\r
+                                       }\r
+#else\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               childsibling.left = parent;\r
+                                               parent.right = nearnephew;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               childsibling.right = parent;\r
+                                               parent.left = nearnephew;\r
+                                       }\r
+#endif\r
+                                       cursor = childsibling;\r
+                                       cursor.red = parent.red;\r
+                                       parent.red = false;\r
+                                       farnephew.red = false;\r
+\r
+#if MAINTAIN_RANK\r
+                                       childsibling.rank++;\r
+                                       parent.rank--;\r
+#endif\r
+#if BAG\r
+                                       cursor.size = parent.size;\r
+                                       parent.size -= farnephew.size + cursor.items;\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size = parent.size;\r
+                                       parent.size -= farnephew.size + 1;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(parent);\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                               else if (nearnephew != null && nearnephew.red)\r
+                               {//Case 1c\r
+#if NCP\r
+                                       Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
+#endif\r
+                                       if (comp > 0)\r
+                                       {\r
+#if NCP\r
+                                               Node.update(ref childsibling, true, nearnephew.right, maxsnapid, generation);\r
+                                               Node.update(ref parent, false, nearnephew.left, maxsnapid, generation);\r
+#else\r
+                                               childsibling.left = nearnephew.right;\r
+                                               parent.right = nearnephew.left;\r
+#endif\r
+                                               nearnephew.left = parent;\r
+                                               nearnephew.right = childsibling;\r
+                                       }\r
+                                       else\r
+                                       {\r
+#if NCP\r
+                                               Node.update(ref childsibling, false, nearnephew.left, maxsnapid, generation);\r
+                                               Node.update(ref parent, true, nearnephew.right, maxsnapid, generation);\r
+#else\r
+                                               childsibling.right = nearnephew.left;\r
+                                               parent.left = nearnephew.right;\r
+#endif\r
+                                               nearnephew.right = parent;\r
+                                               nearnephew.left = childsibling;\r
+                                       }\r
+\r
+                                       cursor = nearnephew;\r
+                                       cursor.red = parent.red;\r
+                                       parent.red = false;\r
+#if MAINTAIN_RANK\r
+                                       nearnephew.rank++;\r
+                                       parent.rank--;\r
+#endif\r
+#if BAG\r
+                                       cursor.size = parent.size;\r
+                                       parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                       childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size = parent.size;\r
+                                       parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                       childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(parent);\r
+                                       fixheight(childsibling);\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                               else\r
+                               {//Case 1a can't happen\r
+                                       throw new Exception("Case 1a can't happen here");\r
+                               }\r
+\r
+                               //Resplice cursor:\r
+                               if (level == 0)\r
+                               {\r
+                                       root = cursor;\r
+                               }\r
+                               else\r
+                               {\r
+                                       Node swap = cursor;\r
+\r
+                                       cursor = path[--level];\r
+                                       path[level] = null;\r
+#if NCP\r
+                                       Node.update(ref cursor, dirs[level] > 0, swap, maxsnapid, generation);\r
+#else\r
+                               \r
+                                       if (dirs[level] > 0)\r
+                                               cursor.left = swap;\r
+                                       else\r
+                                               cursor.right = swap;\r
+#endif\r
+#if BAG\r
+                                       cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                       }\r
+\r
+                       //Stage 6: fixup to the root\r
+                       while (level > 0)\r
+                       {\r
+                               Node child = cursor;\r
+\r
+                               cursor = path[--level];\r
+                               path[level] = null;\r
+#if NCP\r
+                               if (child != (dirs[level] > 0 ? cursor.left : cursor.right))\r
+                                       Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+#if BAG\r
+                               cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                               cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               fixheight(cursor);\r
+#endif\r
+                       }\r
+\r
+#if MAINTAIN_HEIGHT\r
+                       depth = root.height;\r
+#endif\r
+#if NCP\r
+                       root = cursor;\r
+#endif\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from this collection.\r
+               /// </summary>\r
+               [Tested]\r
+               public void Clear()\r
+               {\r
+                       updatecheck();\r
+                       clear();\r
+               }\r
+\r
+\r
+               private void clear()\r
+               {\r
+                       size = 0;\r
+                       root = null;\r
+                       blackdepth = 0;\r
+#if MAINTAIN_HEIGHT\r
+                       depth = 0;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in another collection from this one. If this collection\r
+               /// has bag semantics, take multiplicities into account.\r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       T jtem;\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               if (root == null)\r
+                                       break;\r
+\r
+                               jtem = item;\r
+                               removeIterative(ref jtem, false);\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items not in some other collection from this one. If this collection\r
+               /// has bag semantics, take multiplicities into account.\r
+               /// </summary>\r
+               /// <param name="items">The items to retain.</param>\r
+               [Tested]\r
+               public void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       //A much more efficient version is possible if items is sorted like this.\r
+                       //Well, it is unclear how efficient it would be.\r
+                       //We could use a marking method!?\r
+                       TreeSet<T> t = (TreeSet<T>)MemberwiseClone();\r
+\r
+                       t.Clear();\r
+                       foreach (T item in items)\r
+                               if (ContainsCount(item) > t.ContainsCount(item))\r
+                                       t.Add(item);\r
+\r
+                       root = t.root;\r
+                       size = t.size;\r
+                       blackdepth = t.blackdepth;\r
+#if MAINTAIN_HEIGHT\r
+                       depth = t.depth;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains all the values in another collection.\r
+               /// If this collection has bag semantics (<code>NoDuplicates==false</code>)\r
+               /// the check is made with respect to multiplicities, else multiplicities\r
+               /// are not taken into account.\r
+               /// </summary>\r
+               /// <param name="items">The </param>\r
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+               [Tested]\r
+               public bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       //This is worst-case O(m*logn)\r
+                       foreach (T item in items)\r
+                               if (!Contains(item)) return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               //Higher order:\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the items of this\r
+               /// indexed sorted collection satisfying a certain predicate.\r
+               /// </summary>\r
+               /// <param name="filter">The filter delegate defining the predicate.</param>\r
+               /// <returns>The new indexed sorted collection.</returns>\r
+               [Tested]\r
+               public IIndexedSorted<T> FindAll(Filter<T> filter)\r
+               {\r
+                       TreeSet<T> res = new TreeSet<T>(comparer);\r
+                       MSG.IEnumerator<T> e = GetEnumerator();\r
+                       Node head = null, tail = null;\r
+                       int z = 0;\r
+#if BAG\r
+                       int ec = 0;\r
+#endif\r
+                       while (e.MoveNext())\r
+                       {\r
+                               T thisitem = e.Current;\r
+#if BAG\r
+                               //We could document that filter will only be called \r
+                               //once on each unique item. That might even be good for the user!\r
+                               if (tail!=null && comparer.Compare(thisitem, tail.item) == 0)\r
+                               {\r
+                                       tail.items++;\r
+                                       ec++;\r
+                                       continue;\r
+                               }\r
+#endif\r
+                               if (filter(thisitem))\r
+                               {\r
+                                       if (head == null)\r
+                                       {\r
+                                               head = tail = new Node();\r
+                                       }\r
+                                       else\r
+                                       {\r
+#if BAG\r
+                                               tail.size = tail.items;\r
+#endif\r
+                                               tail.right = new Node();\r
+                                               tail = tail.right;\r
+                                       }\r
+\r
+                                       tail.item = thisitem;\r
+                                       z++;\r
+                               }\r
+                       }\r
+#if BAG\r
+                       if (tail!=null)\r
+                               tail.size = tail.items;\r
+#endif\r
+\r
+                       if (z == 0)\r
+                               return res;\r
+\r
+                       int blackheight = 0, red = z, maxred = 1;\r
+\r
+                       while (maxred <= red)\r
+                       {\r
+                               red -= maxred;\r
+                               maxred <<= 1;\r
+                               blackheight++;\r
+                       }\r
+\r
+                       res.root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);\r
+                       res.blackdepth = blackheight;\r
+                       res.size = z;\r
+#if BAG\r
+                       res.size += ec;\r
+#endif\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the results of\r
+               /// mapping all items of this list.\r
+               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
+               /// the items of this collection (with respect to the two given comparison \r
+               /// relations).\r
+               /// </summary>\r
+               /// <param name="mapper">The delegate definging the map.</param>\r
+               /// <param name="c">The comparion relation to use for the result.</param>\r
+               /// <returns>The new sorted collection.</returns>\r
+               [Tested]\r
+               public IIndexedSorted<V> Map<V>(Mapper<T,V> mapper, IComparer<V> c)\r
+               {\r
+                       TreeSet<V> res = new TreeSet<V>(c);\r
+\r
+                       if (size == 0)\r
+                               return res;\r
+\r
+                       MSG.IEnumerator<T> e = GetEnumerator();\r
+                       TreeSet<V>.Node head = null, tail = null;\r
+                       V oldv = default(V);\r
+                       int z = 0;\r
+#if BAG\r
+                       T lastitem = default(T);\r
+#endif\r
+                       while (e.MoveNext())\r
+                       {\r
+                               T thisitem = e.Current;\r
+#if BAG\r
+                               //We could document that mapper will only be called \r
+                               //once on each unique item. That might even be good for the user!\r
+                               if (tail != null && comparer.Compare(thisitem, lastitem) == 0)\r
+                               {\r
+                                       tail.items++;\r
+                                       continue;\r
+                               }\r
+#endif\r
+                               V newv = mapper(thisitem);\r
+\r
+                               if (head == null)\r
+                               {\r
+                                       head = tail = new TreeSet<V>.Node();\r
+                                       z++;\r
+                               }\r
+                               else\r
+                               {\r
+                                       int comp = c.Compare(oldv, newv);\r
+#if BAG\r
+                                       if (comp == 0)\r
+                                       {\r
+                                               tail.items++;\r
+                                               continue;\r
+                                       }\r
+                                       if (comp > 0)\r
+#else\r
+                                       if (comp >= 0)\r
+#endif\r
+                                               throw new ArgumentException("mapper not monotonic");\r
+#if BAG\r
+                                       tail.size = tail.items;\r
+#endif\r
+                                       tail.right = new TreeSet<V>.Node();\r
+                                       tail = tail.right;\r
+                                       z++;\r
+                               }\r
+#if BAG\r
+                               lastitem = thisitem;\r
+#endif\r
+                               tail.item = oldv = newv;\r
+                       }\r
+\r
+#if BAG\r
+                       tail.size = tail.items;\r
+#endif\r
+\r
+                       int blackheight = 0, red = z, maxred = 1;\r
+\r
+                       while (maxred <= red)\r
+                       {\r
+                               red -= maxred;\r
+                               maxred <<= 1;\r
+                               blackheight++;\r
+                       }\r
+\r
+                       res.root = TreeSet<V>.maketreer(ref head, blackheight, maxred, red);\r
+                       res.blackdepth = blackheight;\r
+                       res.size = size;\r
+                       return res;\r
+               }\r
+\r
+\r
+               //below is the bag utility stuff\r
+               /// <summary>\r
+               /// Count the number of items of the collection equal to a particular value.\r
+               /// Returns 0 if and only if the value is not in the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to count.</param>\r
+               /// <returns>The number of copies found.</returns>\r
+               [Tested]\r
+               public int ContainsCount(T item)\r
+               {\r
+#if BAG\r
+                       Node next; int comp = 0;\r
+\r
+                       next = root;\r
+                       while (next != null)\r
+                       {\r
+                               comp = comparer.Compare(next.item, item);\r
+                               if (comp == 0)\r
+                                       return next.items;\r
+\r
+                               next = comp < 0 ? right(next) : left(next);\r
+                       }\r
+\r
+                       return 0;\r
+#else\r
+                       //Since we are strictly NoDuplicates we just do\r
+                       return Contains(item) ? 1 : 0;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items equivalent to a given value.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               [Tested]\r
+               public void RemoveAllCopies(T item)\r
+               {\r
+#if BAG\r
+                       updatecheck();\r
+                       removeIterative(ref item, true);\r
+#else\r
+                       \r
+                       Remove(item);\r
+#endif\r
+               }\r
+\r
+\r
+               #endregion\r
+\r
+               #region IIndexed<T> Members\r
+                       \r
+               private Node findNode(int i)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                       Node next = root;\r
+\r
+                       if (i >= 0 && i < size)\r
+                               while (true)\r
+                               {\r
+                                       int j = next.left == null ? 0 : next.left.size;\r
+\r
+                                       if (i > j)\r
+                                       {\r
+#if BAG\r
+                                               i -= j + next.items;                                    \r
+                                               if (i<0)\r
+                                                       return next;\r
+#else\r
+                                               i -= j + 1;\r
+#endif\r
+                                               next = next.right;\r
+                                       }\r
+                                       else if (i == j)\r
+                                               return next;\r
+                                       else\r
+                                               next = next.left;\r
+                               }\r
+\r
+                       throw new IndexOutOfRangeException();\r
+#else\r
+                       throw new NotSupportedException();\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <value>The i'th item of this list.</value>\r
+               /// <param name="i">the index to lookup</param>\r
+               [Tested]\r
+               public T this[int i] { [Tested] get { return findNode(i).item; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going forwrds from the start.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of item from start.</returns>\r
+               [Tested]\r
+               public int IndexOf(T item)\r
+               {\r
+                       int upper;\r
+\r
+                       return indexOf(item, out upper);\r
+               }\r
+\r
+\r
+               private int indexOf(T item, out int upper)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                       int ind = 0; Node next = root;\r
+\r
+                       while (next != null)\r
+                       {\r
+                int comp = comparer.Compare(item, next.item);\r
+\r
+                if (comp < 0)\r
+                                       next = next.left;\r
+                               else\r
+                               {\r
+                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
+\r
+                                       if (comp == 0)\r
+                                       {\r
+#if BAG\r
+                                               upper = ind + leftcnt + next.items - 1;\r
+                                               return ind + leftcnt;\r
+#else\r
+                                               return upper = ind + leftcnt;\r
+#endif\r
+                                       }\r
+                                       else\r
+                                       {\r
+#if BAG\r
+                                               ind = ind + next.items + leftcnt;\r
+#else\r
+                                               ind = ind + 1 + leftcnt;\r
+#endif\r
+                                               next = next.right;\r
+                                       }\r
+                               }\r
+                       }\r
+#endif\r
+                       upper = -1;\r
+                       return -1;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going backwords from the end.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of of item from the end.</returns>\r
+               [Tested]\r
+               public int LastIndexOf(T item)\r
+               {\r
+#if BAG\r
+                       int res;\r
+                       indexOf(item, out res);\r
+                       return res;\r
+#else\r
+                       //We have NoDuplicates==true for the set\r
+                       return IndexOf(item);\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the item at a specific position of the list.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <param name="i">The index of the item to remove.</param>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T RemoveAt(int i)\r
+               {\r
+                       updatecheck();\r
+#if MAINTAIN_SIZE\r
+                       if (i < 0 || i >= size)\r
+                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
+\r
+                       //We must follow the pattern of removeIterative()\r
+                       while (dirs.Length < 2 * blackdepth)\r
+                       {\r
+                               dirs = new int[2 * dirs.Length];\r
+                               path = new Node[2 * dirs.Length];\r
+                       }\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (true)\r
+                       {\r
+                               int j = cursor.left == null ? 0 : cursor.left.size;\r
+\r
+                               if (i > j)\r
+                               {\r
+#if BAG\r
+                                       i -= j + cursor.items;\r
+                                       if (i<0)\r
+                                               break;\r
+#else\r
+                                       i -= j + 1;\r
+#endif\r
+                                       dirs[level] = -1;\r
+                                       path[level++] = cursor;\r
+                                       cursor = cursor.right;\r
+                               }\r
+                               else if (i == j)\r
+                                       break;\r
+                               else\r
+                               {\r
+                                       dirs[level] = 1;\r
+                                       path[level++] = cursor;\r
+                                       cursor = cursor.left;\r
+                               }\r
+                       }\r
+\r
+                       T retval = cursor.item;\r
+\r
+#if BAG\r
+                       if (cursor.items>1)\r
+                       {\r
+                               resplicebag(level, cursor);\r
+                               size--;\r
+                               return retval;\r
+                       }\r
+#endif\r
+                       removeIterativePhase2(cursor, level);\r
+                       return retval;\r
+#else\r
+                       throw new NotSupportedException();\r
+#endif\r
+               }\r
+\r
+#if BAG\r
+               private void resplicebag(int level, Node cursor)\r
+               {\r
+#if NCP\r
+                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                       cursor.items--;\r
+                       cursor.size--;\r
+                       while (level-- > 0)\r
+                       {\r
+                               Node kid = cursor;\r
+\r
+                               cursor = path[level];\r
+#if NCP\r
+                               Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
+#endif\r
+                               cursor.size--;\r
+                               path[level] = null;\r
+                       }\r
+               }\r
+#endif\r
+               /// <summary>\r
+               /// Remove all items in an index interval.\r
+               /// <exception cref="IndexOutOfRangeException"/>???. \r
+               /// </summary>\r
+               /// <param name="start">The index of the first item to remove.</param>\r
+               /// <param name="count">The number of items to remove.</param>\r
+               [Tested]\r
+               public void RemoveInterval(int start, int count)\r
+               {\r
+                       if (start < 0 || count < 0)\r
+                               throw new ArgumentOutOfRangeException();\r
+\r
+                       if (start + count > this.size)\r
+                               throw new ArgumentException();\r
+\r
+                       updatecheck();\r
+\r
+                       //This is terrible for large count. We should split the tree at \r
+                       //the endpoints of the range and fuse the parts!\r
+                       //We really need good internal destructive split and catenate functions!\r
+                       for (int i = 0; i < count; i++)\r
+                               RemoveAt(start);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/>.\r
+               /// </summary>\r
+               /// <value>The directed collection of items in a specific index interval.</value>\r
+               /// <param name="start">The low index of the interval (inclusive).</param>\r
+               /// <param name="end">The high index of the interval (exclusive).</param>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> this[int start, int end]\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+                               checkRange(start, end - start);\r
+                               return new Interval(this, start, end - start, true);\r
+                       }\r
+               }\r
+\r
+               #region Interval nested class\r
+               class Interval: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
+               {\r
+                       int start, length, stamp;\r
+\r
+                       bool forwards;\r
+\r
+                       TreeSet<T> tree;\r
+\r
+\r
+                       internal Interval(TreeSet<T> tree, int start, int count, bool forwards)\r
+                       {\r
+#if NCP\r
+                               if (tree.isSnapShot)\r
+                                       throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+                               this.start = start; this.length = count;this.forwards = forwards;\r
+                               this.tree = tree; this.stamp = tree.stamp;\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+            public override int Count { [Tested]get { return length; } }\r
+\r
+\r
+            public override Speed CountSpeed { get { return Speed.Constant; } }\r
+            \r
+            [Tested]\r
+            public override MSG.IEnumerator<T> GetEnumerator()\r
+                       {\r
+#if MAINTAIN_SIZE\r
+                               tree.modifycheck(stamp);\r
+#if BAG\r
+                               int togo;\r
+#endif\r
+                               Node cursor = tree.root;\r
+                               Node[] path = new Node[2 * tree.blackdepth];\r
+                               int level = 0, totaltogo = length;\r
+\r
+                               if (totaltogo == 0)\r
+                                       yield break;\r
+\r
+                               if (forwards)\r
+                               {\r
+                                       int i = start;\r
+\r
+                                       while (true)\r
+                                       {\r
+                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
+\r
+                                               if (i > j)\r
+                                               {\r
+#if BAG\r
+                                                       i -= j + cursor.items;\r
+                                                       if (i < 0)\r
+                                                       {\r
+                                                               togo = cursor.items + i;\r
+                                                               break;\r
+                                                       }\r
+#else\r
+                                                       i -= j + 1;\r
+#endif\r
+                                                       cursor = cursor.right;\r
+                                               }\r
+                                               else if (i == j)\r
+                                               {\r
+#if BAG\r
+                                                       togo = cursor.items;\r
+#endif\r
+                                                       break;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       path[level++] = cursor;\r
+                                                       cursor = cursor.left;\r
+                                               }\r
+                                       }\r
+\r
+                                       T current = cursor.item;\r
+\r
+                                       while (totaltogo-- > 0)\r
+                                       {\r
+                                               yield return current;\r
+                                               tree.modifycheck(stamp);\r
+#if BAG\r
+                                               if (--togo > 0)\r
+                                                       continue;\r
+#endif\r
+                                               if (cursor.right != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.right;\r
+                                                       while (cursor.left != null)\r
+                                                               path[++level] = cursor = cursor.left;\r
+                                               }\r
+                                               else if (level == 0)\r
+                                                       yield break;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       int i = start + length - 1;\r
+\r
+                                       while (true)\r
+                                       {\r
+                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
+\r
+                                               if (i > j)\r
+                                               {\r
+#if BAG\r
+                                                       if (i - j < cursor.items)\r
+                                                       {\r
+                                                               togo = i - j + 1;\r
+                                                               break;\r
+                                                       }\r
+                                                       i -= j + cursor.items;\r
+#else\r
+                                                       i -= j + 1;\r
+#endif\r
+                                                       path[level++] = cursor;\r
+                                                       cursor = cursor.right;\r
+                                               }\r
+                                               else if (i == j)\r
+                                               {\r
+#if BAG\r
+                                                       togo = 1;\r
+#endif\r
+                                                       break;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       cursor = cursor.left;\r
+                                               }\r
+                                       }\r
+\r
+                                       T current = cursor.item;\r
+\r
+                                       while (totaltogo-- > 0)\r
+                                       {\r
+                                               yield return current;\r
+                                               tree.modifycheck(stamp);\r
+#if BAG\r
+                                               if (--togo > 0)\r
+                                                       continue;\r
+#endif\r
+                                               if (cursor.left != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.left;\r
+                                                       while (cursor.right != null)\r
+                                                               path[++level] = cursor = cursor.right;\r
+                                               }\r
+                                               else if (level == 0)\r
+                                                       yield break;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                       }\r
+                               }\r
+\r
+#else\r
+                       throw new NotSupportedException();\r
+#endif\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       public IDirectedCollectionValue<T> Backwards()\r
+                       { return new Interval(tree, start, length, !forwards); }\r
+\r
+\r
+                       [Tested]\r
+                       IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()\r
+                       { return Backwards(); }\r
+\r
+\r
+                       [Tested]\r
+                       public EnumerationDirection Direction\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;\r
+                               }\r
+                       }\r
+               }\r
+               #endregion\r
+\r
+               /// <summary>\r
+               /// Create a collection containing the same items as this collection, but\r
+               /// whose enumerator will enumerate the items backwards. The new collection\r
+               /// will become invalid if the original is modified. Method typicaly used as in\r
+               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
+               /// </summary>\r
+               /// <returns>The backwards collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+               #endregion\r
+\r
+               #region ISequenced Members\r
+               [Tested]\r
+               int ISequenced<T>.GetHashCode() { return sequencedhashcode(); }\r
+\r
+\r
+               [Tested]\r
+               bool ISequenced<T>.Equals(ISequenced<T> that) { return sequencedequals(that); }\r
+               #endregion\r
+\r
+               #region PriorityQueue Members\r
+\r
+        /// <summary>\r
+        /// The comparer object supplied at creation time for this collection\r
+        /// </summary>\r
+        /// <value>The comparer</value>\r
+        public IComparer<T> Comparer { get { return comparer; } }\r
+\r
+\r
+        /// <summary>\r
+               /// Find the current least item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The least item.</returns>\r
+               [Tested]\r
+               public T FindMin()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+#if MAINTAIN_EXTREMA\r
+                       return min;\r
+#else\r
+                       Node cursor = root, next = left(cursor);\r
+\r
+                       while (next != null)\r
+                       {\r
+                               cursor = next;\r
+                               next = left(cursor);\r
+                       }\r
+\r
+                       return cursor.item;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the least item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMin()\r
+               {\r
+                       updatecheck();\r
+\r
+                       //persistence guard?\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       //We must follow the pattern of removeIterative()\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (cursor.left != null)\r
+                       {\r
+                               dirs[level] = 1;\r
+                               path[level++] = cursor;\r
+                               cursor = cursor.left;\r
+                       }\r
+\r
+                       T retval = cursor.item;\r
+\r
+#if BAG\r
+                       if (cursor.items > 1)\r
+                       {\r
+                               resplicebag(level, cursor);\r
+                               size--;\r
+                               return retval;\r
+                       }\r
+#endif\r
+                       removeIterativePhase2(cursor, level);\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the current largest item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The largest item.</returns>\r
+               [Tested]\r
+               public T FindMax()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+#if MAINTAIN_EXTREMA\r
+                       return max;\r
+#else\r
+                       Node cursor = root, next = right(cursor);\r
+\r
+                       while (next != null)\r
+                       {\r
+                               cursor = next;\r
+                               next = right(cursor);\r
+                       }\r
+\r
+                       return cursor.item;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the largest item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMax()\r
+               {\r
+                       //persistence guard?\r
+                       updatecheck();\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       //We must follow the pattern of removeIterative()\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (cursor.right != null)\r
+                       {\r
+                               dirs[level] = -1;\r
+                               path[level++] = cursor;\r
+                               cursor = cursor.right;\r
+                       }\r
+\r
+                       T retval = cursor.item;\r
+\r
+#if BAG\r
+                       if (cursor.items > 1)\r
+                       {\r
+                               resplicebag(level, cursor);\r
+                               size--;\r
+                               return retval;\r
+                       }\r
+#endif\r
+                       removeIterativePhase2(cursor, level);\r
+                       return retval;\r
+               }\r
+               #endregion\r
+\r
+               #region IPredecesorStructure<T> Members\r
+\r
+               /// <summary>\r
+               /// Find the strict predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than or equal to the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the predecessor for.</param>\r
+               /// <returns>The predecessor.</returns>\r
+               [Tested]\r
+               public T Predecessor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp < 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = right(cursor);\r
+                               }\r
+                               else if (comp == 0)\r
+                               {\r
+                                       cursor = left(cursor);\r
+                                       while (cursor != null)\r
+                                       {\r
+                                               bestsofar = cursor;\r
+                                               cursor = right(cursor);\r
+                                       }\r
+                               }\r
+                               else\r
+                                       cursor = left(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak predecessor for.</param>\r
+               /// <returns>The weak predecessor.</returns>\r
+               [Tested]\r
+               public T WeakPredecessor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp < 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = right(cursor);\r
+                               }\r
+                               else if (comp == 0)\r
+                                       return cursor.item;\r
+                               else\r
+                                       cursor = left(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the strict successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than or equal to the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the successor for.</param>\r
+               /// <returns>The successor.</returns>\r
+               [Tested]\r
+               public T Successor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp > 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = left(cursor);\r
+                               }\r
+                               else if (comp == 0)\r
+                               {\r
+                                       cursor = right(cursor);\r
+                                       while (cursor != null)\r
+                                       {\r
+                                               bestsofar = cursor;\r
+                                               cursor = left(cursor);\r
+                                       }\r
+                               }\r
+                               else\r
+                                       cursor = right(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak successor for.</param>\r
+               /// <returns>The weak successor.</returns>\r
+               [Tested]\r
+               public T WeakSuccessor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp == 0)\r
+                                       return cursor.item;\r
+                               else if (comp > 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = left(cursor);\r
+                               }\r
+                               else\r
+                                       cursor = right(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
+               }\r
+\r
+               #endregion\r
+               \r
+               #region ISorted<T> Members\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items greater than or equal to a supplied value.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeFrom(T bot)\r
+               { return new Range(this, true, bot, false, default(T), EnumerationDirection.Forwards); }\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items between two supplied values.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)\r
+               { return new Range(this, true, bot, true, top, EnumerationDirection.Forwards); }\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items less than a supplied value.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeTo(T top)\r
+               { return new Range(this, false, default(T), true, top, EnumerationDirection.Forwards); }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a directed collection with the same items as this collection.\r
+               /// </summary>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeAll()\r
+               { return new Range(this, false, default(T), false, default(T), EnumerationDirection.Forwards); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot) { return RangeFrom(bot); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> ISorted<T>.RangeTo(T top) { return RangeTo(top); }\r
+\r
+\r
+               //Utility for CountXxxx. Actually always called with strict = true.\r
+               private int countTo(T item, bool strict)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                       int ind = 0, comp = 0; Node next = root;\r
+\r
+                       while (next != null)\r
+                       {\r
+                comp = comparer.Compare(item, next.item);\r
+                if (comp < 0)\r
+                                       next = next.left;\r
+                               else\r
+                               {\r
+                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
+#if BAG\r
+                                       if (comp == 0)\r
+                                               return strict ? ind + leftcnt : ind + leftcnt + next.items;\r
+                                       else\r
+                                       {\r
+                                               ind = ind + next.items + leftcnt;\r
+                                               next = next.right;\r
+                                       }\r
+#else\r
+                                       if (comp == 0)\r
+                                               return strict ? ind + leftcnt : ind + leftcnt + 1;\r
+                                       else\r
+                                       {\r
+                                               ind = ind + 1 + leftcnt;\r
+                                               next = next.right;\r
+                                       }\r
+#endif\r
+                               }\r
+                       }\r
+\r
+                       //if we get here, we are at the same side of the whole collection:\r
+                       return ind;\r
+#else\r
+                       throw new NotSupportedException("Code compiled w/o size!");\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Perform a search in the sorted collection for the ranges in which a\r
+               /// non-decreasing function from the item type to <code>int</code> is\r
+               /// negative, zero respectively positive. If the supplied cut function is\r
+               /// not non-decreasing, the result of this call is undefined.\r
+               /// </summary>\r
+               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
+               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
+               /// the <code>c.CompareTo(T that)</code> method.</param>\r
+               /// <param name="low">Returns the largest item in the collection, where the\r
+               /// cut function is negative (if any).</param>\r
+               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
+               /// on this collection.</param>\r
+               /// <param name="high">Returns the least item in the collection, where the\r
+               /// cut function is positive (if any).</param>\r
+               /// <param name="highIsValid">True if the cut function is positive somewhere\r
+               /// on this collection.</param>\r
+               /// <returns></returns>\r
+               [Tested]\r
+               public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)\r
+               {\r
+                       Node cursor = root, lbest = null, rbest = null;\r
+                       bool res = false;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                               int comp = c.CompareTo(cursor.item);\r
+\r
+                               if (comp > 0)\r
+                               {\r
+                                       lbest = cursor;\r
+                                       cursor = right(cursor);\r
+                               }\r
+                               else if (comp < 0)\r
+                               {\r
+                                       rbest = cursor;\r
+                                       cursor = left(cursor);\r
+                               }\r
+                               else\r
+                               {\r
+                                       res = true;\r
+\r
+                                       Node tmp = left(cursor);\r
+\r
+                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
+                                               tmp = left(tmp);\r
+\r
+                                       if (tmp != null)\r
+                                       {\r
+                                               lbest = tmp;\r
+                                               tmp = right(tmp);\r
+                                               while (tmp != null)\r
+                                               {\r
+                                                       if (c.CompareTo(tmp.item) > 0)\r
+                                                       {\r
+                                                               lbest = tmp;\r
+                                                               tmp = right(tmp);\r
+                                                       }\r
+                                                       else\r
+                                                               tmp = left(tmp);\r
+                                               }\r
+                                       }\r
+\r
+                                       tmp = right(cursor);\r
+                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
+                                               tmp = right(tmp);\r
+\r
+                                       if (tmp != null)\r
+                                       {\r
+                                               rbest = tmp;\r
+                                               tmp = left(tmp);\r
+                                               while (tmp != null)\r
+                                               {\r
+                                                       if (c.CompareTo(tmp.item) < 0)\r
+                                                       {\r
+                                                               rbest = tmp;\r
+                                                               tmp = left(tmp);\r
+                                                       }\r
+                                                       else\r
+                                                               tmp = right(tmp);\r
+                                               }\r
+                                       }\r
+\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (highIsValid = (rbest != null))\r
+                               high = rbest.item;\r
+                       else\r
+                               high = default(T);\r
+\r
+                       if (lowIsValid = (lbest != null))\r
+                               low = lbest.item;\r
+                       else\r
+                               low = default(T);\r
+\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items at or above a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountFrom(T bot) { return size - countTo(bot, true); }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountFromTo(T bot, T top)\r
+               {\r
+            if (comparer.Compare(bot, top) >= 0)\r
+                return 0;\r
+\r
+                       return countTo(top, true) - countTo(bot, true);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountTo(T top) { return countTo(top, true); }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection above or at a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeFrom(T low)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int count = CountFrom(low);\r
+\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       for (int i = 0; i < count; i++)\r
+                               DeleteMax();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeFromTo(T low, T hi)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int count = CountFromTo(low, hi);\r
+\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       for (int i = 0; i < count; i++)\r
+                               Remove(Predecessor(hi));\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeTo(T hi)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int count = CountTo(hi);\r
+\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       for (int i = 0; i < count; i++)\r
+                               DeleteMin();\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IPersistent<T> Members\r
+\r
+               private bool disposed;\r
+\r
+\r
+\r
+               /// <summary>\r
+               /// If this tree is a snapshot, remove registration in base tree\r
+               /// </summary>\r
+               [Tested]\r
+               public void Dispose()\r
+               {\r
+                       Dispose(true);\r
+                       GC.SuppressFinalize(this);\r
+               }\r
+\r
+\r
+               private void Dispose(bool disposing)\r
+               {\r
+                       if (!disposed)\r
+                       {\r
+                               if (disposing) { }\r
+#if NCP\r
+                               if (isSnapShot)\r
+                               {\r
+                                       snapdata.Remove(generation, disposing);\r
+                                       snapdata = null;\r
+                                       root = null;\r
+                                       dirs = null;\r
+                                       path = null;\r
+                                       comparer = null;\r
+                                       disposed = true;\r
+                               }\r
+                               else { }\r
+#endif\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// If this tree is a snapshot, remove registration in base tree\r
+               /// </summary>\r
+               ~TreeSet()\r
+               {\r
+                       Dispose(false);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Make a (read-only) snap shot of this collection.\r
+               /// </summary>\r
+               /// <returns>The snap shot.</returns>\r
+               [Tested]\r
+               public ISorted<T> Snapshot()\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new InvalidOperationException("Cannot snapshot a snapshot");\r
+\r
+                       if (snapdata == null)\r
+                       {\r
+                               snapdata = new SnapData(this);\r
+                       }\r
+\r
+                       snapdata.Add(generation, this);\r
+\r
+                       TreeSet<T> res = (TreeSet<T>)MemberwiseClone();\r
+\r
+                       res.isReadOnly = true; res.isSnapShot = true;\r
+                       maxsnapid = generation++;\r
+                       return res;\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Snapdata nested class\r
+               //In a class by itself: the tree itself and snapshots must have a ref to \r
+               //the snapids, but we do not want snapshots to have a (strong) ref to the full\r
+               //updatable tree, which should be garbagecollectable even if there are still \r
+               //live snapshots!\r
+               //\r
+               //Access to SnapData should be thread safe since we expect finalisers \r
+               //of snapshots to remove a snapid that is garbagecollected without \r
+               //having been explicitly Disposed. Therefore we access SnapData through \r
+               //synchronized method/properties.\r
+\r
+#if NCP\r
+               class SnapData\r
+               {\r
+                       TreeSet<int> snapids = new TreeSet<int>(new IC());\r
+\r
+                       WeakReference master;\r
+\r
+\r
+                       internal SnapData(TreeSet<T> tree)\r
+                       {\r
+                               master = new WeakReference(tree);\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       public bool Add(int i, TreeSet<T> tree)\r
+                       {\r
+                               lock (this)\r
+                               {\r
+                                       bool res = snapids.Add(i);\r
+\r
+                                       //assert the following will be i:\r
+                                       tree.maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
+                                       return res;\r
+                               }\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       public bool Remove(int i, bool updmaxsnapid)\r
+                       {\r
+                               lock (this)\r
+                               {\r
+                                       bool res = snapids.Remove(i);\r
+\r
+                                       if (updmaxsnapid)\r
+                                       {\r
+                                               //Is this safe or/and overkill?\r
+                                               object t = master.Target;\r
+\r
+                                               if (t != null && master.IsAlive)\r
+                                               {\r
+                                                       ((TreeSet<T>)t).maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
+                                               }\r
+                                       }\r
+\r
+                                       return res;\r
+                               }\r
+                       }\r
+               }\r
+\r
+#endif\r
+               #endregion\r
+\r
+               #region TreeSet.Range nested class\r
+                       \r
+               internal class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
+               {\r
+                       //We actually need exclusive upper and lower bounds, and flags to \r
+                       //indicate whether the bound is present (we canot rely on default(T))\r
+                       private int stamp;\r
+\r
+                       private TreeSet<T> basis;\r
+\r
+                       private T lowend, highend;\r
+\r
+                       private bool haslowend, hashighend;\r
+\r
+                       EnumerationDirection direction;\r
+\r
+\r
+                       [Tested]\r
+                       public Range(TreeSet<T> basis, bool haslowend, T lowend, bool hashighend, T highend, EnumerationDirection direction)\r
+                       {\r
+                               this.basis = basis;\r
+                               stamp = basis.stamp;\r
+\r
+                               //lowind will be const; should we cache highind?\r
+                               this.lowend = lowend; //Inclusive\r
+                               this.highend = highend;//Exclusive\r
+                               this.haslowend = haslowend;\r
+                               this.hashighend = hashighend;\r
+                               this.direction = direction;\r
+                       }\r
+                       #region IEnumerable<T> Members\r
+\r
+\r
+                       #region TreeSet.Range.Enumerator nested class\r
+                       \r
+                       public class Enumerator: MSG.IEnumerator<T>\r
+                       {\r
+                               #region Private Fields\r
+                               private bool valid = false, ready = true;\r
+\r
+                               private IComparer<T> comparer;\r
+\r
+                               private T current;\r
+#if BAG\r
+                               int togo;\r
+#endif\r
+\r
+                               private Node cursor;\r
+\r
+                               private Node[] path; // stack of nodes\r
+\r
+                               private int level = 0;\r
+\r
+                               private Range range;\r
+\r
+                               private bool forwards;\r
+\r
+                               #endregion\r
+                               [Tested]\r
+                               public Enumerator(Range range)\r
+                               {\r
+                                       comparer = range.basis.comparer;\r
+                                       path = new Node[2 * range.basis.blackdepth];\r
+                                       this.range = range;\r
+                                       forwards = range.direction == EnumerationDirection.Forwards;\r
+                                       cursor = new Node();\r
+                                       if (forwards)\r
+                                               cursor.right = range.basis.root;\r
+                                       else\r
+                                               cursor.left = range.basis.root;\r
+                                       range.basis.modifycheck(range.stamp);\r
+                               }\r
+\r
+\r
+                               int compare(T i1, T i2) { return comparer.Compare(i1, i2); }\r
+\r
+\r
+                               /// <summary>\r
+                               /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
+                               /// </summary>\r
+                               /// <value>The current value of the enumerator.</value>\r
+                               [Tested]\r
+                               public T Current\r
+                               {\r
+                                       [Tested]\r
+                                       get\r
+                                       {\r
+                                               if (valid)\r
+                                                       return current;\r
+                                               else\r
+                                                       throw new InvalidOperationException();\r
+                                       }\r
+                               }\r
+\r
+\r
+                               //Maintain a stack of nodes that are roots of\r
+                               //subtrees not completely exported yet. Invariant:\r
+                               //The stack nodes together with their right subtrees\r
+                               //consists of exactly the items we have not passed\r
+                               //yet (the top of the stack holds current item).\r
+                               /// <summary>\r
+                               /// Move enumerator to next item in tree, or the first item if\r
+                               /// this is the first call to MoveNext. \r
+                               /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
+                               /// </summary>\r
+                               /// <returns>True if enumerator is valid now</returns>\r
+                               [Tested]\r
+                               public bool MoveNext()\r
+                               {\r
+                                       range.basis.modifycheck(range.stamp);\r
+                                       if (!ready)\r
+                                               return false;\r
+#if BAG\r
+                                       if (--togo> 0)\r
+                                               return true;\r
+#endif\r
+                                       if (forwards)\r
+                                       {\r
+                                               if (!valid && range.haslowend)\r
+                                               {\r
+                                                       cursor = cursor.right;\r
+                                                       while (cursor != null)\r
+                                                       {\r
+                                                               int comp = compare(cursor.item, range.lowend);\r
+\r
+                                                               if (comp > 0)\r
+                                                               {\r
+                                                                       path[level++] = cursor;\r
+#if NCP\r
+                                                                       cursor = range.basis.left(cursor);\r
+#else\r
+                                                                       cursor = cursor.left;\r
+#endif\r
+                                                               }\r
+                                                               else if (comp < 0)\r
+                                                               {\r
+#if NCP\r
+                                                                       cursor = range.basis.right(cursor);\r
+#else\r
+                                                                       cursor = cursor.right;\r
+#endif\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       path[level] = cursor;\r
+                                                                       break;\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       if (cursor == null)\r
+                                                       {\r
+                                                               if (level == 0)\r
+                                                                       return valid = ready = false;\r
+                                                               else\r
+                                                                       cursor = path[--level];\r
+                                                       }\r
+                                               }\r
+#if NCP\r
+                                               else if (range.basis.right(cursor) != null)\r
+                                               {\r
+                                                       path[level] = cursor = range.basis.right(cursor);\r
+\r
+                                                       Node next = range.basis.left(cursor);\r
+\r
+                                                       while (next != null)\r
+                                                       {\r
+                                                               path[++level] = cursor = next;\r
+                                                               next = range.basis.left(cursor);\r
+                                                       }\r
+                                               }\r
+#else\r
+                                               else if (cursor.right != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.right;\r
+                                                       while (cursor.left != null)\r
+                                                               path[++level] = cursor = cursor.left;\r
+                                               }\r
+#endif\r
+                                               else if (level == 0)\r
+                                                       return valid = ready = false;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+                                               if (range.hashighend && compare(current, range.highend) >= 0)\r
+                                                       return valid = ready = false;\r
+\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                               return valid = true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (!valid && range.hashighend)\r
+                                               {\r
+                                                       cursor = cursor.left;\r
+                                                       while (cursor != null)\r
+                                                       {\r
+                                                               int comp = compare(cursor.item, range.highend);\r
+\r
+                                                               if (comp < 0)\r
+                                                               {\r
+                                                                       path[level++] = cursor;\r
+#if NCP\r
+                                                                       cursor = range.basis.right(cursor);\r
+#else\r
+                                                                       cursor = cursor.right;\r
+#endif\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+#if NCP\r
+                                                                       cursor = range.basis.left(cursor);\r
+#else\r
+                                                                       cursor = cursor.left;\r
+#endif\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       if (cursor == null)\r
+                                                       {\r
+                                                               if (level == 0)\r
+                                                                       return valid = ready = false;\r
+                                                               else\r
+                                                                       cursor = path[--level];\r
+                                                       }\r
+                                               }\r
+#if NCP\r
+                                               else if (range.basis.left(cursor) != null)\r
+                                               {\r
+                                                       path[level] = cursor = range.basis.left(cursor);\r
+\r
+                                                       Node next = range.basis.right(cursor);\r
+\r
+                                                       while (next != null)\r
+                                                       {\r
+                                                               path[++level] = cursor = next;\r
+                                                               next = range.basis.right(cursor);\r
+                                                       }\r
+                                               }\r
+#else\r
+                                               else if (cursor.left != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.left;\r
+                                                       while (cursor.right != null)\r
+                                                               path[++level] = cursor = cursor.right;\r
+                                               }\r
+#endif\r
+                                               else if (level == 0)\r
+                                                       return valid = ready = false;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+                                               if (range.haslowend && compare(current, range.lowend) < 0)\r
+                                                       return valid = ready = false;\r
+\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                               return valid = true;\r
+                                       }\r
+                               }\r
+\r
+                               void SC.IEnumerator.Reset ()\r
+                               {\r
+                                       throw new NotImplementedException ();\r
+                               }\r
+\r
+                               object SC.IEnumerator.Current {\r
+                                       get {\r
+                                               return Current;\r
+                                       }\r
+                               }\r
+\r
+                               [Tested]\r
+                               public void Dispose()\r
+                               {\r
+                                       comparer = null;\r
+                                       current = default(T);\r
+                                       cursor = null;\r
+                                       path = null;\r
+                                       range = null;\r
+                               }\r
+                       }\r
+\r
+                       #endregion\r
+\r
+                       [Tested]\r
+                       public override MSG.IEnumerator<T> GetEnumerator() { return new Enumerator(this); }\r
+\r
+\r
+                       [Tested]\r
+                       public EnumerationDirection Direction { [Tested]get { return direction; } }\r
+\r
+\r
+                       #endregion\r
+\r
+                       #region Utility\r
+                       \r
+                       bool inside(T item)\r
+                       {\r
+                return (!haslowend || basis.comparer.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer.Compare(item, highend) < 0);\r
+            }\r
+\r
+\r
+                       void checkstamp()\r
+                       {\r
+                               if (stamp < basis.stamp)\r
+                                       throw new InvalidOperationException("Base collection was modified behind my back!");\r
+                       }\r
+\r
+\r
+                       void syncstamp() { stamp = basis.stamp; }\r
+                       \r
+                       #endregion\r
+\r
+                       [Tested]\r
+                       public IDirectedCollectionValue<T> Backwards()\r
+                       {\r
+                               Range b = (Range)MemberwiseClone();\r
+\r
+                               b.direction = direction == EnumerationDirection.Forwards ? EnumerationDirection.Backwards : EnumerationDirection.Forwards;\r
+                               return b;\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+\r
+                       [Tested]\r
+                       public override int Count\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       return haslowend ? (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : (hashighend ? basis.CountTo(highend) : basis.Count);\r
+                               }\r
+                       }\r
+\r
+            //TODO: check that this is correct\r
+            public override Speed CountSpeed { get { return Speed.Log; } }\r
+\r
+        }\r
+\r
+               #endregion\r
+\r
+               #region fixheight utility\r
+\r
+#if MAINTAIN_HEIGHT\r
+               public void fixheight(Node n)\r
+               {\r
+                       int lh = n.left == null ? 0 : n.left.height + 1;\r
+                       int rh = n.right == null ? 0 : n.right.height + 1;\r
+\r
+                       n.height = (short)(lh > rh ? lh : rh);\r
+               }\r
+#endif\r
+\r
+               #endregion\r
+\r
+               #region Diagnostics\r
+               /// <summary>\r
+               /// Display this node on the console, and recursively its subnodes.\r
+               /// </summary>\r
+               /// <param name="n">Node to display</param>\r
+               /// <param name="space">Indentation</param>\r
+               private void minidump(Node n, string space)\r
+               {\r
+                       if (n == null)\r
+                       {\r
+                               //      System.Console.WriteLine(space + "null");\r
+                       }\r
+                       else\r
+                       {\r
+                               minidump(n.right, space + "  ");\r
+                               Console.WriteLine(String.Format("{0} {4} (rank={5}, size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, \r
+#if MAINTAIN_SIZE\r
+                               n.size, \r
+#else\r
+                               0,\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               n.height, \r
+#else\r
+                               0,\r
+#endif\r
+#if NCP\r
+                               n.generation, \r
+#endif\r
+                               n.red ? "RED" : "BLACK", \r
+#if MAINTAIN_RANK\r
+                               n.rank, \r
+#else\r
+                               0,\r
+#endif\r
+#if TRACE_ID\r
+                                       n.id,\r
+#else\r
+                               0,\r
+#endif\r
+#if NCP\r
+#if SEPARATE_EXTRA\r
+                               n.extra == null ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.extra.lastgeneration, n.extra.leftnode ? "L" : "R", n.extra.oldref == null ? "()" : "" + n.extra.oldref.item),\r
+#else\r
+                               n.lastgeneration == -1 ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item),\r
+#endif\r
+#else\r
+                               "",\r
+#endif\r
+#if BAG\r
+                               n.items\r
+#else\r
+                               1\r
+#endif\r
+                               ));\r
+                               minidump(n.left, space + "  ");\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Print the tree structure to the console stdout.\r
+               /// </summary>\r
+               [Tested(via = "Sawtooth")]\r
+               public void dump() { dump(""); }\r
+\r
+\r
+               /// <summary>\r
+               /// Print the tree structure to the console stdout.\r
+               /// </summary>\r
+               [Tested(via = "Sawtooth")]\r
+               public void dump(string msg)\r
+               {\r
+                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
+#if MAINTAIN_HEIGHT\r
+                       depth\r
+#else\r
+                       0\r
+#endif\r
+                       , \r
+#if NCP\r
+                       generation\r
+#endif\r
+                       ));\r
+                       minidump(root, "");\r
+                       check("", Console.Out); Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Display this tree on the console.\r
+               /// </summary>\r
+               /// <param name="msg">Identifying string of this call to dump</param>\r
+               /// <param name="err">Extra (error)message to include</param>\r
+               void dump(string msg, string err)\r
+               {\r
+                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
+#if MAINTAIN_HEIGHT\r
+                       depth\r
+#else\r
+                       0\r
+#endif\r
+                       ,  \r
+#if NCP\r
+                       generation                              \r
+#endif\r
+                       ));\r
+                       minidump(root, ""); Console.Write(err);\r
+                       Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Print warning m on o if b is false.\r
+               /// </summary>\r
+               /// <param name="b">Condition that should hold</param>\r
+               /// <param name="n">Place (used for id display)</param>\r
+               /// <param name="m">Message</param>\r
+               /// <param name="o">Output stream</param>\r
+               /// <returns>b</returns>\r
+               bool massert(bool b, Node n, string m, System.IO.TextWriter o)\r
+               {\r
+                       if (!b) o.WriteLine("*** Node (item={0}, id={1}): {2}", n.item, \r
+#if TRACE_ID\r
+                               n.id\r
+#else\r
+                               0\r
+#endif\r
+                               , m);\r
+\r
+                       return b;\r
+               }\r
+\r
+\r
+               bool rbminicheck(Node n, bool redp, int prank, System.IO.TextWriter o, out T min, out T max, out int blackheight, int maxgen)\r
+               {//Red-Black invariant\r
+                       bool res = true;\r
+\r
+                       res = massert(!(n.red && redp), n, "RED parent of RED node", o) && res;\r
+                       res = massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty", o) && res;\r
+                       res = massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty", o) && res;\r
+#if MAINTAIN_RANK\r
+                       res = massert(n.red == (n.rank == prank), n, "Bad color", o) && res;\r
+                       res = massert(prank <= n.rank + 1, n, "Parentrank-rank >= 2", o) && res;\r
+                       res = massert((n.left != null && n.right != null) || n.rank == 1, n, "Rank>1 but empty child", o) && res;\r
+#endif\r
+#if BAG\r
+                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
+\r
+                       res = massert(sb, n, "Bad size", o) && res;\r
+#elif MAINTAIN_SIZE\r
+                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
+\r
+                       res = massert(sb, n, "Bad size", o) && res;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                       int lh = n.left == null ? 0 : n.left.height + 1;\r
+                       int rh = n.right == null ? 0 : n.right.height + 1;\r
+\r
+                       res = massert(n.height == (lh < rh ? rh : lh), n, "Bad height", o) && res;\r
+#endif\r
+                       int therank =\r
+#if MAINTAIN_RANK\r
+                       n.rank;\r
+#else\r
+                       0;\r
+#endif\r
+                       min = max = n.item;\r
+\r
+                       T otherext;\r
+                       int lbh = 0, rbh = 0;\r
+\r
+                       if (n.left != null)\r
+                       {\r
+                               res = rbminicheck(n.left, n.red, therank, o, out min, out otherext, out lbh, generation) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
+            }\r
+\r
+                       if (n.right != null)\r
+                       {\r
+                               res = rbminicheck(n.right, n.red, therank, o, out otherext, out max, out rbh, generation) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
+            }\r
+\r
+                       res = massert(rbh == lbh, n, "Different blackheights of children", o) && res;\r
+                       blackheight = n.red ? rbh : rbh + 1;\r
+#if MAINTAIN_RANK\r
+                       //The rank is the number of black nodes from this one to\r
+                       //the leaves, not counting this one, but counting 1 for the empty\r
+                       //virtual leaf nodes.\r
+                       res = massert(n.rank == rbh + 1, n, "rank!=blackheight " + blackheight, o) && res;\r
+#endif\r
+                       return res;\r
+               }\r
+\r
+\r
+\r
+\r
+#if NCP\r
+\r
+               bool rbminisnapcheck(Node n, System.IO.TextWriter o, out int size, out T min, out T max)\r
+               {\r
+                       bool res = true;\r
+\r
+                       min = max = n.item;\r
+\r
+                       int lsz = 0, rsz = 0;\r
+                       T otherext;\r
+#if SEPARATE_EXTRA\r
+                       Node.Extra extra = n.extra;\r
+                       Node child = (extra != null && extra.lastgeneration >= treegen && extra.leftnode) ? extra.oldref : n.left;\r
+#else\r
+                       Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left;\r
+#endif\r
+                       if (child != null)\r
+                       {\r
+                               res = rbminisnapcheck(child, o, out lsz, out min, out otherext) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
+            }\r
+\r
+#if SEPARATE_EXTRA\r
+                       child = (extra != null && extra.lastgeneration >= treegen && !extra.leftnode) ? extra.oldref : n.right;\r
+#else\r
+                       child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right;\r
+#endif\r
+                       if (child != null)\r
+                       {\r
+                               res = rbminisnapcheck(child, o, out rsz, out otherext, out max) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
+            }\r
+#if BAG\r
+                       size = n.items + lsz + rsz;\r
+#else\r
+                       size = 1 + lsz + rsz;\r
+#endif\r
+                       return res;\r
+               }\r
+#endif\r
+\r
+               /// <summary>\r
+               /// Checks red-black invariant. Dumps tree to console if bad\r
+               /// </summary>\r
+               /// <param name="name">Title of dump</param>\r
+               /// <returns>false if invariant violation</returns>\r
+               [Tested(via = "Sawtooth")]\r
+               public bool Check(string name)\r
+               {\r
+                       System.Text.StringBuilder e = new System.Text.StringBuilder();\r
+                       System.IO.TextWriter o = new System.IO.StringWriter(e);\r
+\r
+                       if (!check(name, o))\r
+                               return true;\r
+                       else\r
+                       {\r
+                               dump(name, e.ToString());\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Checks red-black invariant. Dumps tree to console if bad\r
+               /// </summary>\r
+               /// <returns>false if invariant violation</returns>\r
+               [Tested]\r
+               public bool Check()\r
+               {\r
+                       //return check("", System.IO.TextWriter.Null);\r
+                       //Console.WriteLine("bamse");\r
+                       return Check("-");\r
+               }\r
+\r
+\r
+               bool check(string msg, System.IO.TextWriter o)\r
+               {\r
+                       if (root != null)\r
+                       {\r
+                               T max, min;\r
+                               int blackheight;\r
+#if NCP\r
+                               if (isSnapShot)\r
+                               {\r
+                                       //Console.WriteLine("Im'a snapshot");\r
+                                       int thesize;\r
+                                       bool rv = rbminisnapcheck(root, o, out thesize, out min, out max);\r
+\r
+                                       rv = massert(size == thesize, root, "bad snapshot size", o) && rv;\r
+                                       return !rv;\r
+                               }\r
+#endif\r
+#if MAINTAIN_RANK\r
+                               bool res = rbminicheck(root, false, root.rank + 1, o, out min, out max, out blackheight, generation);\r
+\r
+                               res = massert(root.rank == blackdepth, root, "blackdepth!=root.rank", o) && res;\r
+#else\r
+                               bool res = rbminicheck(root, false, 0, o, out min, out max, out blackheight, generation);\r
+#endif\r
+                               res = massert(blackheight == blackdepth, root, "bad blackh/d", o) && res;\r
+                               res = massert(!root.red, root, "root is red", o) && res;\r
+#if MAINTAIN_SIZE\r
+                               res = massert(root.size == size, root, "count!=root.size", o) && res;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               res = massert(root.height == depth, root, "depth!=root.height", o) && res;\r
+#endif\r
+                               return !res;\r
+                       }\r
+                       else\r
+                               return false;\r
+               }\r
+               #endregion                      \r
+       }\r
+}\r
+\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/trees/RedBlackTreeBag.cs b/mcs/class/Mono.C5/C5/trees/RedBlackTreeBag.cs
new file mode 100644 (file)
index 0000000..21050b9
--- /dev/null
@@ -0,0 +1,4329 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+#define MAINTAIN_SIZE\r
+#define MAINTAIN_RANKnot\r
+#define MAINTAIN_HEIGHTnot\r
+#define BAG\r
+#define NCP\r
+\r
+#define MAINTAIN_EXTREMAnot\r
+#define TRACE_IDnot\r
+\r
+#if BAG\r
+#if !MAINTAIN_SIZE\r
+#error  BAG defined without MAINTAIN_SIZE!\r
+#endif\r
+#endif\r
+\r
+\r
+using System;\r
+using MSG = System.Collections.Generic;\r
+using SC = System.Collections;\r
+\r
+// NOTE NOTE NOTE NOTE\r
+// This source file is used to produce both TreeBag<T> and TreeBag<T>\r
+// It should be copied to a file called TreeBag.cs in which all code mentions of \r
+// TreeBag is changed to TreeBag and the preprocessor symbol BAG is defined.\r
+// NOTE: there may be problems with documentation comments.\r
+\r
+namespace C5\r
+{\r
+#if BAG\r
+       /// <summary>\r
+       /// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics,\r
+       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. (<see cref="T:C5.TreeBag!1"/> for an \r
+       /// implementation with set semantics).\r
+       /// <br/>\r
+       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
+       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
+       /// be external and supplied by the user in the constructor.\r
+       /// <br/>\r
+       /// Each distinct item is only kept in one place in the tree - together with the number\r
+       /// of times it is a member of the bag. Thus, if two items that are equal according\r
+       /// </summary>\r
+#else\r
+       /// <summary>\r
+       /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics,\r
+       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. <see cref="T:C5.TreeBag!1"/> for a version \r
+       /// with bag semantics. <see cref="T:C5.TreeDictionary!2"/> for a sorted dictionary \r
+       /// based on this tree implementation.\r
+       /// <p>\r
+       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
+       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
+       /// be external and supplied by the user in the constructor.</p>\r
+       ///\r
+       /// <p><i>TODO: describe performance here</i></p>\r
+       /// <p><i>TODO: discuss persistence and its useful usage modes. Warn about the space\r
+       /// leak possible with other usage modes.</i></p>\r
+       /// </summary>\r
+#endif\r
+       public class TreeBag<T>: SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>\r
+       {\r
+               #region Feature\r
+               /// <summary>\r
+               /// A debugging aid for making the selected compilation alternatives \r
+               /// available to the user. (To be removed when selection is finally fixed\r
+               /// for production version).\r
+               /// </summary>\r
+               [Flags]\r
+               public enum Feature: short\r
+               {\r
+                       /// <summary>\r
+                       /// Nothing\r
+                       /// </summary>\r
+                       Dummy = 0,\r
+                       /// <summary>\r
+                       /// Node copy persistence as explained in <a href="litterature.htm#Tarjan1">Tarjan1</a>\r
+                       /// </summary>\r
+                       NodeCopyPersistence = 2,\r
+                       /// <summary>\r
+                       /// Maintain sub tree sizes\r
+                       /// </summary>\r
+                       Sizes = 4,\r
+                       /// <summary>\r
+                       /// Maintain precise node heights\r
+                       /// </summary>\r
+                       Heights = 8,\r
+                       /// <summary>\r
+                       /// Maintain node ranks (~ black height)\r
+                       /// </summary>\r
+                       Ranks = 16,\r
+                       /// <summary>\r
+                       /// Maintain unique ids on tree nodes.\r
+                       /// </summary>\r
+                       Traceid = 32\r
+               }\r
+\r
+\r
+\r
+               static Feature features = Feature.Dummy\r
+#if NCP\r
+               | Feature.NodeCopyPersistence\r
+#endif\r
+#if MAINTAIN_RANK\r
+                       |Feature.Ranks\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                       |Feature.Heights\r
+#endif\r
+#if MAINTAIN_SIZE\r
+               | Feature.Sizes\r
+#endif\r
+#if TRACE_ID\r
+               | Feature.Traceid\r
+#endif\r
+               ;\r
+\r
+\r
+               /// <summary>\r
+               /// A debugging aid for making the selected compilation alternatives \r
+               /// available to the user. (To be removed when selection is finally fixed\r
+               /// for production version).\r
+               /// </summary>\r
+               public static Feature Features { get { return features; } }\r
+\r
+               #endregion\r
+\r
+               #region Fields\r
+\r
+               IComparer<T> comparer;\r
+\r
+               Node root;\r
+\r
+               int blackdepth = 0;\r
+\r
+               //We double these stacks for the iterative add and remove on demand\r
+               private int[] dirs = new int[2];\r
+\r
+               private Node[] path = new Node[2];\r
+#if NCP\r
+               private bool isSnapShot = false;\r
+\r
+               private SnapData snapdata;\r
+\r
+               private int generation;\r
+\r
+               private int maxsnapid = -1;\r
+\r
+#endif\r
+#if MAINTAIN_EXTREMA\r
+               T min, max;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+               private short depth = 0;\r
+#endif\r
+               #endregion\r
+\r
+               #region Util\r
+\r
+               /// <summary>\r
+               /// Fetch the left child of n taking node-copying persistence into\r
+               /// account if relevant. \r
+               /// </summary>\r
+               /// <param name="n"></param>\r
+               /// <returns></returns>\r
+               private Node left(Node n)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                       {\r
+#if SEPARATE_EXTRA\r
+                               Node.Extra e = n.extra;\r
+\r
+                               if (e != null && e.lastgeneration >= treegen && e.leftnode)\r
+                                       return e.oldref;\r
+#else\r
+                               if (n.lastgeneration >= generation && n.leftnode)\r
+                                       return n.oldref;\r
+#endif\r
+                       }\r
+#endif\r
+                       return n.left;\r
+               }\r
+\r
+\r
+               private Node right(Node n)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                       {\r
+#if SEPARATE_EXTRA\r
+                               Node.Extra e = n.extra;\r
+\r
+                               if (e != null && e.lastgeneration >= treegen && !e.leftnode)\r
+                                       return e.oldref;\r
+#else\r
+                               if (n.lastgeneration >= generation && !n.leftnode)\r
+                                       return n.oldref;\r
+#endif\r
+                       }\r
+#endif\r
+                       return n.right;\r
+               }\r
+\r
+\r
+               //This method should be called by methods that use the internal \r
+               //traversal stack, unless certain that there is room enough\r
+               private void stackcheck()\r
+               {\r
+                       while (dirs.Length < 2 * blackdepth)\r
+                       {\r
+                               dirs = new int[2 * dirs.Length];\r
+                               path = new Node[2 * dirs.Length];\r
+                       }\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Node nested class\r
+                       \r
+\r
+               /// <summary>\r
+               /// The type of node in a Red-Black binary tree\r
+               /// </summary>\r
+               class Node\r
+               {\r
+                       public bool red = true;\r
+\r
+                       public T item;\r
+\r
+                       public Node left;\r
+\r
+                       public Node right;\r
+\r
+#if MAINTAIN_SIZE\r
+                       public int size = 1;\r
+#endif\r
+\r
+#if BAG\r
+                       public int items = 1;\r
+#endif\r
+\r
+#if MAINTAIN_HEIGHT\r
+                       public short height; \r
+#endif\r
+\r
+#if MAINTAIN_RANK\r
+                       public short rank = 1;\r
+#endif\r
+\r
+#if TRACE_ID\r
+                       public int id = sid++;\r
+                       public static int sid = 0;\r
+#endif\r
+\r
+#if NCP\r
+                       public int generation;\r
+#if SEPARATE_EXTRA\r
+                       internal class Extra\r
+                       {\r
+                               public int lastgeneration;\r
+\r
+                               public Node oldref;\r
+\r
+                               public bool leftnode;\r
+\r
+                               //public Node next;\r
+                       }\r
+\r
+                       public Extra extra;\r
+\r
+#else\r
+                       public int lastgeneration = -1;\r
+\r
+                       public Node oldref;\r
+\r
+                       public bool leftnode;\r
+#endif\r
+\r
+                       /// <summary>\r
+                       /// Update a child pointer\r
+                       /// </summary>\r
+                       /// <param name="cursor"></param>\r
+                       /// <param name="leftnode"></param>\r
+                       /// <param name="child"></param>\r
+                       /// <param name="maxsnapid"></param>\r
+                       /// <param name="generation"></param>\r
+                       /// <returns>True if node was *copied*</returns>\r
+                       internal static bool update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation)\r
+                       {\r
+                               Node oldref = leftnode ? cursor.left : cursor.right;\r
+\r
+                               if (child == oldref)\r
+                                       return false;\r
+\r
+                               bool retval = false;\r
+\r
+                               if (cursor.generation <= maxsnapid)\r
+                               { \r
+#if SEPARATE_EXTRA\r
+                                       if (cursor.extra == null)\r
+                                       {\r
+                                               Extra extra = cursor.extra = new Extra();       \r
+\r
+                                               extra.leftnode = leftnode;\r
+                                               extra.lastgeneration = maxsnapid;\r
+                                               extra.oldref = oldref;\r
+                                       }\r
+                                       else if (cursor.extra.leftnode != leftnode || cursor.extra.lastgeneration < maxsnapid)\r
+#else\r
+                                       if (cursor.lastgeneration == -1)\r
+                                       {\r
+                                               cursor.leftnode = leftnode;\r
+                                               cursor.lastgeneration = maxsnapid;\r
+                                               cursor.oldref = oldref;\r
+                                       }\r
+                                       else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid)\r
+#endif\r
+                                       {\r
+                                               CopyNode(ref cursor, maxsnapid, generation);\r
+                                               retval = true;\r
+                                       }\r
+                               }\r
+\r
+                               if (leftnode)\r
+                                       cursor.left = child;\r
+                               else\r
+                                       cursor.right = child;\r
+\r
+                               return retval;\r
+                       }\r
+\r
+\r
+                       //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will \r
+                       //always be used in the old copy of cursor. Therefore, after \r
+                       //making the clone, we should update the old copy by restoring\r
+                       //the child pointer and setting extra to null.\r
+                       //OTOH then we cannot clean up unused Extra objects unless we link\r
+                       //them together in a doubly linked list.\r
+                       public static bool CopyNode(ref Node cursor, int maxsnapid, int generation)\r
+                       {\r
+                               if (cursor.generation <= maxsnapid)\r
+                               {\r
+                                       cursor = (Node)(cursor.MemberwiseClone());\r
+                                       cursor.generation = generation;\r
+#if SEPARATE_EXTRA\r
+                                       cursor.extra = null;\r
+#else\r
+                                       cursor.lastgeneration = -1;\r
+#endif\r
+#if TRACE_ID\r
+                                       cursor.id = sid++;\r
+#endif\r
+                                       return true;\r
+                               }\r
+                               else\r
+                                       return false;\r
+                       }\r
+\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+                       \r
+               /// <summary>\r
+               /// Create a red-black tree collection with natural comparer and item hasher.\r
+               /// </summary>\r
+               public TreeBag()\r
+               {\r
+                       comparer = ComparerBuilder.FromComparable<T>.Examine();\r
+                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a red-black tree collection with an external comparer (and natural item hasher,\r
+               /// assumed consistent).\r
+               /// </summary>\r
+               /// <param name="c">The external comparer</param>\r
+               public TreeBag(IComparer<T> c)\r
+               {\r
+                       comparer = c;\r
+                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a red-black tree collection with an external comparer aand an external\r
+               /// item hasher, assumed consistent.\r
+               /// </summary>\r
+               /// <param name="c">The external comparer</param>\r
+               /// <param name="h">The external item hasher</param>\r
+               public TreeBag(IComparer<T> c, IHasher<T> h)\r
+               {\r
+                       comparer = c;\r
+                       itemhasher = h;\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region TreeBag.Enumerator nested class\r
+\r
+               /// <summary>\r
+               /// An enumerator for a red-black tree collection. Based on an explicit stack\r
+               /// of subtrees waiting to be enumerated. Currently only used for the tree set \r
+               /// enumerators (tree bag enumerators use an iterator block based enumerator).\r
+               /// </summary>\r
+               public class Enumerator: MSG.IEnumerator<T>\r
+               {\r
+                       #region Private Fields\r
+                       TreeBag<T> tree;\r
+\r
+                       bool valid = false;\r
+\r
+                       int stamp;\r
+\r
+                       T current;\r
+\r
+                       Node cursor;\r
+\r
+                       Node[] path; // stack of nodes\r
+\r
+                       int level = 0;\r
+                       #endregion\r
+                       /// <summary>\r
+                       /// Create a tree enumerator\r
+                       /// </summary>\r
+                       /// <param name="tree">The red-black tree to enumerate</param>\r
+                       public Enumerator(TreeBag<T> tree)\r
+                       {\r
+                               this.tree = tree;\r
+                               stamp = tree.stamp;\r
+                               path = new Node[2 * tree.blackdepth];\r
+                               cursor = new Node();\r
+                               cursor.right = tree.root;\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
+                       /// </summary>\r
+                       /// <value>The current item of the enumerator.</value>\r
+                       [Tested]\r
+                       public T Current\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       if (valid)\r
+                                               return current;\r
+                                       else\r
+                                               throw new InvalidOperationException();\r
+                               }\r
+                       }\r
+\r
+\r
+                       //Maintain a stack of nodes that are roots of\r
+                       //subtrees not completely exported yet. Invariant:\r
+                       //The stack nodes together with their right subtrees\r
+                       //consists of exactly the items we have not passed\r
+                       //yet (the top of the stack holds current item).\r
+                       /// <summary>\r
+                       /// Move enumerator to next item in tree, or the first item if\r
+                       /// this is the first call to MoveNext. \r
+                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
+                       /// </summary>\r
+                       /// <returns>True if enumerator is valid now</returns>\r
+                       [Tested]\r
+                       public bool MoveNext()\r
+                       {\r
+                               tree.modifycheck(stamp);\r
+                               if (cursor.right != null)\r
+                               {\r
+                                       path[level] = cursor = cursor.right;\r
+                                       while (cursor.left != null)\r
+                                               path[++level] = cursor = cursor.left;\r
+                               }\r
+                               else if (level == 0)\r
+                                       return valid = false;\r
+                               else\r
+                                       cursor = path[--level];\r
+\r
+                               current = cursor.item;\r
+                               return valid = true;\r
+                       }\r
+\r
+                       void SC.IEnumerator.Reset ()\r
+                       {\r
+                               throw new NotImplementedException ();\r
+                       }\r
+\r
+                       object SC.IEnumerator.Current {\r
+                               get {\r
+                                       return Current;\r
+                               }\r
+                       }\r
+\r
+                       #region IDisposable Members for Enumerator\r
+\r
+                       bool disposed;\r
+\r
+\r
+                       /// <summary>\r
+                       /// Call Dispose(true) and then suppress finalization of this enumerator.\r
+                       /// </summary>\r
+                       [Tested]\r
+                       public void Dispose()\r
+                       {\r
+                               Dispose(true);\r
+                               GC.SuppressFinalize(this);\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Remove the internal data (notably the stack array).\r
+                       /// </summary>\r
+                       /// <param name="disposing">True if called from Dispose(),\r
+                       /// false if called from the finalizer</param>\r
+                       protected virtual void Dispose(bool disposing)\r
+                       {\r
+                               if (!disposed)\r
+                               {\r
+                                       if (disposing)\r
+                                       {\r
+                                       }\r
+\r
+                                       current = default(T);\r
+                                       cursor = null;\r
+                                       path = null;\r
+                                       disposed = true;\r
+                               }\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Finalizer for enumeratir\r
+                       /// </summary>\r
+                       ~Enumerator()\r
+                       {\r
+                               Dispose(false);\r
+                       }\r
+                       #endregion\r
+\r
+               }\r
+#if NCP\r
+               /// <summary>\r
+               /// An enumerator for a snapshot of a node copy persistent red-black tree\r
+               /// collection.\r
+               /// </summary>\r
+               public class SnapEnumerator: MSG.IEnumerator<T>\r
+               {\r
+                       #region Private Fields\r
+                       TreeBag<T> tree;\r
+\r
+                       bool valid = false;\r
+\r
+                       int stamp;\r
+#if BAG\r
+                       int togo;\r
+#endif\r
+\r
+                       T current;\r
+\r
+                       Node cursor;\r
+\r
+                       Node[] path; // stack of nodes\r
+\r
+                       int level;\r
+                       #endregion\r
+\r
+                       /// <summary>\r
+                       /// Creta an enumerator for a snapshot of a node copy persistent red-black tree\r
+                       /// collection\r
+                       /// </summary>\r
+                       /// <param name="tree">The snapshot</param>\r
+                       public SnapEnumerator(TreeBag<T> tree)\r
+                       {\r
+                               this.tree = tree;\r
+                               stamp = tree.stamp;\r
+                               path = new Node[2 * tree.blackdepth];\r
+                               cursor = new Node();\r
+                               cursor.right = tree.root;\r
+                       }\r
+\r
+\r
+                       #region MSG.IEnumerator<T> Members\r
+\r
+                       /// <summary>\r
+                       /// Move enumerator to next item in tree, or the first item if\r
+                       /// this is the first call to MoveNext. \r
+                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
+                       /// </summary>\r
+                       /// <returns>True if enumerator is valid now</returns>\r
+                       [Tested]\r
+                       public bool MoveNext()\r
+                       {\r
+                               tree.modifycheck(stamp);//???\r
+\r
+#if BAG\r
+                               if (--togo>0)\r
+                                       return true;\r
+#endif\r
+                               Node next = tree.right(cursor);\r
+\r
+                               if (next != null)\r
+                               {\r
+                                       path[level] = cursor = next;\r
+                                       next = tree.left(cursor);\r
+                                       while (next != null)\r
+                                       {\r
+                                               path[++level] = cursor = next;\r
+                                               next = tree.left(cursor);\r
+                                       }\r
+                               }\r
+                               else if (level == 0)\r
+                                       return valid = false;\r
+                               else\r
+                                       cursor = path[--level];\r
+\r
+#if BAG\r
+                               togo = cursor.items;\r
+#endif\r
+                               current = cursor.item;\r
+                               return valid = true;\r
+                       }\r
+\r
+\r
+                       /// <summary>\r
+                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
+                       /// </summary>\r
+                       /// <value>The current value of the enumerator.</value>\r
+                       [Tested]\r
+                       public T Current\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       if (valid)\r
+                                               return current;\r
+                                       else\r
+                                               throw new InvalidOperationException();\r
+                               }\r
+                       }\r
+\r
+                       #endregion\r
+\r
+                       void SC.IEnumerator.Reset ()\r
+                       {\r
+                               throw new NotImplementedException ();\r
+                       }\r
+\r
+                       object SC.IEnumerator.Current {\r
+                               get {\r
+                                       return Current;\r
+                               }\r
+                       }\r
+\r
+                       #region IDisposable Members\r
+\r
+                       [Tested]\r
+                       void System.IDisposable.Dispose()\r
+                       {\r
+                               tree = null;\r
+                               valid = false;\r
+                               current = default(T);\r
+                               cursor = null;\r
+                               path = null;\r
+                       }\r
+\r
+                       #endregion\r
+               }\r
+#endif\r
+               #endregion\r
+\r
+               #region IEnumerable<T> Members\r
+\r
+               private MSG.IEnumerator<T> getEnumerator(Node node, int origstamp)\r
+               {\r
+                       if (node == null)\r
+                               yield break;\r
+\r
+                       if (node.left != null)\r
+                       {\r
+                               MSG.IEnumerator<T> child = getEnumerator(node.left, origstamp);\r
+\r
+                               while (child.MoveNext())\r
+                               {\r
+                                       modifycheck(origstamp);\r
+                                       yield return child.Current;\r
+                               }\r
+                       }\r
+#if BAG\r
+                       int togo = node.items;\r
+                       while (togo-- > 0)\r
+                       {\r
+                               modifycheck(origstamp);\r
+                               yield return node.item;\r
+                       }\r
+#else\r
+                       modifycheck(origstamp);\r
+                       yield return node.item;\r
+#endif\r
+                       if (node.right != null)\r
+                       {\r
+                               MSG.IEnumerator<T> child = getEnumerator(node.right, origstamp);\r
+\r
+                               while (child.MoveNext())\r
+                               {\r
+                                       modifycheck(origstamp);\r
+                                       yield return child.Current;\r
+                               }\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create an enumerator for this tree\r
+               /// </summary>\r
+               /// <returns>The enumerator</returns>\r
+               [Tested]\r
+               public override MSG.IEnumerator<T> GetEnumerator()\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               return new SnapEnumerator(this);\r
+#endif\r
+#if BAG\r
+                       return getEnumerator(root,stamp);\r
+#else\r
+                       return new Enumerator(this);\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISink<T> Members\r
+                       \r
+               /// <summary>\r
+               /// Add item to tree. If already there, return the found item in the second argument.\r
+               /// </summary>\r
+               /// <param name="item">Item to add</param>\r
+        /// <param name="founditem">item found</param>\r
+        /// <param name="update">whether item in node should be updated</param>\r
+        /// <param name="wasfound">true if found in bag, false if not found or tre is a set</param>\r
+        /// <returns>True if item was added</returns>\r
+        bool addIterative(T item, ref T founditem, bool update, out bool wasfound)\r
+        {\r
+            wasfound = false;\r
+            if (root == null)\r
+                       {\r
+                               root = new Node();\r
+                               root.red = false;\r
+                               blackdepth = 1;\r
+#if MAINTAIN_EXTREMA\r
+                               root.item = min = max = item;\r
+#else\r
+                               root.item = item;\r
+#endif\r
+#if NCP\r
+                               root.generation = generation;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = 0;\r
+#endif\r
+                               return true;\r
+                       }\r
+\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (true)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp == 0)\r
+                               {\r
+                    founditem = cursor.item;\r
+\r
+#if BAG\r
+                    wasfound = true;\r
+#if NCP\r
+                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                                       cursor.items++;\r
+                                       cursor.size++;\r
+                                       if (update)\r
+                                               cursor.item = item;\r
+\r
+                                       update = true;\r
+\r
+#else\r
+                    if (update)\r
+                    {\r
+#if NCP\r
+                        Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                        cursor.item = item;\r
+                    }\r
+#endif\r
+\r
+                    while (level-- > 0)\r
+                    {\r
+                        if (update)\r
+                                               {\r
+                                                       Node kid = cursor;\r
+\r
+                                                       cursor = path[level];\r
+#if NCP\r
+                                                       Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
+#endif\r
+#if BAG\r
+                                                       cursor.size++;\r
+#endif\r
+                                               }\r
+\r
+                                               path[level] = null;\r
+                                       }\r
+#if BAG\r
+                                       return true;\r
+#else\r
+                                       if (update)\r
+                                               root = cursor;\r
+\r
+                                       return false;\r
+#endif\r
+                               }\r
+\r
+                               //else\r
+                               Node child = comp > 0 ? cursor.left : cursor.right;\r
+\r
+                               if (child == null)\r
+                               {\r
+                                       child = new Node();\r
+                                       child.item = item;\r
+#if NCP\r
+                                       child.generation = generation;\r
+                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
+#else\r
+                                       if (comp > 0) { cursor.left = child; }\r
+                                       else { cursor.right = child; }\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                                       cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                                       dirs[level] = comp;\r
+                                       break;\r
+                               }\r
+                               else\r
+                               {\r
+                                       dirs[level] = comp;\r
+                                       path[level++] = cursor;\r
+                                       cursor = child;\r
+                               }\r
+                       }\r
+\r
+                       //We have just added the red node child to "cursor"\r
+                       while (cursor.red)\r
+                       {\r
+                               //take one step up:\r
+                               Node child = cursor;\r
+\r
+                               cursor = path[--level];\r
+                               path[level] = null;\r
+#if NCP\r
+                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                               cursor.size++;\r
+#endif\r
+                               int comp = dirs[level];\r
+                               Node childsibling = comp > 0 ? cursor.right : cursor.left;\r
+\r
+                               if (childsibling != null && childsibling.red)\r
+                               {\r
+                                       //Promote\r
+#if MAINTAIN_RANK\r
+                                       cursor.rank++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                                       child.red = false;\r
+#if NCP\r
+                                       Node.update(ref cursor, comp < 0, childsibling, maxsnapid, generation);\r
+#endif\r
+                                       childsibling.red = false;\r
+\r
+                                       //color cursor red & take one step up the tree unless at root\r
+                                       if (level == 0)\r
+                                       {\r
+                                               root = cursor;\r
+                                               blackdepth++;\r
+                                               return true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               cursor.red = true;\r
+#if NCP\r
+                                               child = cursor;\r
+                                               cursor = path[--level];\r
+                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+                                               path[level] = null;\r
+#if MAINTAIN_SIZE\r
+                                               cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       //ROTATE!!!\r
+                                       int childcomp = dirs[level + 1];\r
+\r
+                                       cursor.red = true;\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               if (childcomp > 0)\r
+                                               {//zagzag\r
+#if NCP\r
+                                                       Node.update(ref cursor, true, child.right, maxsnapid, generation);\r
+                                                       Node.update(ref child, false, cursor, maxsnapid, generation);\r
+#else\r
+                                                       cursor.left = child.right;\r
+                                                       child.right = cursor;\r
+#endif\r
+                                                       cursor = child;\r
+                                               }\r
+                                               else\r
+                                               {//zagzig\r
+                                                       Node badgrandchild = child.right;\r
+#if NCP\r
+                                                       Node.update(ref cursor, true, badgrandchild.right, maxsnapid, generation);\r
+                                                       Node.update(ref child, false, badgrandchild.left, maxsnapid, generation);\r
+                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
+#else\r
+                                                       cursor.left = badgrandchild.right;\r
+                                                       child.right = badgrandchild.left;\r
+#endif\r
+                                                       badgrandchild.left = child;\r
+                                                       badgrandchild.right = cursor;\r
+                                                       cursor = badgrandchild;\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {//comp < 0\r
+                                               if (childcomp < 0)\r
+                                               {//zigzig\r
+#if NCP\r
+                                                       Node.update(ref cursor, false, child.left, maxsnapid, generation);\r
+                                                       Node.update(ref child, true, cursor, maxsnapid, generation);\r
+#else\r
+                                                       cursor.right = child.left;\r
+                                                       child.left = cursor;\r
+#endif\r
+                                                       cursor = child;\r
+                                               }\r
+                                               else\r
+                                               {//zigzag\r
+                                                       Node badgrandchild = child.left;\r
+#if NCP\r
+                                                       Node.update(ref cursor, false, badgrandchild.left, maxsnapid, generation);\r
+                                                       Node.update(ref child, true, badgrandchild.right, maxsnapid, generation);\r
+                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
+#else\r
+                                                       cursor.right = badgrandchild.left;\r
+                                                       child.left = badgrandchild.right;\r
+#endif\r
+                                                       badgrandchild.right = child;\r
+                                                       badgrandchild.left = cursor;\r
+                                                       cursor = badgrandchild;\r
+                                               }\r
+                                       }\r
+\r
+                                       cursor.red = false;\r
+\r
+#if MAINTAIN_SIZE\r
+                                       Node n;\r
+\r
+#if BAG\r
+                                       n = cursor.right;\r
+                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
+                                       n = cursor.left;\r
+                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
+                                       cursor.size += n.size + cursor.items;\r
+#else\r
+                                       n = cursor.right;\r
+                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
+                                       n = cursor.left;\r
+                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
+                                       cursor.size += n.size + 1;\r
+#endif\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor.right);\r
+                                       fixheight(cursor.left);\r
+                                       fixheight(cursor);\r
+#endif\r
+                                       if (level == 0)\r
+                                       {\r
+                                               root = cursor;\r
+                                               return true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               child = cursor;\r
+                                               cursor = path[--level];\r
+                                               path[level] = null;\r
+#if NCP\r
+                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#else\r
+                                               if (dirs[level] > 0)\r
+                                                       cursor.left = child;\r
+                                               else\r
+                                                       cursor.right = child;\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                                               cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(cursor);\r
+#endif\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+#if NCP\r
+                       bool stillmore = true;\r
+#endif\r
+                       while (level > 0)\r
+                       {\r
+                               Node child = cursor;\r
+\r
+                               cursor = path[--level];\r
+                               path[level] = null;\r
+#if NCP\r
+                               if (stillmore)\r
+                                       stillmore = Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                               cursor.size++;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               fixheight(cursor);\r
+#endif\r
+                       }\r
+\r
+                       root = cursor;\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add an item to this collection if possible. If this collection has set\r
+               /// semantics, the item will be added if not already in the collection. If\r
+               /// bag semantics, the item will always be added.\r
+               /// </summary>\r
+               /// <param name="item">The item to add.</param>\r
+               /// <returns>True if item was added.</returns>\r
+               [Tested]\r
+               public bool Add(T item)\r
+               {\r
+                       updatecheck();\r
+\r
+                       //Note: blackdepth of the tree is set inside addIterative\r
+                       T j = default(T);\r
+            bool tmp;\r
+\r
+            if (addIterative(item, ref j, false, out tmp))\r
+                       {\r
+                               size++;\r
+#if MAINTAIN_EXTREMA\r
+                               if (Compare(item, min) < 0)\r
+                                       min = item;\r
+                               else if (Compare(item, max) > 0)\r
+                                       max = item;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = root.height;\r
+#endif\r
+                               return true;\r
+                       }\r
+                       else\r
+                               return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Add the elements from another collection to this collection. If this\r
+               /// collection has set semantics, only items not already in the collection\r
+               /// will be added.\r
+               /// </summary>\r
+               /// <param name="items">The items to add.</param>\r
+               [Tested]\r
+               public void AddAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       int c = 0;\r
+                       T j = default(T);\r
+            bool tmp;\r
+\r
+            updatecheck();\r
+                       foreach (T i in items)\r
+                               if (addIterative(i, ref j, false, out tmp)) c++;\r
+\r
+                       size += c;\r
+               }\r
+\r
+        /// <summary>\r
+        /// Add the elements from another collection with a more specialized item type \r
+        /// to this collection. If this\r
+        /// collection has set semantics, only items not already in the collection\r
+        /// will be added.\r
+        /// </summary>\r
+        /// <typeparam name="U">The type of items to add</typeparam>\r
+        /// <param name="items">The items to add</param>\r
+        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
+        {\r
+            int c = 0;\r
+            T j = default(T);\r
+            bool tmp;\r
+\r
+            updatecheck();\r
+            foreach (T i in items)\r
+                if (addIterative(i, ref j, false, out tmp)) c++;\r
+\r
+            size += c;\r
+        }\r
+\r
+\r
+        /// <summary>\r
+               /// Add all the items from another collection with an enumeration order that \r
+               /// is increasing in the items. <para>The idea is that the implementation may use\r
+               /// a faster algorithm to merge the two collections.</para>\r
+               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
+               /// not to be in increasing order.\r
+               /// </summary>\r
+               /// <param name="items">The collection to add.</param>\r
+               [Tested]\r
+               public void AddSorted(MSG.IEnumerable<T> items)\r
+               {\r
+                       if (size > 0)\r
+                               AddAll(items);\r
+                       else\r
+                       {\r
+                               updatecheck();\r
+                               addSorted(items, true);\r
+                       }\r
+               }\r
+\r
+               #region add-sorted helpers\r
+               \r
+               //Create a RB tree from x+2^h-1  (x < 2^h, h>=1) nodes taken from a\r
+               //singly linked list of red nodes using only the right child refs.\r
+               //The x nodes at depth h+1 will be red, the rest black.\r
+               //(h is the blackdepth of the resulting tree)\r
+               static Node maketreer(ref Node rest, int blackheight, int maxred, int red)\r
+               {\r
+                       if (blackheight == 1)\r
+                       {\r
+                               Node top = rest;\r
+\r
+                               rest = rest.right;\r
+                               if (red > 0)\r
+                               {\r
+                                       top.right = null;\r
+                                       rest.left = top;\r
+                                       top = rest;\r
+#if BAG\r
+                                       top.size += top.left.size;\r
+#elif MAINTAIN_SIZE\r
+                                       top.size = 1 + red;\r
+#endif\r
+                                       rest = rest.right;\r
+                                       red--;\r
+                               }\r
+\r
+                               if (red > 0)\r
+                               {\r
+#if BAG\r
+                                       top.size += rest.size;\r
+#endif\r
+                                       top.right = rest;\r
+                                       rest = rest.right;\r
+                                       top.right.right = null;\r
+                               }\r
+                               else\r
+                                       top.right = null;\r
+\r
+                               top.red = false;\r
+                               return top;\r
+                       }\r
+                       else\r
+                       {\r
+                               maxred >>=1;\r
+\r
+                               int lred = red > maxred ? maxred : red;\r
+                               Node left = maketreer(ref rest, blackheight - 1, maxred, lred);\r
+                               Node top = rest;\r
+\r
+                               rest = rest.right;\r
+                               top.left = left;\r
+                               top.red = false;\r
+#if MAINTAIN_RANK\r
+                               top.rank = (short)blackheight;\r
+#endif\r
+                               top.right = maketreer(ref rest, blackheight - 1, maxred, red - lred);\r
+#if BAG\r
+                               top.size = top.items + top.left.size + top.right.size;\r
+#elif MAINTAIN_SIZE\r
+                               top.size = (maxred << 1) - 1 + red;\r
+#endif\r
+                               return top;\r
+                       }\r
+               }\r
+\r
+\r
+               void addSorted(MSG.IEnumerable<T> items, bool safe)\r
+               {\r
+                       MSG.IEnumerator<T> e = items.GetEnumerator();;\r
+                       if (size > 0)\r
+                               throw new ApplicationException("This can't happen");\r
+\r
+                       if (!e.MoveNext())\r
+                               return;\r
+\r
+                       //To count theCollect \r
+                       Node head = new Node(), tail = head;\r
+                       int z = 1;\r
+                       T lastitem = tail.item = e.Current;\r
+#if BAG\r
+                       int ec=0;\r
+#endif\r
+\r
+                       while (e.MoveNext())\r
+                       {\r
+#if BAG\r
+                               T thisitem = e.Current;\r
+                               int comp = comparer.Compare(lastitem, thisitem);\r
+                               if (comp>0)\r
+                                       throw new ArgumentException("Argument not sorted");\r
+                               if (comp == 0)\r
+                               {\r
+                                       tail.items++;\r
+                                       ec++;\r
+                               }\r
+                               else\r
+                               {\r
+                                       tail.size = tail.items;\r
+                                       z++;\r
+                                       tail.right = new Node();\r
+                                       tail = tail.right;\r
+                                       lastitem = tail.item = thisitem;\r
+#if NCP\r
+                                       tail.generation = generation;\r
+#endif\r
+                               }\r
+#else\r
+                               z++;\r
+                               tail.right = new Node();\r
+                               tail = tail.right;\r
+                               tail.item = e.Current;\r
+                               if (safe)\r
+                               {\r
+                                       if (comparer.Compare(lastitem, tail.item) >= 0)\r
+                                               throw new ArgumentException("Argument not sorted");\r
+\r
+                                       lastitem = tail.item;\r
+                               }\r
+#if NCP\r
+                               tail.generation = generation;\r
+#endif\r
+#endif\r
+                       }\r
+#if BAG\r
+                       tail.size = tail.items;\r
+#endif                         \r
+                       int blackheight = 0, red = z, maxred = 1;\r
+\r
+                       while (maxred <= red)\r
+                       {\r
+                               red -= maxred;\r
+                               maxred <<= 1;\r
+                               blackheight++;\r
+                       }\r
+\r
+                       root = TreeBag<T>.maketreer(ref head, blackheight, maxred, red);\r
+                       blackdepth = blackheight;\r
+                       size = z;\r
+#if BAG\r
+                       size += ec;\r
+#endif                         \r
+                       return;\r
+               }\r
+\r
+               #endregion\r
+\r
+#if BAG\r
+               /// <summary></summary>\r
+               /// <value>True since this collection has bag semantics.</value>\r
+               [Tested]\r
+               public bool AllowsDuplicates { [Tested]get { return true; } }\r
+#else\r
+               /// <summary></summary>\r
+               /// <value>False since this tree has set semantics.</value>\r
+               [Tested]\r
+               public bool AllowsDuplicates { [Tested]get { return false; } }\r
+#endif\r
+\r
+               #endregion\r
+\r
+               #region IEditableCollection<T> Members\r
+                       \r
+\r
+               /// <summary>\r
+               /// The value is symbolic indicating the type of asymptotic complexity\r
+               /// in terms of the size of this collection (worst-case or amortized as\r
+               /// relevant).\r
+               /// </summary>\r
+               /// <value>Speed.Log</value>\r
+               [Tested]\r
+               public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }\r
+\r
+\r
+               [Tested]\r
+               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
+\r
+\r
+               [Tested]\r
+               bool ICollection<T>.Equals(ICollection<T> that)\r
+               { return unsequencedequals(that); }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains (an item equivalent to according to the\r
+               /// itemhasher) a particular value.\r
+               /// </summary>\r
+               /// <param name="item">The value to check for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public bool Contains(T item)\r
+               {\r
+                       Node next; int comp = 0;\r
+\r
+                       next = root;\r
+                       while (next != null)\r
+                       {\r
+                comp = comparer.Compare(next.item, item);\r
+                if (comp == 0)\r
+                                       return true;\r
+\r
+                               next = comp < 0 ? right(next) : left(next);\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               //Variant for dictionary use\r
+               //Will return the actual matching item in the ref argument.\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, return in the ref argument (a\r
+               /// binary copy of) the actual value found.\r
+               /// </summary>\r
+               /// <param name="item">The value to look for.</param>\r
+               /// <returns>True if the items is in this collection.</returns>\r
+               [Tested]\r
+               public bool Find(ref T item)\r
+               {\r
+                       Node next; int comp = 0;\r
+\r
+                       next = root;\r
+                       while (next != null)\r
+                       {\r
+                comp = comparer.Compare(next.item, item);\r
+                if (comp == 0)\r
+                               {\r
+                                       item = next.item;\r
+                                       return true;\r
+                               }\r
+\r
+                               next = comp < 0 ? right(next) : left(next);\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find or add the item to the tree. If the tree does not contain\r
+               /// an item equivalent to this item add it, else return the exisiting\r
+               /// one in the ref argument. \r
+               ///\r
+               /// </summary>\r
+               /// <param name="item"></param>\r
+               /// <returns>True if item was found</returns>\r
+               [Tested]\r
+               public bool FindOrAdd(ref T item)\r
+               {\r
+                       updatecheck();\r
+            bool wasfound;\r
+\r
+            //Note: blackdepth of the tree is set inside addIterative\r
+                       if (addIterative(item, ref item, false, out wasfound))\r
+                       {\r
+                               size++;\r
+#if MAINTAIN_EXTREMA\r
+                               if (Compare(item, min) < 0)\r
+                                       min = item;\r
+                               else if (Compare(item, max) > 0)\r
+                                       max = item;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = root.height;\r
+#endif\r
+                               return wasfound;\r
+                       }\r
+                       else\r
+                               return true;\r
+\r
+               }\r
+\r
+\r
+               //For dictionary use. \r
+               //If found, the matching entry will be updated with the new item.\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
+               /// this updates all equivalent copies in\r
+               /// the collection.\r
+               /// </summary>\r
+               /// <param name="item">Value to update.</param>\r
+               /// <returns>True if the item was found and hence updated.</returns>\r
+               [Tested]\r
+               public bool Update(T item)\r
+               {\r
+                       updatecheck();\r
+#if NCP\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+#endif\r
+                       Node cursor = root;\r
+                       int comp = 0;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                comp = comparer.Compare(cursor.item, item);\r
+                if (comp == 0)\r
+                               {\r
+#if NCP\r
+                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                                       cursor.item = item;\r
+#if NCP\r
+                                       while (level > 0)\r
+                                       {\r
+                                               Node child = cursor;\r
+\r
+                                               cursor = path[--level];\r
+                                               path[level] = null;\r
+#if NCP\r
+                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#else\r
+                                               if (Node.CopyNode(maxsnapid, ref cursor, generation))\r
+                                               {\r
+                                                       if (dirs[level] > 0)\r
+                                                               cursor.left = child;\r
+                                                       else\r
+                                                               cursor.right = child;\r
+                                               }\r
+#endif\r
+                                       }\r
+\r
+                                       root = cursor;\r
+#endif\r
+                                       return true;\r
+                               }\r
+#if NCP\r
+                               dirs[level] = comp;\r
+                               path[level++] = cursor;\r
+#endif\r
+                               cursor = comp < 0 ? cursor.right : cursor.left;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains an item equivalent according to the\r
+               /// itemhasher to a particular value. If so, update the item in the collection \r
+               /// to with a binary copy of the supplied value; else add the value to the collection. \r
+               ///\r
+               /// <p>NOTE: the bag implementation is currently wrong!</p>\r
+               /// </summary>\r
+               /// <param name="item">Value to add or update.</param>\r
+               /// <returns>True if the item was found and updated (hence not added).</returns>\r
+               [Tested]\r
+               public bool UpdateOrAdd(T item)\r
+               {\r
+                       updatecheck();\r
+            bool wasfound;\r
+\r
+            //Note: blackdepth of the tree is set inside addIterative\r
+                       if (addIterative(item, ref item, true, out wasfound))\r
+                       {\r
+                               size++;\r
+#if MAINTAIN_EXTREMA\r
+                               if (Compare(item, min) < 0)\r
+                                       min = item;\r
+                               else if (Compare(item, max) > 0)\r
+                                       max = item;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               depth = root.height;\r
+#endif\r
+                               return wasfound;\r
+                       }\r
+                       else\r
+                               return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection. If the collection has bag\r
+               /// semantics only one copy equivalent to the supplied item is removed. \r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public bool Remove(T item)\r
+               {\r
+                       updatecheck();\r
+                       if (root == null)\r
+                               return false;\r
+\r
+                       return removeIterative(ref item, false);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Remove a particular item from this collection if found. If the collection\r
+               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
+               /// which one is implementation dependent. \r
+               /// If an item was removed, report a binary copy of the actual item removed in \r
+               /// the argument.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove on input.</param>\r
+               /// <returns>True if the item was found (and removed).</returns>\r
+               [Tested]\r
+               public bool RemoveWithReturn(ref T item)\r
+               {\r
+                       updatecheck();\r
+                       if (root == null)\r
+                               return false;\r
+\r
+                       return removeIterative(ref item, false);\r
+               }\r
+\r
+\r
+               private bool removeIterative(ref T item, bool all)\r
+               {\r
+                       //Stage 1: find item\r
+                       stackcheck();\r
+\r
+                       int level = 0, comp;\r
+                       Node cursor = root;\r
+\r
+                       while (true)\r
+                       {\r
+                comp = comparer.Compare(cursor.item, item);\r
+                if (comp == 0)\r
+                               {\r
+                                       item = cursor.item;\r
+#if BAG\r
+                                       if (!all && cursor.items > 1)\r
+                                       {\r
+#if NCP\r
+                                               Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                                               cursor.items--;\r
+                                               cursor.size--;\r
+                                               while (level-- > 0)\r
+                                               {\r
+                                                       Node kid = cursor;\r
+\r
+                                                       cursor = path[level];\r
+#if NCP\r
+                                                       Node.update(ref cursor, dirs[level] > 0,  kid,maxsnapid,generation);\r
+#endif\r
+                                                       cursor.size--;\r
+                                                       path[level] = null;\r
+                                               }\r
+                                               size--;\r
+                                               return true;\r
+                                       }\r
+#endif\r
+                                       break;\r
+                               }\r
+\r
+                               Node child = comp > 0 ? cursor.left : cursor.right;\r
+\r
+                               if (child == null)\r
+                                       return false;\r
+\r
+                               dirs[level] = comp;\r
+                               path[level++] = cursor;\r
+                               cursor = child;\r
+                       }\r
+\r
+                       return removeIterativePhase2(cursor, level);\r
+               }\r
+\r
+\r
+               private bool removeIterativePhase2(Node cursor, int level)\r
+               {\r
+                       if (size == 1)\r
+                       {\r
+                               clear();\r
+                               return true;\r
+                       }\r
+\r
+#if MAINTAIN_EXTREMA\r
+                       if (Compare(cursor.item, min) == 0)\r
+                               min = cursor.right != null ? cursor.right.item : path[level - 1].item;\r
+                       else if (Compare(cursor.item, max) == 0)\r
+                               max = cursor.left != null ? cursor.left.item : path[level - 1].item;\r
+#endif\r
+#if BAG\r
+                       int removedcount = cursor.items;\r
+                       size -= removedcount;\r
+#else\r
+                       //We are certain to remove one node:\r
+                       size--;\r
+#endif\r
+                       //Stage 2: if item's node has no null child, find predecessor\r
+                       int level_of_item = level;\r
+\r
+                       if (cursor.left != null && cursor.right != null)\r
+                       {\r
+                               dirs[level] = 1;\r
+                               path[level++] = cursor;\r
+                               cursor = cursor.left;\r
+                               while (cursor.right != null)\r
+                               {\r
+                                       dirs[level] = -1;\r
+                                       path[level++] = cursor;\r
+                                       cursor = cursor.right;\r
+                               }\r
+#if NCP\r
+                               Node.CopyNode(ref path[level_of_item], maxsnapid, generation);\r
+#endif\r
+                               path[level_of_item].item = cursor.item;\r
+#if BAG\r
+                               path[level_of_item].items = cursor.items;\r
+#endif\r
+                       }\r
+\r
+                       //Stage 3: splice out node to be removed\r
+                       Node newchild = cursor.right == null ? cursor.left : cursor.right;\r
+                       bool demote_or_rotate = newchild == null && !cursor.red;\r
+\r
+                       //assert newchild.red \r
+                       if (newchild != null)\r
+                       {\r
+                               newchild.red = false;\r
+                       }\r
+\r
+                       if (level == 0)\r
+                       {\r
+                               root = newchild;\r
+#if MAINTAIN_HEIGHT\r
+                               depth = 0;\r
+#endif\r
+                               return true;\r
+                       }\r
+\r
+                       level--;\r
+                       cursor = path[level];\r
+                       path[level] = null;\r
+\r
+                       int comp = dirs[level];\r
+                       Node childsibling;\r
+#if NCP\r
+                       Node.update(ref cursor, comp > 0, newchild, maxsnapid, generation);\r
+#else\r
+                       if (comp > 0)\r
+                               cursor.left = newchild;\r
+                       else\r
+                               cursor.right = newchild;\r
+#endif\r
+                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
+#if BAG\r
+                       cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                       cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                       fixheight(cursor);\r
+#endif\r
+\r
+                       //Stage 4: demote till we must rotate\r
+                       Node farnephew = null, nearnephew = null;\r
+\r
+                       while (demote_or_rotate)\r
+                       {\r
+                               if (childsibling.red)\r
+                                       break; //rotate 2+?\r
+\r
+                               farnephew = comp > 0 ? childsibling.right : childsibling.left;\r
+                               if (farnephew != null && farnephew.red)\r
+                                       break; //rotate 1b\r
+\r
+                               nearnephew = comp > 0 ? childsibling.left : childsibling.right;\r
+                               if (nearnephew != null && nearnephew.red)\r
+                                       break; //rotate 1c\r
+\r
+                               //demote cursor\r
+                               childsibling.red = true;\r
+#if MAINTAIN_RANK\r
+                               cursor.rank--;\r
+#endif\r
+                               if (level == 0)\r
+                               {\r
+                                       cursor.red = false;\r
+                                       blackdepth--;\r
+#if MAINTAIN_HEIGHT\r
+                                       depth = root.height;\r
+#endif\r
+#if NCP\r
+                                       root = cursor;\r
+#endif\r
+                                       return true;\r
+                               }\r
+                               else if (cursor.red)\r
+                               {\r
+                                       cursor.red = false;\r
+                                       demote_or_rotate = false;\r
+                                       break; //No rotation\r
+                               }\r
+                               else\r
+                               {\r
+                                       Node child = cursor;\r
+\r
+                                       cursor = path[--level];\r
+                                       path[level] = null;\r
+                                       comp = dirs[level];\r
+                                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
+#if NCP\r
+                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
+#endif\r
+#if BAG\r
+                                       cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                       }\r
+\r
+                       //Stage 5: rotate \r
+                       if (demote_or_rotate)\r
+                       {\r
+                               //At start:\r
+                               //parent = cursor (temporary for swapping nodes)\r
+                               //childsibling is the sibling of the updated child (x)\r
+                               //cursor is always the top of the subtree\r
+                               Node parent = cursor;\r
+\r
+                               if (childsibling.red)\r
+                               {//Case 2 and perhaps more. \r
+                                       //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null \r
+                                       //(and black). The grandnephews are children of nearnephew\r
+                                       Node neargrandnephew, fargrandnephew;\r
+\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               nearnephew = childsibling.left;\r
+                                               farnephew = childsibling.right;\r
+                                               neargrandnephew = nearnephew.left;\r
+                                               fargrandnephew = nearnephew.right;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               nearnephew = childsibling.right;\r
+                                               farnephew = childsibling.left;\r
+                                               neargrandnephew = nearnephew.right;\r
+                                               fargrandnephew = nearnephew.left;\r
+                                       }\r
+\r
+                                       if (fargrandnephew != null && fargrandnephew.red)\r
+                                       {//Case 2+1b\r
+#if NCP\r
+                                               Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
+\r
+                                               //The end result of this will always be e copy of parent\r
+                                               Node.update(ref parent, comp < 0, neargrandnephew, maxsnapid, generation);\r
+                                               Node.update(ref childsibling, comp > 0, nearnephew, maxsnapid, generation);\r
+#endif\r
+                                               if (comp > 0)\r
+                                               {\r
+                                                       nearnephew.left = parent;\r
+                                                       parent.right = neargrandnephew;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       nearnephew.right = parent;\r
+                                                       parent.left = neargrandnephew;\r
+                                               }\r
+\r
+                                               cursor = childsibling;\r
+                                               childsibling.red = false;\r
+                                               nearnephew.red = true;\r
+                                               fargrandnephew.red = false;\r
+#if MAINTAIN_RANK\r
+                                               nearnephew.rank++;\r
+                                               parent.rank--;\r
+#endif\r
+#if BAG\r
+                                               cursor.size = parent.size;\r
+                                               nearnephew.size = cursor.size - cursor.items - farnephew.size;\r
+                                               parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size;\r
+#elif MAINTAIN_SIZE\r
+                                               cursor.size = parent.size;\r
+                                               nearnephew.size = cursor.size - 1 - farnephew.size;\r
+                                               parent.size = nearnephew.size - 1 - fargrandnephew.size;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(parent);\r
+                                               fixheight(nearnephew);\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                                       else if (neargrandnephew != null && neargrandnephew.red)\r
+                                       {//Case 2+1c\r
+#if NCP\r
+                                               Node.CopyNode(ref neargrandnephew, maxsnapid, generation);\r
+#endif\r
+                                               if (comp > 0)\r
+                                               {\r
+#if NCP\r
+                                                       Node.update(ref childsibling, true, neargrandnephew, maxsnapid, generation);\r
+                                                       Node.update(ref nearnephew, true, neargrandnephew.right, maxsnapid, generation);\r
+                                                       Node.update(ref parent, false, neargrandnephew.left, maxsnapid, generation);\r
+#else\r
+                                                       childsibling.left = neargrandnephew;\r
+                                                       nearnephew.left = neargrandnephew.right;\r
+                                                       parent.right = neargrandnephew.left;\r
+#endif\r
+                                                       neargrandnephew.left = parent;\r
+                                                       neargrandnephew.right = nearnephew;\r
+                                               }\r
+                                               else\r
+                                               {\r
+#if NCP\r
+                                                       Node.update(ref childsibling, false, neargrandnephew, maxsnapid, generation);\r
+                                                       Node.update(ref nearnephew, false, neargrandnephew.left, maxsnapid, generation);\r
+                                                       Node.update(ref parent, true, neargrandnephew.right, maxsnapid, generation);\r
+#else\r
+                                                       childsibling.right = neargrandnephew;\r
+                                                       nearnephew.right = neargrandnephew.left;\r
+                                                       parent.left = neargrandnephew.right;\r
+#endif\r
+                                                       neargrandnephew.right = parent;\r
+                                                       neargrandnephew.left = nearnephew;\r
+                                               }\r
+\r
+                                               cursor = childsibling;\r
+                                               childsibling.red = false;\r
+#if MAINTAIN_RANK\r
+                                               neargrandnephew.rank++;\r
+                                               parent.rank--;\r
+#endif\r
+#if BAG\r
+                                               cursor.size = parent.size;\r
+                                               parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                               nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
+                                               neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size;\r
+#elif MAINTAIN_SIZE\r
+                                               cursor.size = parent.size;\r
+                                               parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                               nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
+                                               neargrandnephew.size = 1 + parent.size + nearnephew.size;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(parent);\r
+                                               fixheight(nearnephew);\r
+                                               fixheight(neargrandnephew);\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                                       else\r
+                                       {//Case 2 only\r
+#if NCP\r
+                                               Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
+                                               Node.update(ref childsibling, comp > 0, parent, maxsnapid, generation);\r
+#else\r
+                                               if (comp > 0)\r
+                                               {\r
+                                                       childsibling.left = parent;\r
+                                                       parent.right = nearnephew;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       childsibling.right = parent;\r
+                                                       parent.left = nearnephew;\r
+                                               }\r
+#endif\r
+                                               cursor = childsibling;\r
+                                               childsibling.red = false;\r
+                                               nearnephew.red = true;\r
+#if MAINTAIN_RANK\r
+                                               parent.rank--;\r
+#endif\r
+#if BAG\r
+                                               cursor.size = parent.size;\r
+                                               parent.size -= farnephew.size + cursor.items;\r
+#elif MAINTAIN_SIZE\r
+                                               cursor.size = parent.size;\r
+                                               parent.size -= farnephew.size + 1;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                               fixheight(parent);\r
+                                               fixheight(cursor);\r
+#endif\r
+                                       }\r
+                               }\r
+                               else if (farnephew != null && farnephew.red)\r
+                               {//Case 1b\r
+                                       nearnephew = comp > 0 ? childsibling.left : childsibling.right;         \r
+#if NCP\r
+                                       Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
+                                       Node.CopyNode(ref childsibling, maxsnapid, generation);\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               childsibling.left = parent;\r
+                                               childsibling.right = farnephew;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               childsibling.right = parent;\r
+                                               childsibling.left = farnephew;\r
+                                       }\r
+#else\r
+                                       if (comp > 0)\r
+                                       {\r
+                                               childsibling.left = parent;\r
+                                               parent.right = nearnephew;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               childsibling.right = parent;\r
+                                               parent.left = nearnephew;\r
+                                       }\r
+#endif\r
+                                       cursor = childsibling;\r
+                                       cursor.red = parent.red;\r
+                                       parent.red = false;\r
+                                       farnephew.red = false;\r
+\r
+#if MAINTAIN_RANK\r
+                                       childsibling.rank++;\r
+                                       parent.rank--;\r
+#endif\r
+#if BAG\r
+                                       cursor.size = parent.size;\r
+                                       parent.size -= farnephew.size + cursor.items;\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size = parent.size;\r
+                                       parent.size -= farnephew.size + 1;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(parent);\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                               else if (nearnephew != null && nearnephew.red)\r
+                               {//Case 1c\r
+#if NCP\r
+                                       Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
+#endif\r
+                                       if (comp > 0)\r
+                                       {\r
+#if NCP\r
+                                               Node.update(ref childsibling, true, nearnephew.right, maxsnapid, generation);\r
+                                               Node.update(ref parent, false, nearnephew.left, maxsnapid, generation);\r
+#else\r
+                                               childsibling.left = nearnephew.right;\r
+                                               parent.right = nearnephew.left;\r
+#endif\r
+                                               nearnephew.left = parent;\r
+                                               nearnephew.right = childsibling;\r
+                                       }\r
+                                       else\r
+                                       {\r
+#if NCP\r
+                                               Node.update(ref childsibling, false, nearnephew.left, maxsnapid, generation);\r
+                                               Node.update(ref parent, true, nearnephew.right, maxsnapid, generation);\r
+#else\r
+                                               childsibling.right = nearnephew.left;\r
+                                               parent.left = nearnephew.right;\r
+#endif\r
+                                               nearnephew.right = parent;\r
+                                               nearnephew.left = childsibling;\r
+                                       }\r
+\r
+                                       cursor = nearnephew;\r
+                                       cursor.red = parent.red;\r
+                                       parent.red = false;\r
+#if MAINTAIN_RANK\r
+                                       nearnephew.rank++;\r
+                                       parent.rank--;\r
+#endif\r
+#if BAG\r
+                                       cursor.size = parent.size;\r
+                                       parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                       childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size = parent.size;\r
+                                       parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
+                                       childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(parent);\r
+                                       fixheight(childsibling);\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                               else\r
+                               {//Case 1a can't happen\r
+                                       throw new Exception("Case 1a can't happen here");\r
+                               }\r
+\r
+                               //Resplice cursor:\r
+                               if (level == 0)\r
+                               {\r
+                                       root = cursor;\r
+                               }\r
+                               else\r
+                               {\r
+                                       Node swap = cursor;\r
+\r
+                                       cursor = path[--level];\r
+                                       path[level] = null;\r
+#if NCP\r
+                                       Node.update(ref cursor, dirs[level] > 0, swap, maxsnapid, generation);\r
+#else\r
+                               \r
+                                       if (dirs[level] > 0)\r
+                                               cursor.left = swap;\r
+                                       else\r
+                                               cursor.right = swap;\r
+#endif\r
+#if BAG\r
+                                       cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                                       cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                                       fixheight(cursor);\r
+#endif\r
+                               }\r
+                       }\r
+\r
+                       //Stage 6: fixup to the root\r
+                       while (level > 0)\r
+                       {\r
+                               Node child = cursor;\r
+\r
+                               cursor = path[--level];\r
+                               path[level] = null;\r
+#if NCP\r
+                               if (child != (dirs[level] > 0 ? cursor.left : cursor.right))\r
+                                       Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
+#endif\r
+#if BAG\r
+                               cursor.size -= removedcount;\r
+#elif MAINTAIN_SIZE\r
+                               cursor.size--;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               fixheight(cursor);\r
+#endif\r
+                       }\r
+\r
+#if MAINTAIN_HEIGHT\r
+                       depth = root.height;\r
+#endif\r
+#if NCP\r
+                       root = cursor;\r
+#endif\r
+                       return true;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items from this collection.\r
+               /// </summary>\r
+               [Tested]\r
+               public void Clear()\r
+               {\r
+                       updatecheck();\r
+                       clear();\r
+               }\r
+\r
+\r
+               private void clear()\r
+               {\r
+                       size = 0;\r
+                       root = null;\r
+                       blackdepth = 0;\r
+#if MAINTAIN_HEIGHT\r
+                       depth = 0;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items in another collection from this one. If this collection\r
+               /// has bag semantics, take multiplicities into account.\r
+               /// </summary>\r
+               /// <param name="items">The items to remove.</param>\r
+               [Tested]\r
+               public void RemoveAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       T jtem;\r
+\r
+                       foreach (T item in items)\r
+                       {\r
+                               if (root == null)\r
+                                       break;\r
+\r
+                               jtem = item;\r
+                               removeIterative(ref jtem, false);\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items not in some other collection from this one. If this collection\r
+               /// has bag semantics, take multiplicities into account.\r
+               /// </summary>\r
+               /// <param name="items">The items to retain.</param>\r
+               [Tested]\r
+               public void RetainAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       updatecheck();\r
+\r
+                       //A much more efficient version is possible if items is sorted like this.\r
+                       //Well, it is unclear how efficient it would be.\r
+                       //We could use a marking method!?\r
+                       TreeBag<T> t = (TreeBag<T>)MemberwiseClone();\r
+\r
+                       t.Clear();\r
+                       foreach (T item in items)\r
+                               if (ContainsCount(item) > t.ContainsCount(item))\r
+                                       t.Add(item);\r
+\r
+                       root = t.root;\r
+                       size = t.size;\r
+                       blackdepth = t.blackdepth;\r
+#if MAINTAIN_HEIGHT\r
+                       depth = t.depth;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Check if this collection contains all the values in another collection.\r
+               /// If this collection has bag semantics (<code>NoDuplicates==false</code>)\r
+               /// the check is made with respect to multiplicities, else multiplicities\r
+               /// are not taken into account.\r
+               /// </summary>\r
+               /// <param name="items">The </param>\r
+               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+               [Tested]\r
+               public bool ContainsAll(MSG.IEnumerable<T> items)\r
+               {\r
+                       //This is worst-case O(m*logn)\r
+                       foreach (T item in items)\r
+                               if (!Contains(item)) return false;\r
+\r
+                       return true;\r
+               }\r
+\r
+\r
+               //Higher order:\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the items of this\r
+               /// indexed sorted collection satisfying a certain predicate.\r
+               /// </summary>\r
+               /// <param name="filter">The filter delegate defining the predicate.</param>\r
+               /// <returns>The new indexed sorted collection.</returns>\r
+               [Tested]\r
+               public IIndexedSorted<T> FindAll(Filter<T> filter)\r
+               {\r
+                       TreeBag<T> res = new TreeBag<T>(comparer);\r
+                       MSG.IEnumerator<T> e = GetEnumerator();\r
+                       Node head = null, tail = null;\r
+                       int z = 0;\r
+#if BAG\r
+                       int ec = 0;\r
+#endif\r
+                       while (e.MoveNext())\r
+                       {\r
+                               T thisitem = e.Current;\r
+#if BAG\r
+                               //We could document that filter will only be called \r
+                               //once on each unique item. That might even be good for the user!\r
+                               if (tail!=null && comparer.Compare(thisitem, tail.item) == 0)\r
+                               {\r
+                                       tail.items++;\r
+                                       ec++;\r
+                                       continue;\r
+                               }\r
+#endif\r
+                               if (filter(thisitem))\r
+                               {\r
+                                       if (head == null)\r
+                                       {\r
+                                               head = tail = new Node();\r
+                                       }\r
+                                       else\r
+                                       {\r
+#if BAG\r
+                                               tail.size = tail.items;\r
+#endif\r
+                                               tail.right = new Node();\r
+                                               tail = tail.right;\r
+                                       }\r
+\r
+                                       tail.item = thisitem;\r
+                                       z++;\r
+                               }\r
+                       }\r
+#if BAG\r
+                       if (tail!=null)\r
+                               tail.size = tail.items;\r
+#endif\r
+\r
+                       if (z == 0)\r
+                               return res;\r
+\r
+                       int blackheight = 0, red = z, maxred = 1;\r
+\r
+                       while (maxred <= red)\r
+                       {\r
+                               red -= maxred;\r
+                               maxred <<= 1;\r
+                               blackheight++;\r
+                       }\r
+\r
+                       res.root = TreeBag<T>.maketreer(ref head, blackheight, maxred, red);\r
+                       res.blackdepth = blackheight;\r
+                       res.size = z;\r
+#if BAG\r
+                       res.size += ec;\r
+#endif\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a new indexed sorted collection consisting of the results of\r
+               /// mapping all items of this list.\r
+               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
+               /// the items of this collection (with respect to the two given comparison \r
+               /// relations).\r
+               /// </summary>\r
+               /// <param name="mapper">The delegate definging the map.</param>\r
+               /// <param name="c">The comparion relation to use for the result.</param>\r
+               /// <returns>The new sorted collection.</returns>\r
+               [Tested]\r
+               public IIndexedSorted<V> Map<V>(Mapper<T,V> mapper, IComparer<V> c)\r
+               {\r
+                       TreeBag<V> res = new TreeBag<V>(c);\r
+\r
+                       if (size == 0)\r
+                               return res;\r
+\r
+                       MSG.IEnumerator<T> e = GetEnumerator();\r
+                       TreeBag<V>.Node head = null, tail = null;\r
+                       V oldv = default(V);\r
+                       int z = 0;\r
+#if BAG\r
+                       T lastitem = default(T);\r
+#endif\r
+                       while (e.MoveNext())\r
+                       {\r
+                               T thisitem = e.Current;\r
+#if BAG\r
+                               //We could document that mapper will only be called \r
+                               //once on each unique item. That might even be good for the user!\r
+                               if (tail != null && comparer.Compare(thisitem, lastitem) == 0)\r
+                               {\r
+                                       tail.items++;\r
+                                       continue;\r
+                               }\r
+#endif\r
+                               V newv = mapper(thisitem);\r
+\r
+                               if (head == null)\r
+                               {\r
+                                       head = tail = new TreeBag<V>.Node();\r
+                                       z++;\r
+                               }\r
+                               else\r
+                               {\r
+                                       int comp = c.Compare(oldv, newv);\r
+#if BAG\r
+                                       if (comp == 0)\r
+                                       {\r
+                                               tail.items++;\r
+                                               continue;\r
+                                       }\r
+                                       if (comp > 0)\r
+#else\r
+                                       if (comp >= 0)\r
+#endif\r
+                                               throw new ArgumentException("mapper not monotonic");\r
+#if BAG\r
+                                       tail.size = tail.items;\r
+#endif\r
+                                       tail.right = new TreeBag<V>.Node();\r
+                                       tail = tail.right;\r
+                                       z++;\r
+                               }\r
+#if BAG\r
+                               lastitem = thisitem;\r
+#endif\r
+                               tail.item = oldv = newv;\r
+                       }\r
+\r
+#if BAG\r
+                       tail.size = tail.items;\r
+#endif\r
+\r
+                       int blackheight = 0, red = z, maxred = 1;\r
+\r
+                       while (maxred <= red)\r
+                       {\r
+                               red -= maxred;\r
+                               maxred <<= 1;\r
+                               blackheight++;\r
+                       }\r
+\r
+                       res.root = TreeBag<V>.maketreer(ref head, blackheight, maxred, red);\r
+                       res.blackdepth = blackheight;\r
+                       res.size = size;\r
+                       return res;\r
+               }\r
+\r
+\r
+               //below is the bag utility stuff\r
+               /// <summary>\r
+               /// Count the number of items of the collection equal to a particular value.\r
+               /// Returns 0 if and only if the value is not in the collection.\r
+               /// </summary>\r
+               /// <param name="item">The value to count.</param>\r
+               /// <returns>The number of copies found.</returns>\r
+               [Tested]\r
+               public int ContainsCount(T item)\r
+               {\r
+#if BAG\r
+                       Node next; int comp = 0;\r
+\r
+                       next = root;\r
+                       while (next != null)\r
+                       {\r
+                               comp = comparer.Compare(next.item, item);\r
+                               if (comp == 0)\r
+                                       return next.items;\r
+\r
+                               next = comp < 0 ? right(next) : left(next);\r
+                       }\r
+\r
+                       return 0;\r
+#else\r
+                       //Since we are strictly NoDuplicates we just do\r
+                       return Contains(item) ? 1 : 0;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items equivalent to a given value.\r
+               /// </summary>\r
+               /// <param name="item">The value to remove.</param>\r
+               [Tested]\r
+               public void RemoveAllCopies(T item)\r
+               {\r
+#if BAG\r
+                       updatecheck();\r
+                       removeIterative(ref item, true);\r
+#else\r
+                       \r
+                       Remove(item);\r
+#endif\r
+               }\r
+\r
+\r
+               #endregion\r
+\r
+               #region IIndexed<T> Members\r
+                       \r
+               private Node findNode(int i)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                       Node next = root;\r
+\r
+                       if (i >= 0 && i < size)\r
+                               while (true)\r
+                               {\r
+                                       int j = next.left == null ? 0 : next.left.size;\r
+\r
+                                       if (i > j)\r
+                                       {\r
+#if BAG\r
+                                               i -= j + next.items;                                    \r
+                                               if (i<0)\r
+                                                       return next;\r
+#else\r
+                                               i -= j + 1;\r
+#endif\r
+                                               next = next.right;\r
+                                       }\r
+                                       else if (i == j)\r
+                                               return next;\r
+                                       else\r
+                                               next = next.left;\r
+                               }\r
+\r
+                       throw new IndexOutOfRangeException();\r
+#else\r
+                       throw new NotSupportedException();\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <value>The i'th item of this list.</value>\r
+               /// <param name="i">the index to lookup</param>\r
+               [Tested]\r
+               public T this[int i] { [Tested] get { return findNode(i).item; } }\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going forwrds from the start.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of item from start.</returns>\r
+               [Tested]\r
+               public int IndexOf(T item)\r
+               {\r
+                       int upper;\r
+\r
+                       return indexOf(item, out upper);\r
+               }\r
+\r
+\r
+               private int indexOf(T item, out int upper)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                       int ind = 0; Node next = root;\r
+\r
+                       while (next != null)\r
+                       {\r
+                int comp = comparer.Compare(item, next.item);\r
+\r
+                if (comp < 0)\r
+                                       next = next.left;\r
+                               else\r
+                               {\r
+                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
+\r
+                                       if (comp == 0)\r
+                                       {\r
+#if BAG\r
+                                               upper = ind + leftcnt + next.items - 1;\r
+                                               return ind + leftcnt;\r
+#else\r
+                                               return upper = ind + leftcnt;\r
+#endif\r
+                                       }\r
+                                       else\r
+                                       {\r
+#if BAG\r
+                                               ind = ind + next.items + leftcnt;\r
+#else\r
+                                               ind = ind + 1 + leftcnt;\r
+#endif\r
+                                               next = next.right;\r
+                                       }\r
+                               }\r
+                       }\r
+#endif\r
+                       upper = -1;\r
+                       return -1;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Searches for an item in the list going backwords from the end.\r
+               /// </summary>\r
+               /// <param name="item">Item to search for.</param>\r
+               /// <returns>Index of of item from the end.</returns>\r
+               [Tested]\r
+               public int LastIndexOf(T item)\r
+               {\r
+#if BAG\r
+                       int res;\r
+                       indexOf(item, out res);\r
+                       return res;\r
+#else\r
+                       //We have NoDuplicates==true for the set\r
+                       return IndexOf(item);\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the item at a specific position of the list.\r
+               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
+               /// &gt;= the size of the collection.\r
+               /// </summary>\r
+               /// <param name="i">The index of the item to remove.</param>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T RemoveAt(int i)\r
+               {\r
+                       updatecheck();\r
+#if MAINTAIN_SIZE\r
+                       if (i < 0 || i >= size)\r
+                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
+\r
+                       //We must follow the pattern of removeIterative()\r
+                       while (dirs.Length < 2 * blackdepth)\r
+                       {\r
+                               dirs = new int[2 * dirs.Length];\r
+                               path = new Node[2 * dirs.Length];\r
+                       }\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (true)\r
+                       {\r
+                               int j = cursor.left == null ? 0 : cursor.left.size;\r
+\r
+                               if (i > j)\r
+                               {\r
+#if BAG\r
+                                       i -= j + cursor.items;\r
+                                       if (i<0)\r
+                                               break;\r
+#else\r
+                                       i -= j + 1;\r
+#endif\r
+                                       dirs[level] = -1;\r
+                                       path[level++] = cursor;\r
+                                       cursor = cursor.right;\r
+                               }\r
+                               else if (i == j)\r
+                                       break;\r
+                               else\r
+                               {\r
+                                       dirs[level] = 1;\r
+                                       path[level++] = cursor;\r
+                                       cursor = cursor.left;\r
+                               }\r
+                       }\r
+\r
+                       T retval = cursor.item;\r
+\r
+#if BAG\r
+                       if (cursor.items>1)\r
+                       {\r
+                               resplicebag(level, cursor);\r
+                               size--;\r
+                               return retval;\r
+                       }\r
+#endif\r
+                       removeIterativePhase2(cursor, level);\r
+                       return retval;\r
+#else\r
+                       throw new NotSupportedException();\r
+#endif\r
+               }\r
+\r
+#if BAG\r
+               private void resplicebag(int level, Node cursor)\r
+               {\r
+#if NCP\r
+                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+                       cursor.items--;\r
+                       cursor.size--;\r
+                       while (level-- > 0)\r
+                       {\r
+                               Node kid = cursor;\r
+\r
+                               cursor = path[level];\r
+#if NCP\r
+                               Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
+#endif\r
+                               cursor.size--;\r
+                               path[level] = null;\r
+                       }\r
+               }\r
+#endif\r
+               /// <summary>\r
+               /// Remove all items in an index interval.\r
+               /// <exception cref="IndexOutOfRangeException"/>???. \r
+               /// </summary>\r
+               /// <param name="start">The index of the first item to remove.</param>\r
+               /// <param name="count">The number of items to remove.</param>\r
+               [Tested]\r
+               public void RemoveInterval(int start, int count)\r
+               {\r
+                       if (start < 0 || count < 0)\r
+                               throw new ArgumentOutOfRangeException();\r
+\r
+                       if (start + count > this.size)\r
+                               throw new ArgumentException();\r
+\r
+                       updatecheck();\r
+\r
+                       //This is terrible for large count. We should split the tree at \r
+                       //the endpoints of the range and fuse the parts!\r
+                       //We really need good internal destructive split and catenate functions!\r
+                       for (int i = 0; i < count; i++)\r
+                               RemoveAt(start);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// <exception cref="IndexOutOfRangeException"/>.\r
+               /// </summary>\r
+               /// <value>The directed collection of items in a specific index interval.</value>\r
+               /// <param name="start">The low index of the interval (inclusive).</param>\r
+               /// <param name="end">The high index of the interval (exclusive).</param>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> this[int start, int end]\r
+               {\r
+                       [Tested]\r
+                       get\r
+                       {\r
+                               checkRange(start, end - start);\r
+                               return new Interval(this, start, end - start, true);\r
+                       }\r
+               }\r
+\r
+               #region Interval nested class\r
+               class Interval: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
+               {\r
+                       int start, length, stamp;\r
+\r
+                       bool forwards;\r
+\r
+                       TreeBag<T> tree;\r
+\r
+\r
+                       internal Interval(TreeBag<T> tree, int start, int count, bool forwards)\r
+                       {\r
+#if NCP\r
+                               if (tree.isSnapShot)\r
+                                       throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+                               this.start = start; this.length = count;this.forwards = forwards;\r
+                               this.tree = tree; this.stamp = tree.stamp;\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+            public override int Count { [Tested]get { return length; } }\r
+\r
+\r
+            public override Speed CountSpeed { get { return Speed.Constant; } }\r
+            \r
+            [Tested]\r
+            public override MSG.IEnumerator<T> GetEnumerator()\r
+                       {\r
+#if MAINTAIN_SIZE\r
+                               tree.modifycheck(stamp);\r
+#if BAG\r
+                               int togo;\r
+#endif\r
+                               Node cursor = tree.root;\r
+                               Node[] path = new Node[2 * tree.blackdepth];\r
+                               int level = 0, totaltogo = length;\r
+\r
+                               if (totaltogo == 0)\r
+                                       yield break;\r
+\r
+                               if (forwards)\r
+                               {\r
+                                       int i = start;\r
+\r
+                                       while (true)\r
+                                       {\r
+                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
+\r
+                                               if (i > j)\r
+                                               {\r
+#if BAG\r
+                                                       i -= j + cursor.items;\r
+                                                       if (i < 0)\r
+                                                       {\r
+                                                               togo = cursor.items + i;\r
+                                                               break;\r
+                                                       }\r
+#else\r
+                                                       i -= j + 1;\r
+#endif\r
+                                                       cursor = cursor.right;\r
+                                               }\r
+                                               else if (i == j)\r
+                                               {\r
+#if BAG\r
+                                                       togo = cursor.items;\r
+#endif\r
+                                                       break;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       path[level++] = cursor;\r
+                                                       cursor = cursor.left;\r
+                                               }\r
+                                       }\r
+\r
+                                       T current = cursor.item;\r
+\r
+                                       while (totaltogo-- > 0)\r
+                                       {\r
+                                               yield return current;\r
+                                               tree.modifycheck(stamp);\r
+#if BAG\r
+                                               if (--togo > 0)\r
+                                                       continue;\r
+#endif\r
+                                               if (cursor.right != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.right;\r
+                                                       while (cursor.left != null)\r
+                                                               path[++level] = cursor = cursor.left;\r
+                                               }\r
+                                               else if (level == 0)\r
+                                                       yield break;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       int i = start + length - 1;\r
+\r
+                                       while (true)\r
+                                       {\r
+                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
+\r
+                                               if (i > j)\r
+                                               {\r
+#if BAG\r
+                                                       if (i - j < cursor.items)\r
+                                                       {\r
+                                                               togo = i - j + 1;\r
+                                                               break;\r
+                                                       }\r
+                                                       i -= j + cursor.items;\r
+#else\r
+                                                       i -= j + 1;\r
+#endif\r
+                                                       path[level++] = cursor;\r
+                                                       cursor = cursor.right;\r
+                                               }\r
+                                               else if (i == j)\r
+                                               {\r
+#if BAG\r
+                                                       togo = 1;\r
+#endif\r
+                                                       break;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       cursor = cursor.left;\r
+                                               }\r
+                                       }\r
+\r
+                                       T current = cursor.item;\r
+\r
+                                       while (totaltogo-- > 0)\r
+                                       {\r
+                                               yield return current;\r
+                                               tree.modifycheck(stamp);\r
+#if BAG\r
+                                               if (--togo > 0)\r
+                                                       continue;\r
+#endif\r
+                                               if (cursor.left != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.left;\r
+                                                       while (cursor.right != null)\r
+                                                               path[++level] = cursor = cursor.right;\r
+                                               }\r
+                                               else if (level == 0)\r
+                                                       yield break;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                       }\r
+                               }\r
+\r
+#else\r
+                       throw new NotSupportedException();\r
+#endif\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       public IDirectedCollectionValue<T> Backwards()\r
+                       { return new Interval(tree, start, length, !forwards); }\r
+\r
+\r
+                       [Tested]\r
+                       IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()\r
+                       { return Backwards(); }\r
+\r
+\r
+                       [Tested]\r
+                       public EnumerationDirection Direction\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;\r
+                               }\r
+                       }\r
+               }\r
+               #endregion\r
+\r
+               /// <summary>\r
+               /// Create a collection containing the same items as this collection, but\r
+               /// whose enumerator will enumerate the items backwards. The new collection\r
+               /// will become invalid if the original is modified. Method typicaly used as in\r
+               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
+               /// </summary>\r
+               /// <returns>The backwards collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+               #endregion\r
+\r
+               #region ISequenced Members\r
+               [Tested]\r
+               int ISequenced<T>.GetHashCode() { return sequencedhashcode(); }\r
+\r
+\r
+               [Tested]\r
+               bool ISequenced<T>.Equals(ISequenced<T> that) { return sequencedequals(that); }\r
+               #endregion\r
+\r
+               #region PriorityQueue Members\r
+\r
+        /// <summary>\r
+        /// The comparer object supplied at creation time for this collection\r
+        /// </summary>\r
+        /// <value>The comparer</value>\r
+        public IComparer<T> Comparer { get { return comparer; } }\r
+\r
+\r
+        /// <summary>\r
+               /// Find the current least item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The least item.</returns>\r
+               [Tested]\r
+               public T FindMin()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+#if MAINTAIN_EXTREMA\r
+                       return min;\r
+#else\r
+                       Node cursor = root, next = left(cursor);\r
+\r
+                       while (next != null)\r
+                       {\r
+                               cursor = next;\r
+                               next = left(cursor);\r
+                       }\r
+\r
+                       return cursor.item;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the least item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMin()\r
+               {\r
+                       updatecheck();\r
+\r
+                       //persistence guard?\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       //We must follow the pattern of removeIterative()\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (cursor.left != null)\r
+                       {\r
+                               dirs[level] = 1;\r
+                               path[level++] = cursor;\r
+                               cursor = cursor.left;\r
+                       }\r
+\r
+                       T retval = cursor.item;\r
+\r
+#if BAG\r
+                       if (cursor.items > 1)\r
+                       {\r
+                               resplicebag(level, cursor);\r
+                               size--;\r
+                               return retval;\r
+                       }\r
+#endif\r
+                       removeIterativePhase2(cursor, level);\r
+                       return retval;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the current largest item of this priority queue.\r
+               /// </summary>\r
+               /// <returns>The largest item.</returns>\r
+               [Tested]\r
+               public T FindMax()\r
+               {\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+#if MAINTAIN_EXTREMA\r
+                       return max;\r
+#else\r
+                       Node cursor = root, next = right(cursor);\r
+\r
+                       while (next != null)\r
+                       {\r
+                               cursor = next;\r
+                               next = right(cursor);\r
+                       }\r
+\r
+                       return cursor.item;\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove the largest item from this  priority queue.\r
+               /// </summary>\r
+               /// <returns>The removed item.</returns>\r
+               [Tested]\r
+               public T DeleteMax()\r
+               {\r
+                       //persistence guard?\r
+                       updatecheck();\r
+                       if (size == 0)\r
+                               throw new InvalidOperationException("Priority queue is empty");\r
+\r
+                       //We must follow the pattern of removeIterative()\r
+                       stackcheck();\r
+\r
+                       int level = 0;\r
+                       Node cursor = root;\r
+\r
+                       while (cursor.right != null)\r
+                       {\r
+                               dirs[level] = -1;\r
+                               path[level++] = cursor;\r
+                               cursor = cursor.right;\r
+                       }\r
+\r
+                       T retval = cursor.item;\r
+\r
+#if BAG\r
+                       if (cursor.items > 1)\r
+                       {\r
+                               resplicebag(level, cursor);\r
+                               size--;\r
+                               return retval;\r
+                       }\r
+#endif\r
+                       removeIterativePhase2(cursor, level);\r
+                       return retval;\r
+               }\r
+               #endregion\r
+\r
+               #region IPredecesorStructure<T> Members\r
+\r
+               /// <summary>\r
+               /// Find the strict predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than or equal to the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the predecessor for.</param>\r
+               /// <returns>The predecessor.</returns>\r
+               [Tested]\r
+               public T Predecessor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp < 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = right(cursor);\r
+                               }\r
+                               else if (comp == 0)\r
+                               {\r
+                                       cursor = left(cursor);\r
+                                       while (cursor != null)\r
+                                       {\r
+                                               bestsofar = cursor;\r
+                                               cursor = right(cursor);\r
+                                       }\r
+                               }\r
+                               else\r
+                                       cursor = left(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak predecessor in the sorted collection of a particular value,\r
+               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is less than the minimum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak predecessor for.</param>\r
+               /// <returns>The weak predecessor.</returns>\r
+               [Tested]\r
+               public T WeakPredecessor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp < 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = right(cursor);\r
+                               }\r
+                               else if (comp == 0)\r
+                                       return cursor.item;\r
+                               else\r
+                                       cursor = left(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the strict successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than or equal to the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the successor for.</param>\r
+               /// <returns>The successor.</returns>\r
+               [Tested]\r
+               public T Successor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp > 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = left(cursor);\r
+                               }\r
+                               else if (comp == 0)\r
+                               {\r
+                                       cursor = right(cursor);\r
+                                       while (cursor != null)\r
+                                       {\r
+                                               bestsofar = cursor;\r
+                                               cursor = left(cursor);\r
+                                       }\r
+                               }\r
+                               else\r
+                                       cursor = right(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Find the weak successor in the sorted collection of a particular value,\r
+               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
+               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
+               /// supplied  value is greater than the maximum of this collection.)\r
+               /// </summary>\r
+               /// <param name="item">The item to find the weak successor for.</param>\r
+               /// <returns>The weak successor.</returns>\r
+               [Tested]\r
+               public T WeakSuccessor(T item)\r
+               {\r
+                       Node cursor = root, bestsofar = null;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                int comp = comparer.Compare(cursor.item, item);\r
+\r
+                if (comp == 0)\r
+                                       return cursor.item;\r
+                               else if (comp > 0)\r
+                               {\r
+                                       bestsofar = cursor;\r
+                                       cursor = left(cursor);\r
+                               }\r
+                               else\r
+                                       cursor = right(cursor);\r
+                       }\r
+\r
+                       if (bestsofar != null)\r
+                               return bestsofar.item;\r
+                       else\r
+                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
+               }\r
+\r
+               #endregion\r
+               \r
+               #region ISorted<T> Members\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items greater than or equal to a supplied value.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeFrom(T bot)\r
+               { return new Range(this, true, bot, false, default(T), EnumerationDirection.Forwards); }\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items between two supplied values.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive).</param>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)\r
+               { return new Range(this, true, bot, true, top, EnumerationDirection.Forwards); }\r
+\r
+\r
+               /// <summary>\r
+               /// Query this sorted collection for items less than a supplied value.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive).</param>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeTo(T top)\r
+               { return new Range(this, false, default(T), true, top, EnumerationDirection.Forwards); }\r
+\r
+\r
+               /// <summary>\r
+               /// Create a directed collection with the same items as this collection.\r
+               /// </summary>\r
+               /// <returns>The result directed collection.</returns>\r
+               [Tested]\r
+               public IDirectedCollectionValue<T> RangeAll()\r
+               { return new Range(this, false, default(T), false, default(T), EnumerationDirection.Forwards); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot) { return RangeFrom(bot); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); }\r
+\r
+\r
+               [Tested]\r
+               IDirectedEnumerable<T> ISorted<T>.RangeTo(T top) { return RangeTo(top); }\r
+\r
+\r
+               //Utility for CountXxxx. Actually always called with strict = true.\r
+               private int countTo(T item, bool strict)\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new NotSupportedException("Indexing not supported for snapshots");\r
+#endif\r
+#if MAINTAIN_SIZE\r
+                       int ind = 0, comp = 0; Node next = root;\r
+\r
+                       while (next != null)\r
+                       {\r
+                comp = comparer.Compare(item, next.item);\r
+                if (comp < 0)\r
+                                       next = next.left;\r
+                               else\r
+                               {\r
+                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
+#if BAG\r
+                                       if (comp == 0)\r
+                                               return strict ? ind + leftcnt : ind + leftcnt + next.items;\r
+                                       else\r
+                                       {\r
+                                               ind = ind + next.items + leftcnt;\r
+                                               next = next.right;\r
+                                       }\r
+#else\r
+                                       if (comp == 0)\r
+                                               return strict ? ind + leftcnt : ind + leftcnt + 1;\r
+                                       else\r
+                                       {\r
+                                               ind = ind + 1 + leftcnt;\r
+                                               next = next.right;\r
+                                       }\r
+#endif\r
+                               }\r
+                       }\r
+\r
+                       //if we get here, we are at the same side of the whole collection:\r
+                       return ind;\r
+#else\r
+                       throw new NotSupportedException("Code compiled w/o size!");\r
+#endif\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Perform a search in the sorted collection for the ranges in which a\r
+               /// non-decreasing function from the item type to <code>int</code> is\r
+               /// negative, zero respectively positive. If the supplied cut function is\r
+               /// not non-decreasing, the result of this call is undefined.\r
+               /// </summary>\r
+               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
+               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
+               /// the <code>c.CompareTo(T that)</code> method.</param>\r
+               /// <param name="low">Returns the largest item in the collection, where the\r
+               /// cut function is negative (if any).</param>\r
+               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
+               /// on this collection.</param>\r
+               /// <param name="high">Returns the least item in the collection, where the\r
+               /// cut function is positive (if any).</param>\r
+               /// <param name="highIsValid">True if the cut function is positive somewhere\r
+               /// on this collection.</param>\r
+               /// <returns></returns>\r
+               [Tested]\r
+               public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)\r
+               {\r
+                       Node cursor = root, lbest = null, rbest = null;\r
+                       bool res = false;\r
+\r
+                       while (cursor != null)\r
+                       {\r
+                               int comp = c.CompareTo(cursor.item);\r
+\r
+                               if (comp > 0)\r
+                               {\r
+                                       lbest = cursor;\r
+                                       cursor = right(cursor);\r
+                               }\r
+                               else if (comp < 0)\r
+                               {\r
+                                       rbest = cursor;\r
+                                       cursor = left(cursor);\r
+                               }\r
+                               else\r
+                               {\r
+                                       res = true;\r
+\r
+                                       Node tmp = left(cursor);\r
+\r
+                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
+                                               tmp = left(tmp);\r
+\r
+                                       if (tmp != null)\r
+                                       {\r
+                                               lbest = tmp;\r
+                                               tmp = right(tmp);\r
+                                               while (tmp != null)\r
+                                               {\r
+                                                       if (c.CompareTo(tmp.item) > 0)\r
+                                                       {\r
+                                                               lbest = tmp;\r
+                                                               tmp = right(tmp);\r
+                                                       }\r
+                                                       else\r
+                                                               tmp = left(tmp);\r
+                                               }\r
+                                       }\r
+\r
+                                       tmp = right(cursor);\r
+                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
+                                               tmp = right(tmp);\r
+\r
+                                       if (tmp != null)\r
+                                       {\r
+                                               rbest = tmp;\r
+                                               tmp = left(tmp);\r
+                                               while (tmp != null)\r
+                                               {\r
+                                                       if (c.CompareTo(tmp.item) < 0)\r
+                                                       {\r
+                                                               rbest = tmp;\r
+                                                               tmp = left(tmp);\r
+                                                       }\r
+                                                       else\r
+                                                               tmp = right(tmp);\r
+                                               }\r
+                                       }\r
+\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (highIsValid = (rbest != null))\r
+                               high = rbest.item;\r
+                       else\r
+                               high = default(T);\r
+\r
+                       if (lowIsValid = (lbest != null))\r
+                               low = lbest.item;\r
+                       else\r
+                               low = default(T);\r
+\r
+                       return res;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items at or above a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountFrom(T bot) { return size - countTo(bot, true); }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="bot">The lower bound (inclusive)</param>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountFromTo(T bot, T top)\r
+               {\r
+            if (comparer.Compare(bot, top) >= 0)\r
+                return 0;\r
+\r
+                       return countTo(top, true) - countTo(bot, true);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Determine the number of items below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="top">The upper bound (exclusive)</param>\r
+               /// <returns>The number of matcing items.</returns>\r
+               [Tested]\r
+               public int CountTo(T top) { return countTo(top, true); }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection above or at a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeFrom(T low)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int count = CountFrom(low);\r
+\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       for (int i = 0; i < count; i++)\r
+                               DeleteMax();\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection between two supplied thresholds.\r
+               /// </summary>\r
+               /// <param name="low">The lower threshold (inclusive).</param>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeFromTo(T low, T hi)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int count = CountFromTo(low, hi);\r
+\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       for (int i = 0; i < count; i++)\r
+                               Remove(Predecessor(hi));\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Remove all items of this collection below a supplied threshold.\r
+               /// </summary>\r
+               /// <param name="hi">The upper threshold (exclusive).</param>\r
+               [Tested]\r
+               public void RemoveRangeTo(T hi)\r
+               {\r
+                       updatecheck();\r
+\r
+                       int count = CountTo(hi);\r
+\r
+                       if (count == 0)\r
+                               return;\r
+\r
+                       for (int i = 0; i < count; i++)\r
+                               DeleteMin();\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region IPersistent<T> Members\r
+\r
+               private bool disposed;\r
+\r
+\r
+\r
+               /// <summary>\r
+               /// If this tree is a snapshot, remove registration in base tree\r
+               /// </summary>\r
+               [Tested]\r
+               public void Dispose()\r
+               {\r
+                       Dispose(true);\r
+                       GC.SuppressFinalize(this);\r
+               }\r
+\r
+\r
+               private void Dispose(bool disposing)\r
+               {\r
+                       if (!disposed)\r
+                       {\r
+                               if (disposing) { }\r
+#if NCP\r
+                               if (isSnapShot)\r
+                               {\r
+                                       snapdata.Remove(generation, disposing);\r
+                                       snapdata = null;\r
+                                       root = null;\r
+                                       dirs = null;\r
+                                       path = null;\r
+                                       comparer = null;\r
+                                       disposed = true;\r
+                               }\r
+                               else { }\r
+#endif\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// If this tree is a snapshot, remove registration in base tree\r
+               /// </summary>\r
+               ~TreeBag()\r
+               {\r
+                       Dispose(false);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Make a (read-only) snap shot of this collection.\r
+               /// </summary>\r
+               /// <returns>The snap shot.</returns>\r
+               [Tested]\r
+               public ISorted<T> Snapshot()\r
+               {\r
+#if NCP\r
+                       if (isSnapShot)\r
+                               throw new InvalidOperationException("Cannot snapshot a snapshot");\r
+\r
+                       if (snapdata == null)\r
+                       {\r
+                               snapdata = new SnapData(this);\r
+                       }\r
+\r
+                       snapdata.Add(generation, this);\r
+\r
+                       TreeBag<T> res = (TreeBag<T>)MemberwiseClone();\r
+\r
+                       res.isReadOnly = true; res.isSnapShot = true;\r
+                       maxsnapid = generation++;\r
+                       return res;\r
+#endif\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region Snapdata nested class\r
+               //In a class by itself: the tree itself and snapshots must have a ref to \r
+               //the snapids, but we do not want snapshots to have a (strong) ref to the full\r
+               //updatable tree, which should be garbagecollectable even if there are still \r
+               //live snapshots!\r
+               //\r
+               //Access to SnapData should be thread safe since we expect finalisers \r
+               //of snapshots to remove a snapid that is garbagecollected without \r
+               //having been explicitly Disposed. Therefore we access SnapData through \r
+               //synchronized method/properties.\r
+\r
+#if NCP\r
+               class SnapData\r
+               {\r
+                       TreeBag<int> snapids = new TreeBag<int>(new IC());\r
+\r
+                       WeakReference master;\r
+\r
+\r
+                       internal SnapData(TreeBag<T> tree)\r
+                       {\r
+                               master = new WeakReference(tree);\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       public bool Add(int i, TreeBag<T> tree)\r
+                       {\r
+                               lock (this)\r
+                               {\r
+                                       bool res = snapids.Add(i);\r
+\r
+                                       //assert the following will be i:\r
+                                       tree.maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
+                                       return res;\r
+                               }\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       public bool Remove(int i, bool updmaxsnapid)\r
+                       {\r
+                               lock (this)\r
+                               {\r
+                                       bool res = snapids.Remove(i);\r
+\r
+                                       if (updmaxsnapid)\r
+                                       {\r
+                                               //Is this safe or/and overkill?\r
+                                               object t = master.Target;\r
+\r
+                                               if (t != null && master.IsAlive)\r
+                                               {\r
+                                                       ((TreeBag<T>)t).maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
+                                               }\r
+                                       }\r
+\r
+                                       return res;\r
+                               }\r
+                       }\r
+               }\r
+\r
+#endif\r
+               #endregion\r
+\r
+               #region TreeBag.Range nested class\r
+                       \r
+               internal class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
+               {\r
+                       //We actually need exclusive upper and lower bounds, and flags to \r
+                       //indicate whether the bound is present (we canot rely on default(T))\r
+                       private int stamp;\r
+\r
+                       private TreeBag<T> basis;\r
+\r
+                       private T lowend, highend;\r
+\r
+                       private bool haslowend, hashighend;\r
+\r
+                       EnumerationDirection direction;\r
+\r
+\r
+                       [Tested]\r
+                       public Range(TreeBag<T> basis, bool haslowend, T lowend, bool hashighend, T highend, EnumerationDirection direction)\r
+                       {\r
+                               this.basis = basis;\r
+                               stamp = basis.stamp;\r
+\r
+                               //lowind will be const; should we cache highind?\r
+                               this.lowend = lowend; //Inclusive\r
+                               this.highend = highend;//Exclusive\r
+                               this.haslowend = haslowend;\r
+                               this.hashighend = hashighend;\r
+                               this.direction = direction;\r
+                       }\r
+                       #region IEnumerable<T> Members\r
+\r
+\r
+                       #region TreeBag.Range.Enumerator nested class\r
+                       \r
+                       public class Enumerator: MSG.IEnumerator<T>\r
+                       {\r
+                               #region Private Fields\r
+                               private bool valid = false, ready = true;\r
+\r
+                               private IComparer<T> comparer;\r
+\r
+                               private T current;\r
+#if BAG\r
+                               int togo;\r
+#endif\r
+\r
+                               private Node cursor;\r
+\r
+                               private Node[] path; // stack of nodes\r
+\r
+                               private int level = 0;\r
+\r
+                               private Range range;\r
+\r
+                               private bool forwards;\r
+\r
+                               #endregion\r
+                               [Tested]\r
+                               public Enumerator(Range range)\r
+                               {\r
+                                       comparer = range.basis.comparer;\r
+                                       path = new Node[2 * range.basis.blackdepth];\r
+                                       this.range = range;\r
+                                       forwards = range.direction == EnumerationDirection.Forwards;\r
+                                       cursor = new Node();\r
+                                       if (forwards)\r
+                                               cursor.right = range.basis.root;\r
+                                       else\r
+                                               cursor.left = range.basis.root;\r
+                                       range.basis.modifycheck(range.stamp);\r
+                               }\r
+\r
+\r
+                               int compare(T i1, T i2) { return comparer.Compare(i1, i2); }\r
+\r
+\r
+                               /// <summary>\r
+                               /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
+                               /// </summary>\r
+                               /// <value>The current value of the enumerator.</value>\r
+                               [Tested]\r
+                               public T Current\r
+                               {\r
+                                       [Tested]\r
+                                       get\r
+                                       {\r
+                                               if (valid)\r
+                                                       return current;\r
+                                               else\r
+                                                       throw new InvalidOperationException();\r
+                                       }\r
+                               }\r
+\r
+\r
+                               //Maintain a stack of nodes that are roots of\r
+                               //subtrees not completely exported yet. Invariant:\r
+                               //The stack nodes together with their right subtrees\r
+                               //consists of exactly the items we have not passed\r
+                               //yet (the top of the stack holds current item).\r
+                               /// <summary>\r
+                               /// Move enumerator to next item in tree, or the first item if\r
+                               /// this is the first call to MoveNext. \r
+                               /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
+                               /// </summary>\r
+                               /// <returns>True if enumerator is valid now</returns>\r
+                               [Tested]\r
+                               public bool MoveNext()\r
+                               {\r
+                                       range.basis.modifycheck(range.stamp);\r
+                                       if (!ready)\r
+                                               return false;\r
+#if BAG\r
+                                       if (--togo> 0)\r
+                                               return true;\r
+#endif\r
+                                       if (forwards)\r
+                                       {\r
+                                               if (!valid && range.haslowend)\r
+                                               {\r
+                                                       cursor = cursor.right;\r
+                                                       while (cursor != null)\r
+                                                       {\r
+                                                               int comp = compare(cursor.item, range.lowend);\r
+\r
+                                                               if (comp > 0)\r
+                                                               {\r
+                                                                       path[level++] = cursor;\r
+#if NCP\r
+                                                                       cursor = range.basis.left(cursor);\r
+#else\r
+                                                                       cursor = cursor.left;\r
+#endif\r
+                                                               }\r
+                                                               else if (comp < 0)\r
+                                                               {\r
+#if NCP\r
+                                                                       cursor = range.basis.right(cursor);\r
+#else\r
+                                                                       cursor = cursor.right;\r
+#endif\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       path[level] = cursor;\r
+                                                                       break;\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       if (cursor == null)\r
+                                                       {\r
+                                                               if (level == 0)\r
+                                                                       return valid = ready = false;\r
+                                                               else\r
+                                                                       cursor = path[--level];\r
+                                                       }\r
+                                               }\r
+#if NCP\r
+                                               else if (range.basis.right(cursor) != null)\r
+                                               {\r
+                                                       path[level] = cursor = range.basis.right(cursor);\r
+\r
+                                                       Node next = range.basis.left(cursor);\r
+\r
+                                                       while (next != null)\r
+                                                       {\r
+                                                               path[++level] = cursor = next;\r
+                                                               next = range.basis.left(cursor);\r
+                                                       }\r
+                                               }\r
+#else\r
+                                               else if (cursor.right != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.right;\r
+                                                       while (cursor.left != null)\r
+                                                               path[++level] = cursor = cursor.left;\r
+                                               }\r
+#endif\r
+                                               else if (level == 0)\r
+                                                       return valid = ready = false;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+                                               if (range.hashighend && compare(current, range.highend) >= 0)\r
+                                                       return valid = ready = false;\r
+\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                               return valid = true;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (!valid && range.hashighend)\r
+                                               {\r
+                                                       cursor = cursor.left;\r
+                                                       while (cursor != null)\r
+                                                       {\r
+                                                               int comp = compare(cursor.item, range.highend);\r
+\r
+                                                               if (comp < 0)\r
+                                                               {\r
+                                                                       path[level++] = cursor;\r
+#if NCP\r
+                                                                       cursor = range.basis.right(cursor);\r
+#else\r
+                                                                       cursor = cursor.right;\r
+#endif\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+#if NCP\r
+                                                                       cursor = range.basis.left(cursor);\r
+#else\r
+                                                                       cursor = cursor.left;\r
+#endif\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       if (cursor == null)\r
+                                                       {\r
+                                                               if (level == 0)\r
+                                                                       return valid = ready = false;\r
+                                                               else\r
+                                                                       cursor = path[--level];\r
+                                                       }\r
+                                               }\r
+#if NCP\r
+                                               else if (range.basis.left(cursor) != null)\r
+                                               {\r
+                                                       path[level] = cursor = range.basis.left(cursor);\r
+\r
+                                                       Node next = range.basis.right(cursor);\r
+\r
+                                                       while (next != null)\r
+                                                       {\r
+                                                               path[++level] = cursor = next;\r
+                                                               next = range.basis.right(cursor);\r
+                                                       }\r
+                                               }\r
+#else\r
+                                               else if (cursor.left != null)\r
+                                               {\r
+                                                       path[level] = cursor = cursor.left;\r
+                                                       while (cursor.right != null)\r
+                                                               path[++level] = cursor = cursor.right;\r
+                                               }\r
+#endif\r
+                                               else if (level == 0)\r
+                                                       return valid = ready = false;\r
+                                               else\r
+                                                       cursor = path[--level];\r
+\r
+                                               current = cursor.item;\r
+                                               if (range.haslowend && compare(current, range.lowend) < 0)\r
+                                                       return valid = ready = false;\r
+\r
+#if BAG\r
+                                               togo = cursor.items;\r
+#endif\r
+                                               return valid = true;\r
+                                       }\r
+                               }\r
+\r
+                               void SC.IEnumerator.Reset ()\r
+                               {\r
+                                       throw new NotImplementedException ();\r
+                               }\r
+\r
+                               object SC.IEnumerator.Current {\r
+                                       get {\r
+                                               return Current;\r
+                                       }\r
+                               }\r
+\r
+                               [Tested]\r
+                               public void Dispose()\r
+                               {\r
+                                       comparer = null;\r
+                                       current = default(T);\r
+                                       cursor = null;\r
+                                       path = null;\r
+                                       range = null;\r
+                               }\r
+                       }\r
+\r
+                       #endregion\r
+\r
+                       [Tested]\r
+                       public override MSG.IEnumerator<T> GetEnumerator() { return new Enumerator(this); }\r
+\r
+\r
+                       [Tested]\r
+                       public EnumerationDirection Direction { [Tested]get { return direction; } }\r
+\r
+\r
+                       #endregion\r
+\r
+                       #region Utility\r
+                       \r
+                       bool inside(T item)\r
+                       {\r
+                return (!haslowend || basis.comparer.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer.Compare(item, highend) < 0);\r
+            }\r
+\r
+\r
+                       void checkstamp()\r
+                       {\r
+                               if (stamp < basis.stamp)\r
+                                       throw new InvalidOperationException("Base collection was modified behind my back!");\r
+                       }\r
+\r
+\r
+                       void syncstamp() { stamp = basis.stamp; }\r
+                       \r
+                       #endregion\r
+\r
+                       [Tested]\r
+                       public IDirectedCollectionValue<T> Backwards()\r
+                       {\r
+                               Range b = (Range)MemberwiseClone();\r
+\r
+                               b.direction = direction == EnumerationDirection.Forwards ? EnumerationDirection.Backwards : EnumerationDirection.Forwards;\r
+                               return b;\r
+                       }\r
+\r
+\r
+                       [Tested]\r
+                       IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+\r
+                       [Tested]\r
+                       public override int Count\r
+                       {\r
+                               [Tested]\r
+                               get\r
+                               {\r
+                                       return haslowend ? (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : (hashighend ? basis.CountTo(highend) : basis.Count);\r
+                               }\r
+                       }\r
+\r
+            //TODO: check that this is correct\r
+            public override Speed CountSpeed { get { return Speed.Log; } }\r
+\r
+        }\r
+\r
+               #endregion\r
+\r
+               #region fixheight utility\r
+\r
+#if MAINTAIN_HEIGHT\r
+               public void fixheight(Node n)\r
+               {\r
+                       int lh = n.left == null ? 0 : n.left.height + 1;\r
+                       int rh = n.right == null ? 0 : n.right.height + 1;\r
+\r
+                       n.height = (short)(lh > rh ? lh : rh);\r
+               }\r
+#endif\r
+\r
+               #endregion\r
+\r
+               #region Diagnostics\r
+               /// <summary>\r
+               /// Display this node on the console, and recursively its subnodes.\r
+               /// </summary>\r
+               /// <param name="n">Node to display</param>\r
+               /// <param name="space">Indentation</param>\r
+               private void minidump(Node n, string space)\r
+               {\r
+                       if (n == null)\r
+                       {\r
+                               //      System.Console.WriteLine(space + "null");\r
+                       }\r
+                       else\r
+                       {\r
+                               minidump(n.right, space + "  ");\r
+                               Console.WriteLine(String.Format("{0} {4} (rank={5}, size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, \r
+#if MAINTAIN_SIZE\r
+                               n.size, \r
+#else\r
+                               0,\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               n.height, \r
+#else\r
+                               0,\r
+#endif\r
+#if NCP\r
+                               n.generation, \r
+#endif\r
+                               n.red ? "RED" : "BLACK", \r
+#if MAINTAIN_RANK\r
+                               n.rank, \r
+#else\r
+                               0,\r
+#endif\r
+#if TRACE_ID\r
+                                       n.id,\r
+#else\r
+                               0,\r
+#endif\r
+#if NCP\r
+#if SEPARATE_EXTRA\r
+                               n.extra == null ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.extra.lastgeneration, n.extra.leftnode ? "L" : "R", n.extra.oldref == null ? "()" : "" + n.extra.oldref.item),\r
+#else\r
+                               n.lastgeneration == -1 ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item),\r
+#endif\r
+#else\r
+                               "",\r
+#endif\r
+#if BAG\r
+                               n.items\r
+#else\r
+                               1\r
+#endif\r
+                               ));\r
+                               minidump(n.left, space + "  ");\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Print the tree structure to the console stdout.\r
+               /// </summary>\r
+               [Tested(via = "Sawtooth")]\r
+               public void dump() { dump(""); }\r
+\r
+\r
+               /// <summary>\r
+               /// Print the tree structure to the console stdout.\r
+               /// </summary>\r
+               [Tested(via = "Sawtooth")]\r
+               public void dump(string msg)\r
+               {\r
+                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
+#if MAINTAIN_HEIGHT\r
+                       depth\r
+#else\r
+                       0\r
+#endif\r
+                       , \r
+#if NCP\r
+                       generation\r
+#endif\r
+                       ));\r
+                       minidump(root, "");\r
+                       check("", Console.Out); Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Display this tree on the console.\r
+               /// </summary>\r
+               /// <param name="msg">Identifying string of this call to dump</param>\r
+               /// <param name="err">Extra (error)message to include</param>\r
+               void dump(string msg, string err)\r
+               {\r
+                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
+#if MAINTAIN_HEIGHT\r
+                       depth\r
+#else\r
+                       0\r
+#endif\r
+                       ,  \r
+#if NCP\r
+                       generation                              \r
+#endif\r
+                       ));\r
+                       minidump(root, ""); Console.Write(err);\r
+                       Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Print warning m on o if b is false.\r
+               /// </summary>\r
+               /// <param name="b">Condition that should hold</param>\r
+               /// <param name="n">Place (used for id display)</param>\r
+               /// <param name="m">Message</param>\r
+               /// <param name="o">Output stream</param>\r
+               /// <returns>b</returns>\r
+               bool massert(bool b, Node n, string m, System.IO.TextWriter o)\r
+               {\r
+                       if (!b) o.WriteLine("*** Node (item={0}, id={1}): {2}", n.item, \r
+#if TRACE_ID\r
+                               n.id\r
+#else\r
+                               0\r
+#endif\r
+                               , m);\r
+\r
+                       return b;\r
+               }\r
+\r
+\r
+               bool rbminicheck(Node n, bool redp, int prank, System.IO.TextWriter o, out T min, out T max, out int blackheight, int maxgen)\r
+               {//Red-Black invariant\r
+                       bool res = true;\r
+\r
+                       res = massert(!(n.red && redp), n, "RED parent of RED node", o) && res;\r
+                       res = massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty", o) && res;\r
+                       res = massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty", o) && res;\r
+#if MAINTAIN_RANK\r
+                       res = massert(n.red == (n.rank == prank), n, "Bad color", o) && res;\r
+                       res = massert(prank <= n.rank + 1, n, "Parentrank-rank >= 2", o) && res;\r
+                       res = massert((n.left != null && n.right != null) || n.rank == 1, n, "Rank>1 but empty child", o) && res;\r
+#endif\r
+#if BAG\r
+                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
+\r
+                       res = massert(sb, n, "Bad size", o) && res;\r
+#elif MAINTAIN_SIZE\r
+                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
+\r
+                       res = massert(sb, n, "Bad size", o) && res;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                       int lh = n.left == null ? 0 : n.left.height + 1;\r
+                       int rh = n.right == null ? 0 : n.right.height + 1;\r
+\r
+                       res = massert(n.height == (lh < rh ? rh : lh), n, "Bad height", o) && res;\r
+#endif\r
+                       int therank =\r
+#if MAINTAIN_RANK\r
+                       n.rank;\r
+#else\r
+                       0;\r
+#endif\r
+                       min = max = n.item;\r
+\r
+                       T otherext;\r
+                       int lbh = 0, rbh = 0;\r
+\r
+                       if (n.left != null)\r
+                       {\r
+                               res = rbminicheck(n.left, n.red, therank, o, out min, out otherext, out lbh, generation) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
+            }\r
+\r
+                       if (n.right != null)\r
+                       {\r
+                               res = rbminicheck(n.right, n.red, therank, o, out otherext, out max, out rbh, generation) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
+            }\r
+\r
+                       res = massert(rbh == lbh, n, "Different blackheights of children", o) && res;\r
+                       blackheight = n.red ? rbh : rbh + 1;\r
+#if MAINTAIN_RANK\r
+                       //The rank is the number of black nodes from this one to\r
+                       //the leaves, not counting this one, but counting 1 for the empty\r
+                       //virtual leaf nodes.\r
+                       res = massert(n.rank == rbh + 1, n, "rank!=blackheight " + blackheight, o) && res;\r
+#endif\r
+                       return res;\r
+               }\r
+\r
+\r
+\r
+\r
+#if NCP\r
+\r
+               bool rbminisnapcheck(Node n, System.IO.TextWriter o, out int size, out T min, out T max)\r
+               {\r
+                       bool res = true;\r
+\r
+                       min = max = n.item;\r
+\r
+                       int lsz = 0, rsz = 0;\r
+                       T otherext;\r
+#if SEPARATE_EXTRA\r
+                       Node.Extra extra = n.extra;\r
+                       Node child = (extra != null && extra.lastgeneration >= treegen && extra.leftnode) ? extra.oldref : n.left;\r
+#else\r
+                       Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left;\r
+#endif\r
+                       if (child != null)\r
+                       {\r
+                               res = rbminisnapcheck(child, o, out lsz, out min, out otherext) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
+            }\r
+\r
+#if SEPARATE_EXTRA\r
+                       child = (extra != null && extra.lastgeneration >= treegen && !extra.leftnode) ? extra.oldref : n.right;\r
+#else\r
+                       child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right;\r
+#endif\r
+                       if (child != null)\r
+                       {\r
+                               res = rbminisnapcheck(child, o, out rsz, out otherext, out max) && res;\r
+                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
+            }\r
+#if BAG\r
+                       size = n.items + lsz + rsz;\r
+#else\r
+                       size = 1 + lsz + rsz;\r
+#endif\r
+                       return res;\r
+               }\r
+#endif\r
+\r
+               /// <summary>\r
+               /// Checks red-black invariant. Dumps tree to console if bad\r
+               /// </summary>\r
+               /// <param name="name">Title of dump</param>\r
+               /// <returns>false if invariant violation</returns>\r
+               [Tested(via = "Sawtooth")]\r
+               public bool Check(string name)\r
+               {\r
+                       System.Text.StringBuilder e = new System.Text.StringBuilder();\r
+                       System.IO.TextWriter o = new System.IO.StringWriter(e);\r
+\r
+                       if (!check(name, o))\r
+                               return true;\r
+                       else\r
+                       {\r
+                               dump(name, e.ToString());\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Checks red-black invariant. Dumps tree to console if bad\r
+               /// </summary>\r
+               /// <returns>false if invariant violation</returns>\r
+               [Tested]\r
+               public bool Check()\r
+               {\r
+                       //return check("", System.IO.TextWriter.Null);\r
+                       //Console.WriteLine("bamse");\r
+                       return Check("-");\r
+               }\r
+\r
+\r
+               bool check(string msg, System.IO.TextWriter o)\r
+               {\r
+                       if (root != null)\r
+                       {\r
+                               T max, min;\r
+                               int blackheight;\r
+#if NCP\r
+                               if (isSnapShot)\r
+                               {\r
+                                       //Console.WriteLine("Im'a snapshot");\r
+                                       int thesize;\r
+                                       bool rv = rbminisnapcheck(root, o, out thesize, out min, out max);\r
+\r
+                                       rv = massert(size == thesize, root, "bad snapshot size", o) && rv;\r
+                                       return !rv;\r
+                               }\r
+#endif\r
+#if MAINTAIN_RANK\r
+                               bool res = rbminicheck(root, false, root.rank + 1, o, out min, out max, out blackheight, generation);\r
+\r
+                               res = massert(root.rank == blackdepth, root, "blackdepth!=root.rank", o) && res;\r
+#else\r
+                               bool res = rbminicheck(root, false, 0, o, out min, out max, out blackheight, generation);\r
+#endif\r
+                               res = massert(blackheight == blackdepth, root, "bad blackh/d", o) && res;\r
+                               res = massert(!root.red, root, "root is red", o) && res;\r
+#if MAINTAIN_SIZE\r
+                               res = massert(root.size == size, root, "count!=root.size", o) && res;\r
+#endif\r
+#if MAINTAIN_HEIGHT\r
+                               res = massert(root.height == depth, root, "depth!=root.height", o) && res;\r
+#endif\r
+                               return !res;\r
+                       }\r
+                       else\r
+                               return false;\r
+               }\r
+               #endregion                      \r
+       }\r
+}\r
+\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/trees/TreeDictionary.cs b/mcs/class/Mono.C5/C5/trees/TreeDictionary.cs
new file mode 100644 (file)
index 0000000..6194c20
--- /dev/null
@@ -0,0 +1,136 @@
+#if NET_2_0\r
+/*\r
+ Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ of this software and associated documentation files (the "Software"), to deal\r
+ in the Software without restriction, including without limitation the rights\r
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ copies of the Software, and to permit persons to whom the Software is\r
+ furnished to do so, subject to the following conditions:\r
\r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ SOFTWARE.\r
+*/\r
+\r
+using System;\r
+using MSG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+       /// <summary>\r
+       /// A sorted generic dictionary based on a red-black tree set.\r
+       /// </summary>\r
+       public class TreeDictionary<K,V>: DictionaryBase<K,V>, IDictionary<K,V>, ISortedDictionary<K,V>\r
+       {\r
+               #region Fields\r
+\r
+               private TreeSet<KeyValuePair<K,V>> sortedpairs;\r
+\r
+               #endregion\r
+\r
+               #region Constructors\r
+\r
+               /// <summary>\r
+               /// Create a red-black tree dictionary using the natural comparer for keys.\r
+               /// <exception cref="ArgumentException"/> if the key type K is not comparable.\r
+               /// </summary>\r
+               public TreeDictionary() : this(ComparerBuilder.FromComparable<K>.Examine()) { }\r
+\r
+               /// <summary>\r
+               /// Create a red-black tree dictionary using an external comparer for keys.\r
+               /// </summary>\r
+               /// <param name="c">The external comparer</param>\r
+               public TreeDictionary(IComparer<K> c)\r
+               {\r
+                       pairs = sortedpairs = new TreeSet<KeyValuePair<K,V>>(new KeyValuePairComparer<K,V>(c));\r
+               }\r
+\r
+               #endregion\r
+\r
+               #region ISortedDictionary<K,V> Members\r
+\r
+               /// <summary>\r
+               /// Get the entry in the dictionary whose key is the\r
+               /// predecessor of a specified key.\r
+               /// </summary>\r
+               /// <param name="key">The key</param>\r
+               /// <returns>The entry</returns>\r
+               [Tested]\r
+               public KeyValuePair<K,V> Predecessor(K key)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       return sortedpairs.Predecessor(p);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get the entry in the dictionary whose key is the\r
+               /// weak predecessor of a specified key.\r
+               /// </summary>\r
+               /// <param name="key">The key</param>\r
+               /// <returns>The entry</returns>\r
+               [Tested]\r
+               public KeyValuePair<K,V> WeakPredecessor(K key)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       return sortedpairs.WeakPredecessor(p);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get the entry in the dictionary whose key is the\r
+               /// successor of a specified key.\r
+               /// </summary>\r
+               /// <param name="key">The key</param>\r
+               /// <returns>The entry</returns>\r
+               [Tested]\r
+               public KeyValuePair<K,V> Successor(K key)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       return sortedpairs.Successor(p);\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Get the entry in the dictionary whose key is the\r
+               /// weak successor of a specified key.\r
+               /// </summary>\r
+               /// <param name="key">The key</param>\r
+               /// <returns>The entry</returns>\r
+               [Tested]\r
+               public KeyValuePair<K,V> WeakSuccessor(K key)\r
+               {\r
+                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
+\r
+                       return sortedpairs.WeakSuccessor(p);\r
+               }\r
+\r
+               #endregion\r
+\r
+               //TODO: put in interface\r
+               /// <summary>\r
+               /// Make a snapshot of the current state of this dictionary\r
+               /// </summary>\r
+               /// <returns>The snapshot</returns>\r
+               [Tested]\r
+               public MSG.IEnumerable<KeyValuePair<K,V>> Snapshot()\r
+               {\r
+                       TreeDictionary<K,V> res = (TreeDictionary<K,V>)MemberwiseClone();\r
+\r
+                       res.pairs = (TreeSet<KeyValuePair<K,V>>)sortedpairs.Snapshot();\r
+                       return res;\r
+               }\r
+       }\r
+}\r
+#endif\r
diff --git a/mcs/class/Mono.C5/C5/trees/set2bag.pl b/mcs/class/Mono.C5/C5/trees/set2bag.pl
new file mode 100644 (file)
index 0000000..86de856
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl\r
+\r
+use strict;\r
+\r
+open(RBTS,"RedBlackTree.cs") || die "Can't open infile";\r
+\r
+rename "RedBlackTreeBag.cs", "RedBlackTreeBag.cs.old" || die "Can't backup";\r
+\r
+open(RBTB,">RedBlackTreeBag.cs")  || die "Can't open outfile";\r
+\r
+my @cond=(1);\r
+my $printing = 1;\r
+\r
+#Assume all conditions on BAG symbol is '#if BAG'\r
+while (<RBTS>) {\r
+  if (/^#define BAG/) {\r
+    print RBTB "#define BAG\r\n";\r
+    next;\r
+  }\r
+  s/TreeSet/TreeBag/g;\r
+  print RBTB;\r
+}\r
+\r
+close(RBTS) || die "Can't close infile";\r
+close(RBTB) || die "Can't close outfile";\r
index 7617ccc1f7ed830f2cd9ad79ec5d12811022ab46..371ca103fce40ee83d8aade8e48da1d203cdfbe3 100644 (file)
@@ -1,6 +1,10 @@
+2006-02-16  Martin Baulig  <martin@ximian.com>
+
+       * C5/: New directory containing all the source code.
+
 2005-07-10  Kamil Skalski <nazgul@nemerle.org>
 
-       * Builder.cs: Use MakeGenericType instead of BindGenericParameters.
+       * C5/Builder.cs: Use MakeGenericType instead of BindGenericParameters.
 
 2005-06-27  Ben Maurer  <bmaurer@ximian.com>
 
@@ -10,7 +14,7 @@
 
        Reflect latest API changes.
 
-       * Collections.cs (EnumerableBase): Explicitly implement
+       * C5/Collections.cs (EnumerableBase): Explicitly implement
        System.Collections.IEnumerable.GetEnumerator(). 
 
        * Makefile: Add `nowarn:169'.
 
 2004-11-19  Martin Baulig  <martin@ximian.com>
 
-       * Wrappers.cs: Removed all the FIXME's.  GMCS can now compile the
+       * C5/Wrappers.cs: Removed all the FIXME's.  GMCS can now compile the
        original, unmodified code :-)
 
 2004-11-12  Martin Baulig  <martin@ximian.com>
 
-       * Wrappers.cs: Added workaround for #69082.
+       * C5/Wrappers.cs: Added workaround for #69082.
 
-       * linkedlists/LinkedList.cs: Added workaround for bug #57747.
+       * C5/linkedlists/LinkedList.cs: Added workaround for bug #57747.
 
 2004-08-16  Martin Baulig  <martin@ximian.com>
 
diff --git a/mcs/class/Mono.C5/Collections.cs b/mcs/class/Mono.C5/Collections.cs
deleted file mode 100644 (file)
index d85f621..0000000
+++ /dev/null
@@ -1,1351 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// Direction of enumeration order relative to original collection.\r
-       /// </summary>\r
-       public enum EnumerationDirection { \r
-               /// <summary>\r
-               /// Same direction\r
-               /// </summary>\r
-               Forwards, \r
-               /// <summary>\r
-               /// Opposite direction\r
-               /// </summary>\r
-               Backwards \r
-       }\r
-\r
-       #region int stuff\r
-       class IC: IComparer<int>\r
-       {\r
-               [Tested]\r
-               public int Compare(int a, int b) { return a > b ? 1 : a < b ? -1 : 0; }\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A hasher for int32\r
-       /// </summary>\r
-       public class IntHasher: IHasher<int>\r
-       {\r
-               /// <summary>\r
-               /// Get the hash code of this integer, i.e. itself\r
-               /// </summary>\r
-               /// <param name="item">The integer</param>\r
-               /// <returns>The same</returns>\r
-               [Tested]\r
-               public int GetHashCode(int item) { return item; }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if two integers are equal\r
-               /// </summary>\r
-               /// <param name="i1">first integer</param>\r
-               /// <param name="i2">second integer</param>\r
-               /// <returns>True if equal</returns>\r
-               [Tested]\r
-               public bool Equals(int i1, int i2) { return i1 == i2; }\r
-       }\r
-\r
-\r
-       #endregion\r
-\r
-       #region Natural Comparers\r
-\r
-\r
-       /// <summary>\r
-       /// A natural generic IComparer for an IComparable&lt;T&gt; item type\r
-       /// </summary>\r
-       public class NaturalComparer<T>: IComparer<T>\r
-               where T: IComparable<T>\r
-       {\r
-               /// <summary>\r
-               /// Compare two items\r
-               /// </summary>\r
-               /// <param name="a">First item</param>\r
-               /// <param name="b">Second item</param>\r
-               /// <returns>a &lt;=&gt; b</returns>\r
-               [Tested]\r
-               public int Compare(T a, T b) { return a.CompareTo(b); }\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A natural generic IComparer for a System.IComparable item type\r
-       /// </summary>\r
-       public class NaturalComparerO<T>: IComparer<T>\r
-               where T: System.IComparable\r
-       {\r
-               /// <summary>\r
-               /// Compare two items\r
-               /// </summary>\r
-               /// <param name="a">First item</param>\r
-               /// <param name="b">Second item</param>\r
-               /// <returns>a &lt;=&gt; b</returns>\r
-               [Tested]\r
-               public int Compare(T a, T b) { return a.CompareTo(b); }\r
-       }\r
-\r
-\r
-\r
-       #endregion\r
-\r
-       #region Hashers\r
-       /// <summary>\r
-       /// The default item hasher for a reference type. A trivial wrapper for calling \r
-       /// the GetHashCode and Equals methods inherited from object.\r
-       ///\r
-       /// <p>Should only be instantiated with a reference type as generic type parameter. \r
-       /// This is asserted at instatiation time in Debug builds.</p>\r
-       /// </summary>\r
-       public sealed class DefaultReferenceTypeHasher<T>: IHasher<T>\r
-       {\r
-               static DefaultReferenceTypeHasher()\r
-               {\r
-                       Debug.Assert(!typeof(T).IsValueType, "DefaultReferenceTypeHasher instantiated with value type: " + typeof(T));\r
-               }\r
-               \r
-               /// <summary>\r
-               /// Get the hash code with respect to this item hasher\r
-               /// </summary>\r
-               /// <param name="item">The item</param>\r
-               /// <returns>The hash code</returns>\r
-               [Tested]\r
-               public int GetHashCode(T item) { return item.GetHashCode(); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if two items are equal with respect to this item hasher\r
-               /// </summary>\r
-               /// <param name="i1">first item</param>\r
-               /// <param name="i2">second item</param>\r
-               /// <returns>True if equal</returns>\r
-               [Tested]\r
-               public bool Equals(T i1, T i2)\r
-               {\r
-                       //For reference types, the (object) cast should be jitted as a noop. \r
-                       return (object)i1 == null ? (object)i2 == null : i1.Equals(i2);\r
-               }\r
-       }\r
-\r
-       /// <summary>\r
-       /// The default item hasher for a value type. A trivial wrapper for calling \r
-       /// the GetHashCode and Equals methods inherited from object.\r
-       ///\r
-       /// <p>Should only be instantiated with a value type as generic type parameter. \r
-       /// This is asserted at instatiation time in Debug builds.</p>\r
-       /// <p>We cannot add the constraint "where T : struct" to get a compile time check\r
-       /// because we need to instantiate this class in C5.HasherBuilder.ByPrototype[T].Examine()\r
-       /// with a T that is only known at runtime to be a value type!</p>\r
-       /// </summary>\r
-       \r
-    //Note: we could (now) add a constraint "where T : struct" to get a compile time check,\r
-    //but \r
-       public sealed class DefaultValueTypeHasher<T>: IHasher<T>\r
-       {\r
-               static DefaultValueTypeHasher()\r
-               {\r
-                       Debug.Assert(typeof(T).IsValueType, "DefaultValueTypeHasher instantiated with reference type: " + typeof(T));\r
-               }\r
-               /// <summary>\r
-               /// Get the hash code with respect to this item hasher\r
-               /// </summary>\r
-               /// <param name="item">The item</param>\r
-               /// <returns>The hash code</returns>\r
-               [Tested]\r
-               public int GetHashCode(T item) { return item.GetHashCode(); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if two items are equal with respect to this item hasher\r
-               /// </summary>\r
-               /// <param name="i1">first item</param>\r
-               /// <param name="i2">second item</param>\r
-               /// <returns>True if equal</returns>\r
-               [Tested]\r
-               public bool Equals(T i1, T i2) { return i1.Equals(i2); }\r
-       }\r
-\r
-       #endregion\r
-\r
-       #region Bases\r
-\r
-       /// <summary>\r
-       /// A base class for implementing an IEnumerable&lt;T&gt;\r
-       /// </summary>\r
-       public abstract class EnumerableBase<T>: MSG.IEnumerable<T>\r
-       {\r
-               /// <summary>\r
-               /// Create an enumerator for this collection.\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               public abstract MSG.IEnumerator<T> GetEnumerator();\r
-\r
-               System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()\r
-               {\r
-                       return GetEnumerator ();\r
-               }\r
-\r
-               /// <summary>\r
-               /// Count the number of items in an enumerable by enumeration\r
-               /// </summary>\r
-               /// <param name="items">The enumerable to count</param>\r
-               /// <returns>The size of the enumerable</returns>\r
-               protected static int countItems(MSG.IEnumerable<T> items)\r
-               {\r
-                       ICollectionValue<T> jtems = items as ICollectionValue<T>;\r
-\r
-                       if (jtems != null)\r
-                               return jtems.Count;\r
-\r
-                       int count = 0;\r
-\r
-                       using (MSG.IEnumerator<T> e = items.GetEnumerator())\r
-                               while (e.MoveNext()) count++;\r
-\r
-                       return count;\r
-               }\r
-       }\r
-\r
-\r
-       /// <summary>\r
-       /// Base class for classes implementing ICollectionValue[T]\r
-       /// </summary>\r
-       public abstract class CollectionValueBase<T>: EnumerableBase<T>, ICollectionValue<T>\r
-       {\r
-               //This forces our subclasses to make Count virtual!\r
-               /// <summary>\r
-               /// The number of items in this collection.\r
-               /// </summary>\r
-               /// <value></value>\r
-               public abstract int Count { get;}\r
-\r
-        /// <summary>\r
-        /// The value is symbolic indicating the type of asymptotic complexity\r
-        /// in terms of the size of this collection (worst-case or amortized as\r
-        /// relevant).\r
-        /// </summary>\r
-        /// <value>A characterization of the speed of the \r
-        /// <code>Count</code> property in this collection.</value>\r
-        public abstract Speed CountSpeed { get; }\r
-\r
-\r
-        /// <summary>\r
-               /// Copy the items of this collection to part of an array.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if i is negative.\r
-               /// <exception cref="ArgumentException"/> if the array does not have room for the items.\r
-               /// </summary>\r
-               /// <param name="a">The array to copy to</param>\r
-               /// <param name="i">The starting index.</param>\r
-               [Tested]\r
-               public virtual void CopyTo(T[] a, int i)\r
-               {\r
-                       if (i < 0)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       if (i + Count > a.Length)\r
-                               throw new ArgumentException();\r
-\r
-                       foreach (T item in this) a[i++] = item;\r
-               }\r
-\r
-        /// <summary>\r
-        /// Create an array with the items of this collection (in the same order as an\r
-        /// enumerator would output them).\r
-        /// </summary>\r
-        /// <returns>The array</returns>\r
-        //[Tested]\r
-        public virtual T[] ToArray()\r
-        {\r
-            T[] res = new T[Count];\r
-            int i = 0;\r
-\r
-            foreach (T item in this) res[i++] = item;\r
-\r
-            return res;\r
-        }\r
-\r
-        /// <summary>\r
-        /// Apply an Applier&lt;T&gt; to this enumerable\r
-        /// </summary>\r
-        /// <param name="a">The applier delegate</param>\r
-        [Tested]\r
-        public void Apply(Applier<T> a)\r
-        {\r
-            foreach (T item in this)\r
-                a(item);\r
-        }\r
-\r
-\r
-        /// <summary>\r
-        /// Check if there exists an item  that satisfies a\r
-        /// specific predicate in this collection.\r
-        /// </summary>\r
-        /// <param name="filter">A filter delegate \r
-        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
-        /// <returns>True is such an item exists</returns>\r
-        [Tested]\r
-        public bool Exists(Filter<T> filter)\r
-        {\r
-            foreach (T item in this)\r
-                if (filter(item))\r
-                    return true;\r
-\r
-            return false;\r
-        }\r
-\r
-\r
-        /// <summary>\r
-        /// Check if all items in this collection satisfies a specific predicate.\r
-        /// </summary>\r
-        /// <param name="filter">A filter delegate \r
-        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
-        /// <returns>True if all items satisfies the predicate</returns>\r
-        [Tested]\r
-        public bool All(Filter<T> filter)\r
-        {\r
-            foreach (T item in this)\r
-                if (!filter(item))\r
-                    return false;\r
-\r
-            return true;\r
-        }\r
-\r
-        /// <summary>\r
-        /// Create an enumerator for this collection.\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               public override abstract MSG.IEnumerator<T> GetEnumerator();\r
-       }\r
-\r
-\r
-       /// <summary>\r
-       /// Base class (abstract) for ICollection implementations.\r
-       /// </summary>\r
-       public abstract class CollectionBase<T>: CollectionValueBase<T>\r
-       {\r
-               #region Fields\r
-\r
-               object syncroot = new object();\r
-\r
-               /// <summary>\r
-               /// The underlying field of the ReadOnly property\r
-               /// </summary>\r
-               protected bool isReadOnly = false;\r
-\r
-               /// <summary>\r
-               /// The current stamp value\r
-               /// </summary>\r
-               protected int stamp;\r
-\r
-               /// <summary>\r
-               /// The number of items in the collection\r
-               /// </summary>\r
-               protected int size;\r
-\r
-               /// <summary>\r
-               /// The item hasher of the collection\r
-               /// </summary>\r
-               protected IHasher<T> itemhasher;\r
-\r
-               int iUnSequencedHashCode, iUnSequencedHashCodeStamp = -1;\r
-\r
-               #endregion\r
-               \r
-               #region Util\r
-\r
-               //protected bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }\r
-               /// <summary>\r
-               /// Utility method for range checking.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the start or count is negative\r
-               /// <exception cref="ArgumentException"/> if the range does not fit within collection size.\r
-               /// </summary>\r
-               /// <param name="start">start of range</param>\r
-               /// <param name="count">size of range</param>\r
-               [Tested]\r
-               protected void checkRange(int start, int count)\r
-               {\r
-                       if (start < 0 || count < 0)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       if (start + count > size)\r
-                               throw new ArgumentException();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Compute the unsequenced hash code of a collection\r
-               /// </summary>\r
-               /// <param name="items">The collection to compute hash code for</param>\r
-               /// <param name="itemhasher">The item hasher</param>\r
-               /// <returns>The hash code</returns>\r
-               [Tested]\r
-               public static int ComputeHashCode(ICollectionValue<T> items, IHasher<T> itemhasher)\r
-               {\r
-                       int h = 0;\r
-\r
-                       foreach (T item in items)\r
-                               h ^= itemhasher.GetHashCode(item);\r
-\r
-                       return (items.Count << 16) + h;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Examine if tit and tat are equal as unsequenced collections\r
-               /// using the specified item hasher (assumed compatible with the two collections).\r
-               /// </summary>\r
-               /// <param name="tit">The first collection</param>\r
-               /// <param name="tat">The second collection</param>\r
-               /// <param name="itemhasher">The item hasher to use for comparison</param>\r
-               /// <returns>True if equal</returns>\r
-               [Tested]\r
-               public static bool StaticEquals(ICollection<T> tit, ICollection<T> tat, IHasher<T> itemhasher)\r
-               {\r
-                       if (tat == null)\r
-                               return tit == null;\r
-\r
-                       if (tit.Count != tat.Count)\r
-                               return false;\r
-\r
-                       //This way we might run through both enumerations twice, but\r
-                       //probably not (if the hash codes are good)\r
-                       if (tit.GetHashCode() != tat.GetHashCode())\r
-                               return false;\r
-\r
-            if (!tit.AllowsDuplicates && (tat.AllowsDuplicates || tat.ContainsSpeed >= tit.ContainsSpeed))\r
-            {\r
-                //TODO: use foreach construction\r
-                               using (MSG.IEnumerator<T> dit = tit.GetEnumerator())\r
-                               {\r
-                                       while (dit.MoveNext())\r
-                                               if (!tat.Contains(dit.Current))\r
-                                                       return false;\r
-                               }\r
-                       }\r
-            else if (!tat.AllowsDuplicates)\r
-            {\r
-                               using (MSG.IEnumerator<T> dat = tat.GetEnumerator())\r
-                               {\r
-                                       while (dat.MoveNext())\r
-                                               if (!tit.Contains(dat.Current))\r
-                                                       return false;\r
-                               }\r
-                       }\r
-                       else\r
-                       {//both are bags, we only have a slow one\r
-                               //unless the bags are based on a fast T->int dictinary (tree or hash) \r
-                               using (MSG.IEnumerator<T> dat = tat.GetEnumerator())\r
-                               {\r
-                                       while (dat.MoveNext())\r
-                                       {\r
-                                               T item = dat.Current;\r
-\r
-                                               if (tit.ContainsCount(item) != tat.ContainsCount(item))\r
-                                                       return false;\r
-                                       }\r
-                               }\r
-                               //That was O(n^3) - completely unacceptable.\r
-                               //If we use an auxiliary bool[] we can do the comparison in O(n^2)\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get the unsequenced collection hash code of this collection: from the cached \r
-               /// value if present and up to date, else (re)compute.\r
-               /// </summary>\r
-               /// <returns>The hash code</returns>\r
-               protected int unsequencedhashcode()\r
-               {\r
-                       if (iUnSequencedHashCodeStamp == stamp)\r
-                               return iUnSequencedHashCode;\r
-\r
-                       iUnSequencedHashCode = ComputeHashCode(this, itemhasher);\r
-                       iUnSequencedHashCodeStamp = stamp;\r
-                       return iUnSequencedHashCode;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if the contents of that is equal to the contents of this\r
-               /// in the unsequenced sense. Using the item hasher of this collection.\r
-               /// </summary>\r
-               /// <param name="that">The collection to compare to.</param>\r
-               /// <returns>True if  equal</returns>\r
-               protected bool unsequencedequals(ICollection<T> that)\r
-               {\r
-                       return StaticEquals((ICollection<T>)this, that, itemhasher);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="InvalidOperationException"/> if this collection has been updated \r
-               /// since a target time\r
-               /// </summary>\r
-               /// <param name="thestamp">The stamp identifying the target time</param>\r
-               protected virtual void modifycheck(int thestamp)\r
-               {\r
-                       if (this.stamp != thestamp)\r
-                               throw new InvalidOperationException("Collection was modified");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if it is valid to perform update operations, and if so increment stamp\r
-               /// </summary>\r
-               protected virtual void updatecheck()\r
-               {\r
-                       if (isReadOnly)\r
-                               throw new InvalidOperationException("Collection cannot be modified through this guard object");\r
-\r
-                       stamp++;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IEditableCollection<T> members\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True if this collection is read only</value>\r
-               [Tested]\r
-               public bool IsReadOnly { [Tested]get { return isReadOnly; } }\r
-\r
-               #endregion\r
-\r
-               #region ICollection<T> members\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>The size of this collection</value>\r
-               [Tested]\r
-               public override int Count { [Tested]get { return size; } }\r
-\r
-        /// <summary>\r
-        /// The value is symbolic indicating the type of asymptotic complexity\r
-        /// in terms of the size of this collection (worst-case or amortized as\r
-        /// relevant).\r
-        /// </summary>\r
-        /// <value>A characterization of the speed of the \r
-        /// <code>Count</code> property in this collection.</value>\r
-        public override Speed CountSpeed { get { return Speed.Constant; } }\r
-\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> members\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>A distinguished object to use for locking to synchronize multithreaded access</value>\r
-               [Tested]\r
-               public object SyncRoot { get { return syncroot; } }\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True is this collection is empty</value>\r
-               [Tested]\r
-               public bool IsEmpty { [Tested]get { return size == 0; } }\r
-               #endregion\r
-\r
-               #region IEnumerable<T> Members\r
-               /// <summary>\r
-               /// Create an enumerator for this collection.\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               public override abstract MSG.IEnumerator<T> GetEnumerator();\r
-               #endregion\r
-       }\r
-\r
-\r
-       /// <summary>\r
-       /// Base class (abstract) for sequenced collection implementations.\r
-       /// </summary>\r
-       public abstract class SequencedBase<T>: CollectionBase<T>\r
-       {\r
-               #region Fields\r
-\r
-               int iSequencedHashCode, iSequencedHashCodeStamp = -1;\r
-\r
-               #endregion\r
-\r
-               #region Util\r
-\r
-               /// <summary>\r
-               /// Compute the unsequenced hash code of a collection\r
-               /// </summary>\r
-               /// <param name="items">The collection to compute hash code for</param>\r
-               /// <param name="itemhasher">The item hasher</param>\r
-               /// <returns>The hash code</returns>\r
-               [Tested]\r
-               public static int ComputeHashCode(ISequenced<T> items, IHasher<T> itemhasher)\r
-               {\r
-                       //NOTE: It must be possible to devise a much stronger combined hashcode, \r
-                       //but unfortunately, it has to be universal. OR we could use a (strong)\r
-                       //family and initialise its parameter randomly at load time of this class!\r
-                       //(We would not want to have yet a flag to check for invalidation?!)\r
-                       int iIndexedHashCode = 0;\r
-\r
-                       foreach (T item in items)\r
-                               iIndexedHashCode = iIndexedHashCode * 31 + itemhasher.GetHashCode(item);\r
-\r
-                       return iIndexedHashCode;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Examine if tit and tat are equal as sequenced collections\r
-               /// using the specified item hasher (assumed compatible with the two collections).\r
-               /// </summary>\r
-               /// <param name="tit">The first collection</param>\r
-               /// <param name="tat">The second collection</param>\r
-               /// <param name="itemhasher">The item hasher to use for comparison</param>\r
-               /// <returns>True if equal</returns>\r
-               [Tested]\r
-               public static bool StaticEquals(ISequenced<T> tit, ISequenced<T> tat, IHasher<T> itemhasher)\r
-               {\r
-                       if (tat == null)\r
-                               return tit == null;\r
-\r
-                       if (tit.Count != tat.Count)\r
-                               return false;\r
-\r
-                       //This way we might run through both enumerations twice, but\r
-                       //probably not (if the hash codes are good)\r
-                       if (tit.GetHashCode() != tat.GetHashCode())\r
-                               return false;\r
-\r
-                       using (MSG.IEnumerator<T> dat = tat.GetEnumerator(), dit = tit.GetEnumerator())\r
-                       {\r
-                               while (dit.MoveNext())\r
-                               {\r
-                                       dat.MoveNext();\r
-                                       if (!itemhasher.Equals(dit.Current, dat.Current))\r
-                                               return false;\r
-                               }\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get the sequenced collection hash code of this collection: from the cached \r
-               /// value if present and up to date, else (re)compute.\r
-               /// </summary>\r
-               /// <returns>The hash code</returns>\r
-               protected int sequencedhashcode()\r
-               {\r
-                       if (iSequencedHashCodeStamp == stamp)\r
-                               return iSequencedHashCode;\r
-\r
-                       iSequencedHashCode = ComputeHashCode((ISequenced<T>)this, itemhasher);\r
-                       iSequencedHashCodeStamp = stamp;\r
-                       return iSequencedHashCode;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if the contents of that is equal to the contents of this\r
-               /// in the sequenced sense. Using the item hasher of this collection.\r
-               /// </summary>\r
-               /// <param name="that">The collection to compare to.</param>\r
-               /// <returns>True if  equal</returns>\r
-               protected bool sequencedequals(ISequenced<T> that)\r
-               {\r
-                       return StaticEquals((ISequenced<T>)this, that, itemhasher);\r
-               }\r
-\r
-\r
-               #endregion\r
-\r
-               /// <summary>\r
-               /// Create an enumerator for this collection.\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               public override abstract MSG.IEnumerator<T> GetEnumerator();\r
-\r
-\r
-               /// <summary>\r
-               /// <code>Forwards</code> if same, else <code>Backwards</code>\r
-               /// </summary>\r
-               /// <value>The enumeration direction relative to the original collection.</value>\r
-               [Tested]\r
-               public EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }\r
-       }\r
-\r
-\r
-       /// <summary>\r
-       /// Base class for collection classes of dynamic array type implementations.\r
-       /// </summary>\r
-       public class ArrayBase<T>: SequencedBase<T>\r
-       {\r
-               #region Fields\r
-               /// <summary>\r
-               /// The actual internal array container. Will be extended on demand.\r
-               /// </summary>\r
-               protected T[] array;\r
-\r
-               /// <summary>\r
-               /// The offset into the internal array container of the first item. The offset is 0 for a \r
-               /// base dynamic array and may be positive for an updatable view into a base dynamic array.\r
-               /// </summary>\r
-               protected int offset;\r
-               #endregion\r
-\r
-               #region Util\r
-               /// <summary>\r
-               /// Double the size of the internal array.\r
-               /// </summary>\r
-               protected virtual void expand()\r
-               {\r
-                       expand(2 * array.Length, size);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Expand the internal array container.\r
-               /// </summary>\r
-               /// <param name="newcapacity">The new size of the internal array - \r
-               /// will be rounded upwards to a power of 2.</param>\r
-               /// <param name="newsize">The (new) size of the (base) collection.</param>\r
-               protected virtual void expand(int newcapacity, int newsize)\r
-               {\r
-                       Debug.Assert(newcapacity >= newsize);\r
-\r
-                       int newlength = array.Length;\r
-\r
-                       while (newlength < newcapacity) newlength *= 2;\r
-\r
-                       T[] newarray = new T[newlength];\r
-\r
-                       Array.Copy(array, newarray, newsize);\r
-                       array = newarray;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at a specific index, moving items to the right\r
-               /// upwards and expanding the array if necessary.\r
-               /// </summary>\r
-               /// <param name="i">The index at which to insert.</param>\r
-               /// <param name="item">The item to insert.</param>\r
-               protected virtual void insert(int i, T item)\r
-               {\r
-                       if (size == array.Length)\r
-                               expand();\r
-\r
-                       if (i < size)\r
-                               Array.Copy(array, i, array, i + 1, size - i);\r
-\r
-                       array[i] = item;\r
-                       size++;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-\r
-               /// <summary>\r
-               /// Create an empty ArrayBase object.\r
-               /// </summary>\r
-               /// <param name="capacity">The initial capacity of the internal array container.\r
-               /// Will be rounded upwards to the nearest power of 2 greater than or equal to 8.</param>\r
-               /// <param name="hasher">The item hasher to use, primarily for item equality</param>\r
-               public ArrayBase(int capacity, IHasher<T> hasher)\r
-               {\r
-                       int newlength = 8;\r
-\r
-                       while (newlength < capacity) newlength *= 2;\r
-\r
-                       array = new T[newlength];\r
-                       itemhasher = hasher;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IIndexed members\r
-\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/>.\r
-               /// </summary>\r
-               /// <value>The directed collection of items in a specific index interval.</value>\r
-               /// <param name="start">The low index of the interval (inclusive).</param>\r
-        /// <param name="count">The size of the range.</param>\r
-        [Tested]\r
-        public IDirectedCollectionValue<T> this[int start, int count]\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-                               checkRange(start, count);\r
-                               return new Range(this, start, count, true);\r
-                       }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IEditableCollection members\r
-               /// <summary>\r
-               /// Remove all items and reset size of internal array container.\r
-               /// </summary>\r
-               [Tested]\r
-               public virtual void Clear()\r
-               {\r
-                       updatecheck();\r
-                       array = new T[8];\r
-                       size = 0;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an array containing (copies) of the items of this collection in enumeration order.\r
-               /// </summary>\r
-               /// <returns>The new array</returns>\r
-               [Tested]\r
-               public override T[] ToArray()\r
-               {\r
-                       T[] res = new T[size];\r
-\r
-                       Array.Copy(array, res, size);\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Perform an internal consistency (invariant) test on the array base.\r
-               /// </summary>\r
-               /// <returns>True if test succeeds.</returns>\r
-               [Tested]\r
-               public virtual bool Check()\r
-               {\r
-                       bool retval = true;\r
-\r
-                       if (size > array.Length)\r
-                       {\r
-                               Console.WriteLine("Bad size ({0}) > array.Length ({1})", size, array.Length);\r
-                               return false;\r
-                       }\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                       {\r
-                               if ((object)(array[i]) == null)\r
-                               {\r
-                                       Console.WriteLine("Bad element: null at index {0}", i);\r
-                                       return false;\r
-                               }\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IDirectedCollection<T> Members\r
-\r
-               /// <summary>\r
-               /// Create a directed collection with the same contents as this one, but \r
-               /// opposite enumeration sequence.\r
-               /// </summary>\r
-               /// <returns>The mirrored collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> Backwards() { return this[0, size].Backwards(); }\r
-\r
-               #endregion\r
-\r
-               #region IEnumerable<T> Members\r
-               /// <summary>\r
-               /// Create an enumerator for this array based collection.\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               [Tested]\r
-               public override MSG.IEnumerator<T> GetEnumerator()\r
-               {\r
-                       int thestamp = stamp, theend = size + offset, thestart = offset;\r
-\r
-                       for (int i = thestart; i < theend; i++)\r
-                       {\r
-                               modifycheck(thestamp);\r
-                               yield return array[i];\r
-                       }\r
-               }\r
-               #endregion\r
-\r
-               #region Range nested class\r
-               /// <summary>\r
-               /// A helper class for defining results of interval queries on array based collections.\r
-               /// </summary>\r
-               protected class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
-               {\r
-                       int start, count, delta, stamp;\r
-\r
-                       ArrayBase<T> thebase;\r
-\r
-\r
-                       internal Range(ArrayBase<T> thebase, int start, int count, bool forwards)\r
-                       {\r
-                               this.thebase = thebase;  stamp = thebase.stamp;\r
-                               delta = forwards ? 1 : -1;\r
-                               this.start = start + thebase.offset; this.count = count;\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// \r
-                       /// </summary>\r
-                       /// <value>The number of items in the range</value>\r
-                       [Tested]\r
-                       public override int Count { [Tested]get { thebase.modifycheck(stamp); return count; } }\r
-\r
-            /// <summary>\r
-            /// The value is symbolic indicating the type of asymptotic complexity\r
-            /// in terms of the size of this collection (worst-case or amortized as\r
-            /// relevant).\r
-            /// </summary>\r
-            /// <value>A characterization of the speed of the \r
-            /// <code>Count</code> property in this collection.</value>\r
-            public override Speed CountSpeed { get { thebase.modifycheck(stamp); return Speed.Constant; } }\r
-\r
-            /// <summary>\r
-                       /// Create an enumerator for this range of an array based collection.\r
-                       /// </summary>\r
-                       /// <returns>The enumerator</returns>\r
-                       [Tested]\r
-                       public override MSG.IEnumerator<T> GetEnumerator()\r
-                       {\r
-                               for (int i = 0; i < count; i++)\r
-                               {\r
-                                       thebase.modifycheck(stamp);\r
-                                       yield return thebase.array[start + delta * i];\r
-                               }\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Create a araay collection range with the same contents as this one, but \r
-                       /// opposite enumeration sequence.\r
-                       /// </summary>\r
-                       /// <returns>The mirrored collection.</returns>\r
-                       [Tested]\r
-                       public IDirectedCollectionValue<T> Backwards()\r
-                       {\r
-                               thebase.modifycheck(stamp);\r
-\r
-                               Range res = (Range)MemberwiseClone();\r
-\r
-                               res.delta = -delta;\r
-                               res.start = start + (count - 1) * delta;\r
-                               return res;\r
-                       }\r
-\r
-\r
-                       IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()\r
-                       {\r
-                               return Backwards();\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// <code>Forwards</code> if same, else <code>Backwards</code>\r
-                       /// </summary>\r
-                       /// <value>The enumeration direction relative to the original collection.</value>\r
-                       [Tested]\r
-                       public EnumerationDirection Direction\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       thebase.modifycheck(stamp);\r
-                                       return delta > 0 ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;\r
-                               }\r
-                       }\r
-               }\r
-               #endregion\r
-       }\r
-\r
-       #endregion\r
-\r
-       #region Sorting\r
-       /// <summary>\r
-       /// A utility class with functions for sorting arrays with respect to an IComparer&lt;T&gt;\r
-       /// </summary>\r
-       public class Sorting\r
-       {\r
-               /// <summary>\r
-               /// Sort part of array in place using IntroSort\r
-               /// </summary>\r
-               /// <param name="a">Array to sort</param>\r
-               /// <param name="f">Index of first position to sort</param>\r
-               /// <param name="b">Index of first position beyond the part to sort</param>\r
-               /// <param name="c">IComparer&lt;T&gt; to sort by</param>\r
-               [Tested]\r
-               public static void IntroSort<T>(T[] a, int f, int b, IComparer<T> c)\r
-               {\r
-                       new Sorter<T>(a, c).IntroSort(f, b);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Sort part of array in place using Insertion Sort\r
-               /// </summary>\r
-               /// <param name="a">Array to sort</param>\r
-               /// <param name="f">Index of first position to sort</param>\r
-               /// <param name="b">Index of first position beyond the part to sort</param>\r
-               /// <param name="c">IComparer&lt;T&gt; to sort by</param>\r
-               [Tested]\r
-               public static void InsertionSort<T>(T[] a, int f, int b, IComparer<T> c)\r
-               {\r
-                       new Sorter<T>(a, c).InsertionSort(f, b);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Sort part of array in place using Heap Sort\r
-               /// </summary>\r
-               /// <param name="a">Array to sort</param>\r
-               /// <param name="f">Index of first position to sort</param>\r
-               /// <param name="b">Index of first position beyond the part to sort</param>\r
-               /// <param name="c">IComparer&lt;T&gt; to sort by</param>\r
-               [Tested]\r
-               public static void HeapSort<T>(T[] a, int f, int b, IComparer<T> c)\r
-               {\r
-                       new Sorter<T>(a, c).HeapSort(f, b);\r
-               }\r
-\r
-\r
-               class Sorter<T>\r
-               {\r
-                       T[] a;\r
-\r
-                       IComparer<T> c;\r
-\r
-\r
-                       internal Sorter(T[] a, IComparer<T> c) { this.a = a; this.c = c; }\r
-\r
-\r
-                       internal void IntroSort(int f, int b)\r
-                       {\r
-                               if (b - f > 31)\r
-                               {\r
-                                       int depth_limit = (int)Math.Floor(2.5 * Math.Log(b - f, 2));\r
-\r
-                                       introSort(f, b, depth_limit);\r
-                               }\r
-                               else\r
-                                       InsertionSort(f, b);\r
-                       }\r
-\r
-\r
-                       private void introSort(int f, int b, int depth_limit)\r
-                       {\r
-                               const int size_threshold = 14;//24;\r
-\r
-                               if (depth_limit-- == 0)\r
-                                       HeapSort(f, b);\r
-                               else if (b - f <= size_threshold)\r
-                                       InsertionSort(f, b);\r
-                               else\r
-                               {\r
-                                       int p = partition(f, b);\r
-\r
-                                       introSort(f, p, depth_limit);\r
-                                       introSort(p, b, depth_limit);\r
-                               }\r
-                       }\r
-\r
-\r
-                       private int compare(T i1, T i2) { return c.Compare(i1, i2); }\r
-\r
-\r
-                       private int partition(int f, int b)\r
-                       {\r
-                               int bot = f, mid = (b + f) / 2, top = b - 1;\r
-                               T abot = a[bot], amid = a[mid], atop = a[top];\r
-\r
-                               if (compare(abot, amid) < 0)\r
-                               {\r
-                                       if (compare(atop, abot) < 0)//atop<abot<amid\r
-                                               { a[top] = amid; amid = a[mid] = abot; a[bot] = atop; }\r
-                                       else if (compare(atop, amid) < 0) //abot<=atop<amid\r
-                                               { a[top] = amid; amid = a[mid] = atop; }\r
-                                       //else abot<amid<=atop\r
-                               }\r
-                               else\r
-                               {\r
-                                       if (compare(amid, atop) > 0) //atop<amid<=abot\r
-                                               { a[bot] = atop; a[top] = abot; }\r
-                                       else if (compare(abot, atop) > 0) //amid<=atop<abot\r
-                                               { a[bot] = amid; amid = a[mid] = atop; a[top] = abot; }\r
-                                       else //amid<=abot<=atop\r
-                                               { a[bot] = amid; amid = a[mid] = abot; }\r
-                               }\r
-\r
-                               int i = bot, j = top;\r
-\r
-                               while (true)\r
-                               {\r
-                                       while (compare(a[++i], amid) < 0);\r
-\r
-                                       while (compare(amid, a[--j]) < 0);\r
-\r
-                                       if (i < j)\r
-                                       {\r
-                                               T tmp = a[i]; a[i] = a[j]; a[j] = tmp;\r
-                                       }\r
-                                       else\r
-                                               return i;\r
-                               }\r
-                       }\r
-\r
-\r
-                       internal void InsertionSort(int f, int b)\r
-                       {\r
-                               for (int j = f + 1; j < b; j++)\r
-                               {\r
-                                       T key = a[j], other;\r
-                                       int i = j - 1;\r
-\r
-                                       if (c.Compare(other = a[i], key) > 0)\r
-                                       {\r
-                                               a[j] = other;\r
-                                               while (i > f && c.Compare(other = a[i - 1], key) > 0) { a[i--] = other; }\r
-\r
-                                               a[i] = key;\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-\r
-                       internal void HeapSort(int f, int b)\r
-                       {\r
-                               for (int i = (b + f) / 2; i >= f; i--) heapify(f, b, i);\r
-\r
-                               for (int i = b - 1; i > f; i--)\r
-                               {\r
-                                       T tmp = a[f]; a[f] = a[i]; a[i] = tmp;\r
-                                       heapify(f, i, f);\r
-                               }\r
-                       }\r
-\r
-\r
-                       private void heapify(int f, int b, int i)\r
-                       {\r
-                               T pv = a[i], lv, rv, max = pv;\r
-                               int j = i, maxpt = j;\r
-\r
-                               while (true)\r
-                               {\r
-                                       int l = 2 * j - f + 1, r = l + 1;\r
-\r
-                                       if (l < b && compare(lv = a[l], max) > 0) { maxpt = l; max = lv; }\r
-\r
-                                       if (r < b && compare(rv = a[r], max) > 0) { maxpt = r; max = rv; }\r
-\r
-                                       if (maxpt == j)\r
-                                               break;\r
-\r
-                                       a[j] = max;\r
-                                       max = pv;\r
-                                       j = maxpt;\r
-                               }\r
-\r
-                               if (j > i)\r
-                                       a[j] = pv;\r
-                       }\r
-               }\r
-       }\r
-\r
-       #endregion\r
-\r
-       #region Random\r
-       /// <summary>\r
-       /// A modern random number generator based on (whatever)\r
-       /// </summary>\r
-       public class C5Random : Random\r
-       {\r
-               private uint[] Q = new uint[16];\r
-\r
-               private uint c = 362436, i = 15;\r
-\r
-\r
-               private uint Cmwc()\r
-               {\r
-                       ulong t, a = 487198574UL;\r
-                       uint x, r = 0xfffffffe;\r
-\r
-                       i = (i + 1) & 15;\r
-                       t = a * Q[i] + c;\r
-                       c = (uint)(t >> 32);\r
-                       x = (uint)(t + c);\r
-                       if (x < c)\r
-                       {\r
-                               x++;\r
-                               c++;\r
-                       }\r
-\r
-                       return Q[i] = r - x;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get a new random System.Double value\r
-               /// </summary>\r
-               /// <returns>The random double</returns>\r
-               public override double NextDouble()\r
-               {\r
-                       return Cmwc() / 4294967296.0;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get a new random System.Double value\r
-               /// </summary>\r
-               /// <returns>The random double</returns>\r
-               protected override double Sample()\r
-               {\r
-                       return NextDouble();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get a new random System.Int32 value\r
-               /// </summary>\r
-               /// <returns>The random int</returns>\r
-               public override int Next()\r
-               {\r
-                       return (int)Cmwc();\r
-               }\r
-               \r
-\r
-               /// <summary>\r
-               /// Get a random non-negative integer less than a given upper bound\r
-               /// </summary>\r
-               /// <param name="max">The upper bound (exclusive)</param>\r
-               /// <returns></returns>\r
-               public override int Next(int max)\r
-               {\r
-                       if (max < 0)\r
-                               throw new ApplicationException("max must be non-negative");\r
-\r
-                       return (int)(Cmwc() / 4294967296.0 * max);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get a random integer between two given bounds\r
-               /// </summary>\r
-               /// <param name="min">The lower bound (inclusive)</param>\r
-               /// <param name="max">The upper bound (exclusive)</param>\r
-               /// <returns></returns>\r
-               public override int Next(int min, int max)\r
-               {\r
-                       if (min > max)\r
-                               throw new ApplicationException("min must be less than or equal to max");\r
-\r
-                       return min + (int)(Cmwc() / 4294967296.0 * max);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Fill a array of byte with random bytes\r
-               /// </summary>\r
-               /// <param name="buffer">The array to fill</param>\r
-               public override void NextBytes(byte[] buffer)\r
-               {\r
-                       for (int i = 0, length = buffer.Length; i < length; i++)\r
-                               buffer[i] = (byte)Cmwc();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a random number generator seed by system time.\r
-               /// </summary>\r
-               public C5Random() : this(DateTime.Now.Ticks)\r
-               {\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a random number generator with a given seed\r
-               /// </summary>\r
-               /// <param name="seed">The seed</param>\r
-               public C5Random(long seed)\r
-               {\r
-                       if (seed == 0)\r
-                               throw new ApplicationException("Seed must be non-zero");\r
-\r
-                       uint j = (uint)(seed & 0xFFFFFFFF);\r
-\r
-                       for (int i = 0; i < 16; i++)\r
-                       {\r
-                               j ^= j << 13;\r
-                               j ^= j >>17;\r
-                               j ^= j << 5;\r
-                               Q[i] = j;\r
-                       }\r
-\r
-                       Q[15] = (uint)(seed ^ (seed >> 32));\r
-               }\r
-       }\r
-\r
-       #endregion\r
-\r
-       #region Custom code attributes\r
-\r
-       /// <summary>\r
-       /// A custom attribute to mark methods and properties as being tested \r
-       /// sufficiently in the regression test suite.\r
-       /// </summary>\r
-       [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]\r
-       public class TestedAttribute: Attribute\r
-       {\r
-\r
-               /// <summary>\r
-               /// Optional reference to test case\r
-               /// </summary>\r
-               [Tested]\r
-               public string via;\r
-\r
-\r
-               /// <summary>\r
-               /// Pretty print attribute value\r
-               /// </summary>\r
-               /// <returns>"Tested via " + via</returns>\r
-               [Tested]\r
-               public override string ToString() { return "Tested via " + via; }\r
-       }\r
-\r
-       #endregion\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/Dictionaries.cs b/mcs/class/Mono.C5/Dictionaries.cs
deleted file mode 100644 (file)
index 6d6d498..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// An entry in a dictionary from K to V.\r
-       /// </summary>\r
-       public struct KeyValuePair<K,V>\r
-       {\r
-               /// <summary>\r
-               /// The key field of the entry\r
-               /// </summary>\r
-               public K key;\r
-\r
-               /// <summary>\r
-               /// The value field of the entry\r
-               /// </summary>\r
-               public V value;\r
-\r
-\r
-               /// <summary>\r
-               /// Create an entry with specified key and value\r
-               /// </summary>\r
-               /// <param name="k">The key</param>\r
-               /// <param name="v">The value</param>\r
-               public KeyValuePair(K k, V v) { key = k; value = v; }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an entry with a specified key. The value is undefined.\r
-               /// </summary>\r
-               /// <param name="k">The key</param>\r
-               public KeyValuePair(K k) { key = k; value = default(V); }\r
-\r
-\r
-               /// <summary>\r
-               /// Pretty print an entry\r
-               /// </summary>\r
-               /// <returns>(key, value)</returns>\r
-               [Tested]\r
-               public override string ToString() { return "(" + key + ", " + value + ")"; }\r
-\r
-\r
-               /// <summary>\r
-               /// Check equality of entries\r
-               /// </summary>\r
-               /// <param name="obj">The other object</param>\r
-               /// <returns>True if obj is an entry of the same type and has the same key</returns>\r
-               [Tested]\r
-               public override bool Equals(object obj)\r
-               { return obj is KeyValuePair<K,V> && key.Equals(((KeyValuePair<K,V>)obj).key); }\r
-\r
-\r
-               /// <summary>\r
-               /// Get the hash code of the key.\r
-               /// </summary>\r
-               /// <returns>The hash code</returns>\r
-               [Tested]\r
-               public override int GetHashCode() { return key.GetHashCode(); }\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// Default comparer for dictionary entries in a sorted dictionary.\r
-       /// Entry comparisons only look at keys.\r
-       /// </summary>\r
-       public class KeyValuePairComparer<K,V>: IComparer<KeyValuePair<K,V>>\r
-       {\r
-               IComparer<K> myc;\r
-\r
-\r
-               /// <summary>\r
-               /// Create an entry comparer for a item comparer of the keys\r
-               /// </summary>\r
-               /// <param name="c">Comparer of keys</param>\r
-               public KeyValuePairComparer(IComparer<K> c) { myc = c; }\r
-\r
-\r
-               /// <summary>\r
-               /// Compare two entries\r
-               /// </summary>\r
-               /// <param name="a">First entry</param>\r
-               /// <param name="b">Second entry</param>\r
-               /// <returns>The result of comparing the keys</returns>\r
-               [Tested]\r
-               public int Compare(KeyValuePair<K,V> a, KeyValuePair<K,V> b)\r
-               { return myc.Compare(a.key, b.key); }\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// Default hasher for dictionary entries.\r
-       /// Operations only look at keys.\r
-       /// </summary>\r
-       public sealed class KeyValuePairHasher<K,V>: IHasher<KeyValuePair<K,V>>\r
-       {\r
-               IHasher<K> myh;\r
-\r
-\r
-               /// <summary>\r
-               /// Create an entry hasher using the default hasher for keys\r
-               /// </summary>\r
-               public KeyValuePairHasher() { myh = HasherBuilder.ByPrototype<K>.Examine(); }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an entry hasher from a specified item hasher for the keys\r
-               /// </summary>\r
-               /// <param name="c">The key hasher</param>\r
-               public KeyValuePairHasher(IHasher<K> c) { myh = c; }\r
-\r
-\r
-               /// <summary>\r
-               /// Get the hash code of the entry\r
-               /// </summary>\r
-               /// <param name="item">The entry</param>\r
-               /// <returns>The hash code of the key</returns>\r
-               [Tested]\r
-               public int GetHashCode(KeyValuePair<K,V> item) { return myh.GetHashCode(item.key); }\r
-\r
-\r
-               /// <summary>\r
-               /// Test two entries for equality\r
-               /// </summary>\r
-               /// <param name="i1">First entry</param>\r
-               /// <param name="i2">Second entry</param>\r
-               /// <returns>True if keys are equal</returns>\r
-               [Tested]\r
-               public bool Equals(KeyValuePair<K,V> i1, KeyValuePair<K,V> i2)\r
-               { return myh.Equals(i1.key, i2.key); }\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A base class for implementing a dictionary based on a set collection implementation.\r
-       /// <p>See the source code for <see cref="T:C5.HashDictionary!2"/> for an example</p>\r
-       /// \r
-       /// </summary>\r
-       public abstract class DictionaryBase<K,V>: EnumerableBase<KeyValuePair<K,V>>, IDictionary<K,V>\r
-       {\r
-               /// <summary>\r
-               /// The set collection of entries underlying this dictionary implementation\r
-               /// </summary>\r
-               protected ICollection<KeyValuePair<K,V>> pairs;\r
-\r
-\r
-               #region IDictionary<K,V> Members\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>The number of entrues in the dictionary</value>\r
-               [Tested]\r
-               public int Count { [Tested]get { return pairs.Count; } }\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>A distinguished object to use for locking to synchronize multithreaded access</value>\r
-               [Tested]\r
-               public object SyncRoot { [Tested]get { return pairs.SyncRoot; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Add a new (key, value) pair (a mapping) to the dictionary.\r
-               /// <exception cref="InvalidOperationException"/> if there already is an entry with the same key. \r
-               /// </summary>\r
-               /// <param name="key">Key to add</param>\r
-               /// <param name="val">Value to add</param>\r
-               [Tested]\r
-               public void Add(K key, V val)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key, val);\r
-\r
-                       if (!pairs.Add(p))\r
-                               throw new System.ArgumentException("Item has already been added.  Key in dictionary: '" + key + "'  Key being added: '" + key + "'");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove an entry with a given key from the dictionary\r
-               /// </summary>\r
-               /// <param name="key">The key of the entry to remove</param>\r
-               /// <returns>True if an entry was found (and removed)</returns>\r
-               [Tested]\r
-               public bool Remove(K key)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       return pairs.Remove(p);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove an entry with a given key from the dictionary and report its value.\r
-               /// </summary>\r
-               /// <param name="key">The key of the entry to remove</param>\r
-               /// <param name="val">On exit, the value of the removed entry</param>\r
-               /// <returns>True if an entry was found (and removed)</returns>\r
-               [Tested]\r
-               public bool Remove(K key, out V val)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       if (pairs.RemoveWithReturn(ref p))\r
-                       {\r
-                               val = p.value;\r
-                               return true;\r
-                       }\r
-                       else\r
-                       {\r
-                               val = default(V);\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all entries from the dictionary\r
-               /// </summary>\r
-               [Tested]\r
-               public void Clear() { pairs.Clear(); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if there is an entry with a specified key\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <returns>True if key was found</returns>\r
-               [Tested]\r
-               public bool Contains(K key)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       return pairs.Contains(p);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if there is an entry with a specified key and report the corresponding\r
-               /// value if found. This can be seen as a safe form of "val = this[key]".\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">On exit, the value of the entry</param>\r
-               /// <returns>True if key was found</returns>\r
-               [Tested]\r
-               public bool Find(K key, out V val)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       if (pairs.Find(ref p))\r
-                       {\r
-                               val = p.value;\r
-                               return true;\r
-                       }\r
-                       else\r
-                       {\r
-                               val = default(V);\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Look for a specific key in the dictionary and if found replace the value with a new one.\r
-               /// This can be seen as a non-adding version of "this[key] = val".\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">The new value</param>\r
-               /// <returns>True if key was found</returns>\r
-               [Tested]\r
-               public bool Update(K key, V val)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key, val);\r
-\r
-                       return pairs.Update(p);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Look for a specific key in the dictionary. If found, report the corresponding value,\r
-               /// else add an entry with the key and the supplied value.\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">On entry the value to add if the key is not found.\r
-               /// On exit the value found if any.</param>\r
-               /// <returns>True if key was found</returns>\r
-               [Tested]\r
-               public bool FindOrAdd(K key, ref V val)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key, val);\r
-\r
-                       if (!pairs.FindOrAdd(ref p))\r
-                               return false;\r
-                       else\r
-                       {\r
-                               val = p.value;\r
-                               return true;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Update value in dictionary corresponding to key if found, else add new entry.\r
-               /// More general than "this[key] = val;" by reporting if key was found.\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">The value to add or replace with.</param>\r
-               /// <returns>True if entry was updated.</returns>\r
-               [Tested]\r
-               public bool UpdateOrAdd(K key, V val)\r
-               {\r
-                       return pairs.UpdateOrAdd(new KeyValuePair<K,V>(key, val));\r
-               }\r
-\r
-\r
-\r
-               #region Keys,Values support classes\r
-                       \r
-               internal class ValuesCollection: CollectionValueBase<V>, ICollectionValue<V>\r
-               {\r
-                       ICollection<KeyValuePair<K,V>> pairs;\r
-\r
-\r
-                       internal ValuesCollection(ICollection<KeyValuePair<K,V>> pairs)\r
-                       { this.pairs = pairs; }\r
-\r
-\r
-                       [Tested]\r
-                       public override MSG.IEnumerator<V> GetEnumerator()\r
-                       {\r
-                               //Updatecheck is performed by the pairs enumerator\r
-                               foreach (KeyValuePair<K,V> p in pairs)\r
-                                       yield return p.value;\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-            public override int Count { [Tested]get { return pairs.Count; } }\r
-\r
-            public override Speed CountSpeed { get { return Speed.Constant; } }\r
-        }\r
-\r
-\r
-\r
-        internal class KeysCollection: CollectionValueBase<K>, ICollectionValue<K>\r
-               {\r
-                       ICollection<KeyValuePair<K,V>> pairs;\r
-\r
-\r
-                       internal KeysCollection(ICollection<KeyValuePair<K,V>> pairs)\r
-                       { this.pairs = pairs; }\r
-\r
-\r
-                       [Tested]\r
-                       public override MSG.IEnumerator<K> GetEnumerator()\r
-                       {\r
-                               foreach (KeyValuePair<K,V> p in pairs)\r
-                                       yield return p.key;\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       public override int Count { [Tested]get { return pairs.Count; } }\r
-\r
-            public override Speed CountSpeed { get { return pairs.CountSpeed; } }\r
-        }\r
-               #endregion\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>A collection containg the all the keys of the dictionary</value>\r
-               [Tested]\r
-               public ICollectionValue<K> Keys { [Tested]get { return new KeysCollection(pairs); } }\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>A collection containing all the values of the dictionary</value>\r
-               [Tested]\r
-               public ICollectionValue<V> Values { [Tested]get { return new ValuesCollection(pairs); } }\r
-\r
-\r
-               /// <summary>\r
-               /// Indexer for dictionary.\r
-               /// <exception cref="InvalidOperationException"/> if no entry is found. \r
-               /// </summary>\r
-               /// <value>The value corresponding to the key</value>\r
-               [Tested]\r
-               public V this[K key]\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-                               KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                               if (pairs.Find(ref p))\r
-                                       return p.value;\r
-                               else\r
-                                       throw new System.ArgumentException("Key not present in Dictionary");\r
-                       }\r
-                       [Tested]\r
-                       set\r
-                       { pairs.UpdateOrAdd(new KeyValuePair<K,V>(key, value)); }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True if dictionary is read  only</value>\r
-               [Tested]\r
-               public bool IsReadOnly { [Tested]get { return pairs.IsReadOnly; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this dictionary.\r
-               /// Only avaliable in DEBUG builds???\r
-               /// </summary>\r
-               /// <returns>True if check does not fail.</returns>\r
-               [Tested]\r
-               public bool Check() { return pairs.Check(); }\r
-\r
-               #endregion\r
-\r
-               #region IEnumerable<KeyValuePair<K,V>> Members\r
-\r
-\r
-               /// <summary>\r
-               /// Create an enumerator for the collection of entries of the dictionary\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               [Tested]\r
-               public override MSG.IEnumerator<KeyValuePair<K,V>> GetEnumerator()\r
-               {\r
-                       return pairs.GetEnumerator();;\r
-               }\r
-\r
-               #endregion\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/Interfaces.cs b/mcs/class/Mono.C5/Interfaces.cs
deleted file mode 100644 (file)
index c999dc2..0000000
+++ /dev/null
@@ -1,1378 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using MSG = System.Collections.Generic;\r
-namespace C5\r
-{\r
-       /*************************************************************************/\r
-    //TODO: use the MS defs fro m MSG if any?\r
-       /// <summary>\r
-       /// A generic delegate that when invoked performs some operation\r
-       /// on it T argument.\r
-       /// </summary>\r
-       public delegate void Applier<T>(T t);\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A generic delegate whose invocation constitutes a map from T to V.\r
-       /// </summary>\r
-       public delegate V Mapper<T,V>(T item);\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A generic delegate that when invoked on a T item returns a boolean\r
-       /// value -- i.e. a T predicate.\r
-       /// </summary> \r
-       public delegate bool Filter<T>(T item);\r
-\r
-\r
-\r
-       /************************************************************************\r
-       /// <summary>\r
-       /// A generic collection that may be enumerated. This is the coarsest interface\r
-       /// for main stream generic collection classes (as opposed to priority queues).\r
-       /// It can also be the result of a query operation on another collection \r
-       /// (where the result size is not easily computable, in which case the result\r
-       /// could have been an <code>ICollectionValue&lt;T&gt;</code>).\r
-       /// </summary>\r
-       public interface noIEnumerable<T>\r
-       {\r
-               /// <summary>\r
-               /// Create an enumerator for the collection\r
-               /// </summary>\r
-               /// <returns>The enumerator(SIC)</returns>\r
-               MSG.IEnumerator<T> GetEnumerator();\r
-       }\r
-    */\r
-\r
-\r
-       /// <summary>\r
-       /// A generic collection, that can be enumerated backwards.\r
-       /// </summary>\r
-       public interface IDirectedEnumerable<T>: MSG.IEnumerable<T>\r
-       {\r
-               /// <summary>\r
-               /// Create a collection containing the same items as this collection, but\r
-               /// whose enumerator will enumerate the items backwards. The new collection\r
-               /// will become invalid if the original is modified. Method typicaly used as in\r
-               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
-               /// </summary>\r
-               /// <returns>The backwards collection.</returns>\r
-               IDirectedEnumerable<T> Backwards();\r
-\r
-\r
-               /// <summary>\r
-               /// <code>Forwards</code> if same, else <code>Backwards</code>\r
-               /// </summary>\r
-               /// <value>The enumeration direction relative to the original collection.</value>\r
-               EnumerationDirection Direction { get;}\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A generic collection that may be enumerated and can answer\r
-       /// efficiently how many items it contains. Like <code>IEnumerable&lt;T&gt;</code>,\r
-       /// this interface does not prescribe any operations to initialize or update the \r
-       /// collection. The main usage for this interface is to be the return type of \r
-       /// query operations on generic collection.\r
-       /// </summary>\r
-       public interface ICollectionValue<T>: MSG.IEnumerable<T>\r
-       {\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>The number of items in this collection</value>\r
-               int Count { get;}\r
-\r
-        /// <summary>\r
-        /// The value is symbolic indicating the type of asymptotic complexity\r
-        /// in terms of the size of this collection (worst-case or amortized as\r
-        /// relevant).\r
-        /// </summary>\r
-        /// <value>A characterization of the speed of the \r
-        /// <code>Count</code> property in this collection.</value>\r
-        Speed CountSpeed { get;}\r
-\r
-        /// <summary>\r
-               /// Copy the items of this collection to a contiguous part of an array.\r
-               /// </summary>\r
-               /// <param name="a">The array to copy to</param>\r
-               /// <param name="i">The index at which to copy the first item</param>\r
-               void CopyTo(T[] a, int i);\r
-\r
-        /// <summary>\r
-        /// Create an array with the items of this collection (in the same order as an\r
-        /// enumerator would output them).\r
-        /// </summary>\r
-        /// <returns>The array</returns>\r
-        T[] ToArray();\r
-\r
-        /// <summary>\r
-        /// Apply a delegate to all items of this collection.\r
-        /// </summary>\r
-        /// <param name="a">The delegate to apply</param>\r
-        void Apply(Applier<T> a);\r
-\r
-\r
-        /// <summary>\r
-        /// Check if there exists an item  that satisfies a\r
-        /// specific predicate in this collection.\r
-        /// </summary>\r
-        /// <param name="filter">A filter delegate \r
-        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
-        /// <returns>True is such an item exists</returns>\r
-        bool Exists(Filter<T> filter);\r
-\r
-\r
-        /// <summary>\r
-        /// Check if all items in this collection satisfies a specific predicate.\r
-        /// </summary>\r
-        /// <param name="filter">A filter delegate \r
-        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>\r
-        /// <returns>True if all items satisfies the predicate</returns>\r
-        bool All(Filter<T> filter);\r
-    }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A sized generic collection, that can be enumerated backwards.\r
-       /// </summary>\r
-       public interface IDirectedCollectionValue<T>: ICollectionValue<T>, IDirectedEnumerable<T>\r
-       {\r
-               /// <summary>\r
-               /// Create a collection containing the same items as this collection, but\r
-               /// whose enumerator will enumerate the items backwards. The new collection\r
-               /// will become invalid if the original is modified. Method typicaly used as in\r
-               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
-               /// </summary>\r
-               /// <returns>The backwards collection.</returns>\r
-               new IDirectedCollectionValue<T> Backwards();\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A generic collection to which one may add items. This is just the intersection\r
-       /// of the main stream generic collection interfaces and the priority queue interface,\r
-       /// <see cref="T:C5.ICollection!1"/> and <see cref="T:C5.IPriorityQueue!1"/>.\r
-       /// </summary>\r
-       public interface IExtensible<T> : ICollectionValue<T>\r
-       {\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>False if this collection has set semantics, true if bag semantics.</value>\r
-               bool AllowsDuplicates { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>An object to be used for locking to enable multi threaded code\r
-               /// to acces this collection safely.</value>\r
-               object SyncRoot { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True if this collection is empty.</value>\r
-               bool IsEmpty { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to this collection if possible. If this collection has set\r
-               /// semantics, the item will be added if not already in the collection. If\r
-               /// bag semantics, the item will always be added.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True if item was added.</returns>\r
-               bool Add(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Add the elements from another collection to this collection. If this\r
-               /// collection has set semantics, only items not already in the collection\r
-               /// will be added.\r
-               /// </summary>\r
-               /// <param name="items">The items to add.</param>\r
-               void AddAll(MSG.IEnumerable<T> items);\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. If this\r
-        /// collection has set semantics, only items not already in the collection\r
-        /// will be added.\r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        void AddAll<U>(MSG.IEnumerable<U> items) where U : T;\r
-\r
-               //void Clear(); // for priority queue\r
-               //int Count why not?\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this collection.\r
-               /// <p>This is only relevant for developers of the library</p>\r
-               /// </summary>\r
-               /// <returns>True if check was passed.</returns>\r
-               bool Check();\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// The symbolic characterization of the speed of lookups for a collection.\r
-       /// The values may refer to worst-case, amortized and/or expected asymtotic \r
-       /// complexity wrt. the collection size.\r
-       /// </summary>\r
-       public enum Speed: short\r
-       {\r
-        /// <summary>\r
-        /// Counting the collection with the <code>Count property</code> may not return\r
-        /// (for a synthetic and potentially infinite collection).\r
-        /// </summary>\r
-        PotentiallyInfinite = 1,\r
-        /// <summary>\r
-        /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>\r
-        /// property may take time O(n),\r
-        /// where n is the size of the collection.\r
-        /// </summary>\r
-        Linear = 2,\r
-        /// <summary>\r
-        /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>\r
-        /// property  takes time O(log n),\r
-        /// where n is the size of the collection.\r
-               /// </summary>\r
-               Log = 3,\r
-               /// <summary>\r
-        /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>\r
-        /// property  takes time O(1),\r
-        /// where n is the size of the collection.\r
-               /// </summary>\r
-               Constant = 4\r
-       }\r
-\r
-\r
-\r
-       //TODO: add ItemHasher to interface by making it an IHasher<T>? No, add Comparer property!\r
-       /// <summary>\r
-       /// The simplest interface of a main stream generic collection\r
-       /// with lookup, insertion and removal operations. \r
-       /// </summary>\r
-       public interface ICollection<T>: IExtensible<T>\r
-       {\r
-               /// <summary>\r
-               /// If true any call of an updating operation will throw an\r
-               /// <code>InvalidOperationException</code>\r
-               /// </summary>\r
-               /// <value>True if this collection is read only.</value>\r
-               bool IsReadOnly { get;}\r
-\r
-\r
-               //This is somewhat similar to the RandomAccess marker itf in java\r
-               /// <summary>\r
-               /// The value is symbolic indicating the type of asymptotic complexity\r
-               /// in terms of the size of this collection (worst-case or amortized as\r
-               /// relevant).\r
-               /// </summary>\r
-               /// <value>A characterization of the speed of lookup operations\r
-               /// (<code>Contains()</code> etc.) of the implementation of this list.</value>\r
-               Speed ContainsSpeed { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// The hashcode is defined as the sum of <code>h(item)</code> over the items\r
-               /// of the collection, where the function <code>h</code> is??? \r
-               /// </summary>\r
-               /// <returns>The unordered hashcode of this collection.</returns>\r
-               int GetHashCode();\r
-\r
-\r
-               /// <summary>\r
-               /// Compare the contents of this collection to another one without regards to\r
-               /// the sequence order. The comparison will use this collection's itemhasher\r
-               /// to compare individual items.\r
-               /// </summary>\r
-               /// <param name="that">The collection to compare to.</param>\r
-               /// <returns>True if this collection and that contains the same items.</returns>\r
-               bool Equals(ICollection<T> that);\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains (an item equivalent to according to the\r
-               /// itemhasher) a particular value.\r
-               /// </summary>\r
-               /// <param name="item">The value to check for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               bool Contains(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Count the number of items of the collection equal to a particular value.\r
-               /// Returns 0 if and only if the value is not in the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to count.</param>\r
-               /// <returns>The number of copies found.</returns>\r
-               int ContainsCount(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains all the values in another collection.\r
-               /// If this collection has bag semantics (<code>NoDuplicates==false</code>)\r
-               /// the check is made with respect to multiplicities, else multiplicities\r
-               /// are not taken into account.\r
-               /// </summary>\r
-               /// <param name="items">The </param>\r
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
-               bool ContainsAll(MSG.IEnumerable<T> items);\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               bool Find(ref T item);\r
-\r
-\r
-               //This should probably just be bool Add(ref T item); !!!\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found. Else, add the item to the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the item was found (hence not added).</returns>\r
-               bool FindOrAdd(ref T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
-               /// it is implementation dependent if this updates all equivalent copies in\r
-               /// the collection or just one.\r
-               /// </summary>\r
-               /// <param name="item">Value to update.</param>\r
-               /// <returns>True if the item was found and hence updated.</returns>\r
-               bool Update(T item);\r
-\r
-\r
-               //Better to call this AddOrUpdate since the return value fits that better\r
-               //OTOH for a bag the update would be better be the default!!!\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value; else add the value to the collection. \r
-               /// </summary>\r
-               /// <param name="item">Value to add or update.</param>\r
-               /// <returns>True if the item was found and updated (hence not added).</returns>\r
-               bool UpdateOrAdd(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection. If the collection has bag\r
-               /// semantics only one copy equivalent to the supplied item is removed. \r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               bool Remove(T item);\r
-\r
-\r
-               //CLR will allow us to let this be bool Remove(ref T item); !!!\r
-               /// <summary>\r
-               /// Remove a particular item from this collection if found. If the collection\r
-               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
-               /// which one is implementation dependent. \r
-               /// If an item was removed, report a binary copy of the actual item removed in \r
-               /// the argument.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove on input.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               bool RemoveWithReturn(ref T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items equivalent to a given value.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               void RemoveAllCopies(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in another collection from this one. If this collection\r
-               /// has bag semantics, take multiplicities into account.\r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               void RemoveAll(MSG.IEnumerable<T> items);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from this collection.\r
-               /// </summary>\r
-               void Clear();\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items not in some other collection from this one. If this collection\r
-               /// has bag semantics, take multiplicities into account.\r
-               /// </summary>\r
-               /// <param name="items">The items to retain.</param>\r
-               void RetainAll(MSG.IEnumerable<T> items);\r
-\r
-               //IDictionary<T> UniqueItems()\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// An editable collection maintaining a definite sequence order of the items.\r
-       ///\r
-       /// <p>Implementations of this interface must compute the hash code and \r
-       /// equality exactly as prescribed in the method definitions in order to\r
-       /// be consistent with other collection classes implementing this interface.</p>\r
-       /// <p>This interface is usually implemented by explicit interface implementation,\r
-       /// not as ordinary virtual methods.</p>\r
-       /// </summary>\r
-       public interface ISequenced<T>: ICollection<T>, IDirectedCollectionValue<T>\r
-       {\r
-               /// <summary>\r
-               /// The hashcode is defined as <code>h(...h(h(x1),x2)...,xn)</code> for\r
-               /// <code>h(a,b)=31*a+b</code> and the x's the hash codes of \r
-               /// </summary>\r
-               /// <returns>The sequence order hashcode of this collection.</returns>\r
-               new int GetHashCode();\r
-\r
-\r
-               /// <summary>\r
-               /// Compare this sequenced collection to another one in sequence order.\r
-               /// </summary>\r
-               /// <param name="that">The sequenced collection to compare to.</param>\r
-               /// <returns>True if this collection and that contains equal (according to\r
-               /// this collection's itemhasher) in the same sequence order.</returns>\r
-               bool Equals(ISequenced<T> that);\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A sequenced collection, where indices of items in the order are maintained\r
-       /// </summary>\r
-       public interface IIndexed<T>: ISequenced<T>\r
-       {\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <value>The i'th item of this list.</value>\r
-               /// <param name="i">the index to lookup</param>\r
-               T this[int i] { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/>.\r
-               /// </summary>\r
-               /// <value>The directed collection of items in a specific index interval.</value>\r
-               /// <param name="start">The low index of the interval (inclusive).</param>\r
-               /// <param name="count">The size of the range.</param>\r
-               IDirectedCollectionValue<T> this[int start, int count] { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going forwrds from the start.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of item from start.</returns>\r
-               int IndexOf(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going backwords from the end.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of of item from the end.</returns>\r
-               int LastIndexOf(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the item at a specific position of the list.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <param name="i">The index of the item to remove.</param>\r
-               /// <returns>The removed item.</returns>\r
-               T RemoveAt(int i);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in an index interval.\r
-               /// <exception cref="IndexOutOfRangeException"/>???. \r
-               /// </summary>\r
-               /// <param name="start">The index of the first item to remove.</param>\r
-               /// <param name="count">The number of items to remove.</param>\r
-               void RemoveInterval(int start, int count);\r
-       }\r
-\r
-    //TODO: decide if this should extend ICollection\r
-    /// <summary>\r
-    /// The interface describing the operations of a LIFO stack data structure.\r
-    /// </summary>\r
-    /// <typeparam name="T">The item type</typeparam>\r
-    public interface IStack<T>\r
-    {\r
-        /// <summary>\r
-        /// Push an item to the top of the stack.\r
-        /// </summary>\r
-        /// <param name="item">The item</param>\r
-        void Push(T item);\r
-        /// <summary>\r
-        /// Pop the item at the top of the stack from the stack.\r
-        /// </summary>\r
-        /// <returns>The popped item.</returns>\r
-        T Pop();\r
-    }\r
-\r
-    //TODO: decide if this should extend ICollection\r
-    /// <summary>\r
-    /// The interface describing the operations of a FIFO queue data structure.\r
-    /// </summary>\r
-    /// <typeparam name="T">The item type</typeparam>\r
-    public interface IQueue<T>\r
-    {\r
-        /// <summary>\r
-        /// Enqueue an item at the back of the queue. \r
-        /// </summary>\r
-        /// <param name="item">The item</param>\r
-        void EnQueue(T item);\r
-        /// <summary>\r
-        /// Dequeue an item from the front of the queue.\r
-        /// </summary>\r
-        /// <returns>The item</returns>\r
-        T DeQueue();\r
-    }\r
-\r
-\r
-       /// <summary>\r
-       /// This is an indexed collection, where the item order is chosen by \r
-       /// the user at insertion time.\r
-       ///\r
-       /// NBNBNB: we neeed a description of the view functionality here!\r
-       /// </summary>\r
-       public interface IList<T>: IIndexed<T>, IStack<T>, IQueue<T>\r
-       {\r
-               /// <summary>\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <value>The first item in this list.</value>\r
-               T First { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <value>The last item in this list.</value>\r
-               T Last { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// Since <code>Add(T item)</code> always add at the end of the list,\r
-               /// this describes if list has FIFO or LIFO semantics.\r
-               /// </summary>\r
-               /// <value>True if the <code>Remove()</code> operation removes from the\r
-               /// start of the list, false if it removes from the end.</value>\r
-               bool FIFO { get; set;}\r
-\r
-\r
-               /// <summary>\r
-               /// On this list, this indexer is read/write.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <value>The i'th item of this list.</value>\r
-               /// <param name="i">The index of the item to fetch or store.</param>\r
-               new T this[int i] { get; set;}\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at a specific index location in this list. \r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt; the size of the collection.</summary>\r
-               /// <exception cref="InvalidOperationException"/> if the list has\r
-               /// <code>NoDuplicates=true</code> and the item is \r
-               /// already in the list.\r
-               /// <param name="i">The index at which to insert.</param>\r
-               /// <param name="item">The item to insert.</param>\r
-               void Insert(int i, T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at the front of this list.\r
-               /// <exception cref="InvalidOperationException"/> if the list has\r
-               /// <code>NoDuplicates=true</code> and the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               void InsertFirst(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at the back of this list.\r
-               /// <exception cref="InvalidOperationException"/> if the list has\r
-               /// <code>NoDuplicates=true</code> and the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               void InsertLast(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item right before the first occurrence of some target item.\r
-               /// <exception cref="InvalidOperationException"/> if target     is not found\r
-               /// or if the list has <code>NoDuplicates=true</code> and the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target before which to insert.</param>\r
-               void InsertBefore(T item, T target);\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item right after the last(???) occurrence of some target item.\r
-               /// <exception cref="InvalidOperationException"/> if target     is not found\r
-               /// or if the list has <code>NoDuplicates=true</code> and the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target after which to insert.</param>\r
-               void InsertAfter(T item, T target);\r
-\r
-\r
-               /// <summary>\r
-               /// Insert into this list all items from an enumerable collection starting \r
-               /// at a particular index.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt; the size of the collection.\r
-               /// <exception cref="InvalidOperationException"/> if the list has \r
-               /// <code>NoDuplicates=true</code> and one of the items to insert is\r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="i">Index to start inserting at</param>\r
-               /// <param name="items">Items to insert</param>\r
-               void InsertAll(int i, MSG.IEnumerable<T> items);\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new list consisting of the items of this list satisfying a \r
-               /// certain predicate.\r
-               /// </summary>\r
-               /// <param name="filter">The filter delegate defining the predicate.</param>\r
-               /// <returns>The new list.</returns>\r
-               IList<T> FindAll(Filter<T> filter);\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new list consisting of the results of mapping all items of this\r
-               /// list. The new list will use the default hasher for the item type V.\r
-               /// </summary>\r
-               /// <typeparam name="V">The type of items of the new list</typeparam>\r
-               /// <param name="mapper">The delegate defining the map.</param>\r
-               /// <returns>The new list.</returns>\r
-               IList<V> Map<V>(Mapper<T,V> mapper);\r
-\r
-        /// <summary>\r
-        /// Create a new list consisting of the results of mapping all items of this\r
-               /// list. The new list will use a specified hasher for the item type.\r
-        /// </summary>\r
-        /// <typeparam name="V">The type of items of the new list</typeparam>\r
-        /// <param name="mapper">The delegate defining the map.</param>\r
-        /// <param name="hasher">The hasher to use for the new list</param>\r
-        /// <returns>The new list.</returns>\r
-        IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher);\r
-        \r
-        /// <summary>\r
-        /// Remove one item from the list: from the front if <code>FIFO</code>\r
-               /// is true, else from the back.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               T Remove();\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one item from the fromnt of the list.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               T RemoveFirst();\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one item from the back of the list.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               T RemoveLast();\r
-\r
-\r
-               /// <summary>\r
-               /// Create a list view on this list. \r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the view would not fit into\r
-               /// this list.\r
-               /// </summary>\r
-               /// <param name="start">The index in this list of the start of the view.</param>\r
-               /// <param name="count">The size of the view.</param>\r
-               /// <returns>The new list view.</returns>\r
-               IList<T> View(int start, int count);\r
-\r
-\r
-               /// <summary>\r
-               /// Null if this list is not a view.\r
-               /// </summary>\r
-        /// <value>Underlying list for view.</value>\r
-        IList<T> Underlying { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// </summary>\r
-        /// <value>Offset for this list view or 0 for an underlying list.</value>\r
-        int Offset { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// Slide this list view along the underlying list.\r
-               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
-               /// would bring either end of the view outside the underlying list.\r
-               /// </summary>\r
-               /// <param name="offset">The signed amount to slide: positive to slide\r
-               /// towards the end.</param>\r
-               void Slide(int offset);\r
-\r
-\r
-               /// <summary>\r
-               /// Slide this list view along the underlying list, changing its size.\r
-               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
-               /// would bring either end of the view outside the underlying list.\r
-               /// </summary>\r
-               /// <param name="offset">The signed amount to slide: positive to slide\r
-               /// towards the end.</param>\r
-               /// <param name="size">The new size of the view.</param>\r
-               void Slide(int offset, int size);\r
-\r
-\r
-               /// <summary>\r
-               /// Reverse the list so the items are in the opposite sequence order.\r
-               /// </summary>\r
-               void Reverse();\r
-\r
-\r
-               /// <summary>\r
-               /// Reverst part of the list so the items are in the opposite sequence order.\r
-               /// <exception cref="ArgumentException"/> if the count is negative.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
-               /// into the list.\r
-               /// </summary>\r
-               /// <param name="start">The index of the start of the part to reverse.</param>\r
-               /// <param name="count">The size of the part to reverse.</param>\r
-               void Reverse(int start, int count);\r
-\r
-\r
-               //NaturalSort for comparable items?\r
-               /// <summary>\r
-               /// Check if this list is sorted according to a specific sorting order.\r
-               /// </summary>\r
-               /// <param name="c">The comparer defining the sorting order.</param>\r
-               /// <returns>True if the list is sorted, else false.</returns>\r
-               bool IsSorted(IComparer<T> c);\r
-\r
-\r
-               /// <summary>\r
-               /// Sort the items of the list according to a specific sorting order.\r
-               /// </summary>\r
-               /// <param name="c">The comparer defining the sorting order.</param>\r
-               void Sort(IComparer<T> c);\r
-\r
-\r
-               /// <summary>\r
-               /// Randonmly shuffle the items of this list. \r
-               /// </summary>\r
-               void Shuffle();\r
-\r
-\r
-               /// <summary>\r
-               /// Shuffle the items of this list according to a specific random source.\r
-               /// </summary>\r
-               /// <param name="rnd">The random source.</param>\r
-               void Shuffle(Random rnd);\r
-       }\r
-\r
-\r
-    /// <summary>\r
-       /// A generic collection of items prioritized by a comparison (order) relation.\r
-       /// Supports adding items and reporting or removing extremal elements. \r
-       /// The priority queue itself exports the used\r
-       /// order relation through its implementation of <code>IComparer&lt;T&gt;</code>\r
-       /// </summary>\r
-       public interface IPriorityQueue<T>: IExtensible<T>\r
-       {\r
-\r
-               /// <summary>\r
-               /// Find the current least item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The least item.</returns>\r
-               T FindMin();\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the least item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               T DeleteMin();\r
-\r
-\r
-               /// <summary>\r
-               /// Find the current largest item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The largest item.</returns>\r
-               T FindMax();\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the largest item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               T DeleteMax();\r
-\r
-        /// <summary>\r
-        /// The comparer object supplied at creation time for this collection\r
-        /// </summary>\r
-        /// <value>The comparer</value>\r
-        IComparer<T> Comparer { get;}\r
-    }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A collection where items are maintained in sorted order.\r
-       /// </summary>\r
-       public interface ISorted<T>: ISequenced<T>, IPriorityQueue<T>\r
-       {\r
-               /// <summary>\r
-               /// Find the strict predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than or equal to the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the predecessor for.</param>\r
-               /// <returns>The predecessor.</returns>\r
-               T Predecessor(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Find the strict successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than or equal to the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the successor for.</param>\r
-               /// <returns>The successor.</returns>\r
-               T Successor(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak predecessor for.</param>\r
-               /// <returns>The weak predecessor.</returns>\r
-               T WeakPredecessor(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak successor for.</param>\r
-               /// <returns>The weak successor.</returns>\r
-               T WeakSuccessor(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Perform a search in the sorted collection for the ranges in which a\r
-               /// non-decreasing function from the item type to <code>int</code> is\r
-               /// negative, zero respectively positive. If the supplied cut function is\r
-               /// not non-decreasing, the result of this call is undefined.\r
-               /// </summary>\r
-               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
-               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
-               /// the <code>c.CompareTo(T that)</code> method.</param>\r
-               /// <param name="low">Returns the largest item in the collection, where the\r
-               /// cut function is negative (if any).</param>\r
-               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
-               /// on this collection.</param>\r
-               /// <param name="high">Returns the least item in the collection, where the\r
-               /// cut function is positive (if any).</param>\r
-               /// <param name="highIsValid">True if the cut function is positive somewhere\r
-               /// on this collection.</param>\r
-               /// <returns></returns>\r
-               bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid);\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items greater than or equal to a supplied value.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               IDirectedEnumerable<T> RangeFrom(T bot);\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items between two supplied values.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               IDirectedEnumerable<T> RangeFromTo(T bot, T top);\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items less than a supplied value.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               IDirectedEnumerable<T> RangeTo(T top);\r
-\r
-\r
-               /// <summary>\r
-               /// Create a directed collection with the same items as this collection.\r
-               /// </summary>\r
-               /// <returns>The result directed collection.</returns>\r
-               IDirectedCollectionValue<T> RangeAll();\r
-\r
-\r
-               /// <summary>\r
-               /// Add all the items from another collection with an enumeration order that \r
-               /// is increasing in the items.\r
-               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
-               /// not to be in increasing order.\r
-               /// </summary>\r
-               /// <param name="items">The collection to add.</param>\r
-               void AddSorted(MSG.IEnumerable<T> items);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection above or at a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               void RemoveRangeFrom(T low);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               void RemoveRangeFromTo(T low, T hi);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               void RemoveRangeTo(T hi);\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A collection where items are maintained in sorted order together\r
-       /// with their indexes in that order.\r
-       /// </summary>\r
-       public interface IIndexedSorted<T>: ISorted<T>, IIndexed<T>\r
-       {\r
-               /// <summary>\r
-               /// Determine the number of items at or above a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               int CountFrom(T bot);\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               int CountFromTo(T bot, T top);\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               int CountTo(T top);\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items greater than or equal to a supplied value.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               new IDirectedCollectionValue<T> RangeFrom(T bot);\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items between two supplied values.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               new IDirectedCollectionValue<T> RangeFromTo(T bot, T top);\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items less than a supplied value.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               new IDirectedCollectionValue<T> RangeTo(T top);\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the items of this\r
-               /// indexed sorted collection satisfying a certain predicate.\r
-               /// </summary>\r
-               /// <param name="f">The filter delegate defining the predicate.</param>\r
-               /// <returns>The new indexed sorted collection.</returns>\r
-               IIndexedSorted<T> FindAll(Filter<T> f);\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the results of\r
-               /// mapping all items of this list.\r
-               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
-               /// the items of this collection (with respect to the two given comparison \r
-               /// relations).\r
-               /// </summary>\r
-               /// <param name="m">The delegate definging the map.</param>\r
-               /// <param name="c">The comparion relation to use for the result.</param>\r
-               /// <returns>The new sorted collection.</returns>\r
-               IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c);\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// The type of a sorted collection with persistence\r
-       /// </summary>\r
-       public interface IPersistentSorted<T>: ISorted<T>, IDisposable\r
-       {\r
-               /// <summary>\r
-               /// Make a (read-only) snap shot of this collection.\r
-               /// </summary>\r
-               /// <returns>The snap shot.</returns>\r
-               ISorted<T> Snapshot();\r
-    }\r
-\r
-\r
-\r
-       /*************************************************************************/\r
-       /// <summary>\r
-       /// A dictionary with keys of type K and values of type V. Equivalent to a\r
-       /// finite partial map from K to V.\r
-       /// </summary>\r
-       public interface IDictionary<K,V>: MSG.IEnumerable<KeyValuePair<K,V>>\r
-       {\r
-               /// <summary>\r
-               /// Indexer for dictionary.\r
-               /// <exception cref="InvalidOperationException"/> if no entry is found. \r
-               /// </summary>\r
-               /// <value>The value corresponding to the key</value>\r
-               V this[K key] { get; set;}\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>The number of entrues in the dictionary</value>\r
-               int Count { get; }\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True if dictionary is read  only</value>\r
-               bool IsReadOnly { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>The distinguished object to use for locking to synchronize multithreaded access</value>\r
-               object SyncRoot { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>A collection containg the all the keys of the dictionary</value>\r
-               ICollectionValue<K> Keys { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>A collection containing all the values of the dictionary</value>\r
-               ICollectionValue<V> Values { get;}\r
-\r
-\r
-               /// <summary>\r
-               /// Add a new (key, value) pair (a mapping) to the dictionary.\r
-               /// <exception cref="InvalidOperationException"/> if there already is an entry with the same key. \r
-               /// </summary>\r
-               /// <param name="key">Key to add</param>\r
-               /// <param name="val">Value to add</param>\r
-               void Add(K key, V val);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove an entry with a given key from the dictionary\r
-               /// </summary>\r
-               /// <param name="key">The key of the entry to remove</param>\r
-               /// <returns>True if an entry was found (and removed)</returns>\r
-               bool Remove(K key);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove an entry with a given key from the dictionary and report its value.\r
-               /// </summary>\r
-               /// <param name="key">The key of the entry to remove</param>\r
-               /// <param name="val">On exit, the value of the removed entry</param>\r
-               /// <returns>True if an entry was found (and removed)</returns>\r
-               bool Remove(K key, out V val);\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all entries from the dictionary\r
-               /// </summary>\r
-               void Clear();\r
-\r
-\r
-               /// <summary>\r
-               /// Check if there is an entry with a specified key\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <returns>True if key was found</returns>\r
-               bool Contains(K key);\r
-\r
-\r
-               /// <summary>\r
-               /// Check if there is an entry with a specified key and report the corresponding\r
-               /// value if found. This can be seen as a safe form of "val = this[key]".\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">On exit, the value of the entry</param>\r
-               /// <returns>True if key was found</returns>\r
-               bool Find(K key, out V val);        \r
-\r
-\r
-               /// <summary>\r
-               /// Look for a specific key in the dictionary and if found replace the value with a new one.\r
-               /// This can be seen as a non-adding version of "this[key] = val".\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">The new value</param>\r
-               /// <returns>True if key was found</returns>\r
-               bool Update(K key, V val);          //no-adding                                 \r
-\r
-\r
-               /// <summary>\r
-               /// Look for a specific key in the dictionary. If found, report the corresponding value,\r
-               /// else add an entry with the key and the supplied value.\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">On entry the value to add if the key is not found.\r
-               /// On exit the value found if any.</param>\r
-               /// <returns>True if key was found</returns>\r
-               bool FindOrAdd(K key, ref V val);   //mixture\r
-\r
-\r
-               /// <summary>\r
-               /// Update value in dictionary corresponding to key if found, else add new entry.\r
-               /// More general than "this[key] = val;" by reporting if key was found.\r
-               /// </summary>\r
-               /// <param name="key">The key to look for</param>\r
-               /// <param name="val">The value to add or replace with.</param>\r
-               /// <returns>True if key was found and value updated.</returns>\r
-               bool UpdateOrAdd(K key, V val);     \r
-\r
-\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this dictionary.\r
-               /// Only avaliable in DEBUG builds???\r
-               /// </summary>\r
-               /// <returns>True if check does not fail.</returns>\r
-               bool Check();\r
-       }\r
-\r
-\r
-\r
-       /// <summary>\r
-       /// A dictionary with sorted keys.\r
-       /// </summary>\r
-       public interface ISortedDictionary<K,V>: IDictionary<K,V>\r
-       {\r
-               /// <summary>\r
-               /// Find the entry with the largest key less than a given key.\r
-               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
-               /// </summary>\r
-               /// <param name="key">The key to compare to</param>\r
-               /// <returns>The entry</returns>\r
-               KeyValuePair<K,V> Predecessor(K key);\r
-\r
-\r
-               /// <summary>\r
-               /// Find the entry with the least key greater than a given key.\r
-               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
-               /// </summary>\r
-               /// <param name="key">The key to compare to</param>\r
-               /// <returns>The entry</returns>\r
-               KeyValuePair<K,V> Successor(K key);\r
-\r
-\r
-               /// <summary>\r
-               /// Find the entry with the largest key less than or equal to a given key.\r
-               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
-               /// </summary>\r
-               /// <param name="key">The key to compare to</param>\r
-               /// <returns>The entry</returns>\r
-               KeyValuePair<K,V> WeakPredecessor(K key);\r
-\r
-\r
-               /// <summary>\r
-               /// Find the entry with the least key greater than or equal to a given key.\r
-               /// <exception cref="InvalidOperationException"/> if there is no such entry. \r
-               /// </summary>\r
-               /// <param name="key">The key to compare to</param>\r
-               /// <returns>The entry</returns>\r
-               KeyValuePair<K,V> WeakSuccessor(K key);\r
-       }\r
-\r
-\r
-\r
-       /*******************************************************************/\r
-       /// <summary>\r
-       /// The type of an item comparer\r
-       /// <p>Implementations of this interface must asure that the method is self-consistent\r
-       /// and defines a sorting order on items, or state precise conditions under which this is true.</p>\r
-       /// <p>Implementations <b>must</b> assure that repeated calls of\r
-       /// the method to the same (in reference or binary identity sense) arguments \r
-       /// will return values with the same sign (-1, 0 or +1), or state precise conditions\r
-       /// under which the user \r
-       /// can be assured repeated calls will return the same sign.</p>\r
-       /// <p>Implementations of this interface must always return values from the method\r
-       /// and never throw exceptions.</p>\r
-       /// <p>This interface is identical to System.Collections.Generic.IComparer&lt;T&gt;</p>\r
-       /// </summary>\r
-       public interface IComparer<T>\r
-       {\r
-               /// <summary>\r
-               /// Compare two items with respect to this item comparer\r
-               /// </summary>\r
-               /// <param name="a">First item</param>\r
-               /// <param name="b">Second item</param>\r
-               /// <returns>Positive if a is greater than b, 0 if they are equal, negative if a is less than b</returns>\r
-               int Compare(T a, T b);\r
-       }\r
-\r
-\r
-    /*\r
-       /// <summary>\r
-       /// The interface for an item that is generic comparable.\r
-       /// <p>Implementations of this interface <b>must</b> assure that repeated calls of\r
-       /// the method to the same (in reference or binary identity sense) object and argument\r
-       /// will return values with the same sign (-1, 0 or +1), or state precise conditions\r
-       /// under which the user \r
-       /// can be assured repeated calls will return the same sign.</p>\r
-       /// <p>Implementations of this interface must always return values from the method\r
-       /// and never throw exceptions.</p>\r
-       /// <p>This interface is identical to System.Collections.Generic.IComparable&lt;T&gt;</p>\r
-       /// </summary>\r
-       public interface unIComparable<T> //: System.IComparable<T>\r
-       {\r
-               /// <summary>\r
-               /// Compare this item to another one\r
-               /// </summary>\r
-               /// <param name="that">The other item</param>\r
-               /// <returns>Positive if this is greater than , 0 if equal to, negative if less than that</returns>\r
-               int CompareTo(T that);\r
-       }\r
-    */\r
-\r
-\r
-       /// <summary>\r
-       /// The type of an item hasher. \r
-       /// <p>Implementations of this interface <b>must</b> assure that the methods are \r
-       /// consistent, i.e. that whenever two items i1 and i2 satisfies that Equals(i1,i2)\r
-       /// returns true, then GetHashCode returns the same values for i1 and i2.</p>\r
-       /// <p>Implementations of this interface <b>must</b> assure that repeated calls of\r
-       /// the methods to the same (in reference or binary identity sense) arguments \r
-       /// will return the same values, or state precise conditions under which the user \r
-       /// can be assured repeated calls will return the same values.</p>\r
-       /// <p>Implementations of this interface must always return values from the methods\r
-       /// and never throw exceptions.</p>\r
-       /// <p>This interface is similar in function to System.IKeyComparer&lt;T&gt;</p>\r
-       /// </summary>\r
-       public interface IHasher<T>\r
-       {\r
-               /// <summary>\r
-               /// Get the hash code with respect to this item hasher\r
-               /// </summary>\r
-               /// <param name="item">The item</param>\r
-               /// <returns>The hash code</returns>\r
-               int GetHashCode(T item);\r
-\r
-\r
-               /// <summary>\r
-               /// Check if two items are equal with respect to this item hasher\r
-               /// </summary>\r
-               /// <param name="i1">first item</param>\r
-               /// <param name="i2">second item</param>\r
-               /// <returns>True if equal</returns>\r
-               bool Equals(T i1, T i2);\r
-       }\r
-}\r
-#endif\r
index 54331d01057c841a39b1d8f3159203b5c7bf0ddd..daf3c451984fba152f6bc546d18a23787df50cf7 100644 (file)
@@ -1,18 +1,18 @@
-arrays/ArrayList.cs
-arrays/HashedArray.cs
-arrays/SortedArray.cs
-AssemblyInfo.cs
-Builder.cs
-Collections.cs
-Dictionaries.cs
-hashing/HashBag.cs
-hashing/HashDictionary.cs
-hashing/HashTable.cs
-heaps/IntervalHeap.cs
-Interfaces.cs
-linkedlists/HashedLinkedLIst.cs
-linkedlists/LinkedList.cs
-trees/RedBlackTree.cs
-trees/RedBlackTreeBag.cs
-trees/TreeDictionary.cs
-Wrappers.cs
+C5/arrays/ArrayList.cs
+C5/arrays/HashedArray.cs
+C5/arrays/SortedArray.cs
+C5/AssemblyInfo.cs
+C5/Builder.cs
+C5/Collections.cs
+C5/Dictionaries.cs
+C5/hashing/HashBag.cs
+C5/hashing/HashDictionary.cs
+C5/hashing/HashTable.cs
+C5/heaps/IntervalHeap.cs
+C5/Interfaces.cs
+C5/linkedlists/HashedLinkedLIst.cs
+C5/linkedlists/LinkedList.cs
+C5/trees/RedBlackTree.cs
+C5/trees/RedBlackTreeBag.cs
+C5/trees/TreeDictionary.cs
+C5/Wrappers.cs
diff --git a/mcs/class/Mono.C5/Wrappers.cs b/mcs/class/Mono.C5/Wrappers.cs
deleted file mode 100644 (file)
index fed4fa7..0000000
+++ /dev/null
@@ -1,1594 +0,0 @@
-#if NET_2_0
-/*
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-*/
-
-using System;
-using System.Diagnostics;
-using MSG = System.Collections.Generic;
-using SC = System.Collections;
-namespace C5
-{
-       /// <summary>
-       /// A read-only wrapper class for a generic enumerator
-       /// </summary>
-       public class GuardedEnumerator<T>: MSG.IEnumerator<T>
-       {
-               #region Fields
-
-               MSG.IEnumerator<T> enumerator;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Create a wrapper around a generic enumerator
-               /// </summary>
-               /// <param name="enumerator">The enumerator to wrap</param>
-               public GuardedEnumerator(MSG.IEnumerator<T> enumerator)
-               { this.enumerator = enumerator; }
-
-               #endregion
-
-               #region IEnumerator<T> Members
-
-               /// <summary>
-               /// Move wrapped enumerator to next item, or the first item if
-               /// this is the first call to MoveNext. 
-               /// </summary>
-               /// <returns>True if enumerator is valid now</returns>
-               public bool MoveNext() { return enumerator.MoveNext(); }
-
-
-               /// <summary>
-               /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
-               /// </summary>
-               /// <value>The current item of the wrapped enumerator.</value>
-               public T Current { get { return enumerator.Current; } }
-
-               void SC.IEnumerator.Reset ()
-               {
-                       enumerator.Reset ();
-               }
-
-               object SC.IEnumerator.Current {
-                       get { return enumerator.Current; }
-               }
-
-               #endregion
-
-               #region IDisposable Members
-
-               /// <summary>
-               /// Dispose wrapped enumerator
-               /// </summary>
-               public void Dispose() { enumerator.Dispose(); }
-
-               #endregion
-       }
-
-
-
-       /// <summary>
-       /// A read-only wrapper class for a generic enumerable
-       ///
-       /// <p>This is mainly interesting as a base of other guard classes</p>
-       /// </summary>
-       public class GuardedEnumerable<T>: MSG.IEnumerable<T>
-       {
-               #region Fields
-
-               MSG.IEnumerable<T> enumerable;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap an enumerable in a read-only wrapper
-               /// </summary>
-               /// <param name="enumerable">The enumerable to wrap</param>
-               public GuardedEnumerable(MSG.IEnumerable<T> enumerable)
-               { this.enumerable = enumerable; }
-
-               #endregion
-
-               #region MSG.IEnumerable<T> Members
-
-               /// <summary>
-               /// Get an enumerator from the wrapped enumerable
-               /// </summary>
-               /// <returns>The enumerator (itself wrapped)</returns>
-               public MSG.IEnumerator<T> GetEnumerator()
-               { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
-
-               #endregion
-
-               SC.IEnumerator SC.IEnumerable.GetEnumerator()
-               { return GetEnumerator (); }
-       }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for a generic directed enumerable
-       ///
-       /// <p>This is mainly interesting as a base of other guard classes</p>
-       /// </summary>
-       public class GuardedDirectedEnumerable<T>: GuardedEnumerable<T>, IDirectedEnumerable<T>
-       {
-               #region Fields
-
-               IDirectedEnumerable<T> directedenumerable;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a directed enumerable in a read-only wrapper
-               /// </summary>
-               /// <param name="directedenumerable">the collection to wrap</param>
-               public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
-                       : base(directedenumerable)
-               { this.directedenumerable = directedenumerable; }
-
-               #endregion
-
-               #region IDirectedEnumerable<T> Members
-
-               /// <summary>
-               /// Get a enumerable that enumerates the wrapped collection in the opposite direction
-               /// </summary>
-               /// <returns>The mirrored enumerable</returns>
-               public IDirectedEnumerable<T> Backwards()
-               { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
-
-
-               /// <summary>
-               /// <code>Forwards</code> if same, else <code>Backwards</code>
-               /// </summary>
-               /// <value>The enumeration direction relative to the original collection.</value>
-               public EnumerationDirection Direction
-               { get { return directedenumerable.Direction; } }
-
-               #endregion
-       }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for an ICollectionValue&lt;T&gt;
-       ///
-       /// <p>This is mainly interesting as a base of other guard classes</p>
-       /// </summary>
-       public class GuardedCollectionValue<T>: GuardedEnumerable<T>, ICollectionValue<T>
-       {
-               #region Fields
-
-               ICollectionValue<T> collection;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper
-               /// </summary>
-               /// <param name="collection">the collection to wrap</param>
-               public GuardedCollectionValue(ICollectionValue<T> collection) : base(collection)
-               { this.collection = collection; }
-
-               #endregion
-
-               #region ICollection<T> Members
-
-               /// <summary>
-               /// Get the size of the wrapped collection
-               /// </summary>
-               /// <value>The size</value>
-               public int Count { get { return collection.Count; } }
-
-        /// <summary>
-        /// The value is symbolic indicating the type of asymptotic complexity
-        /// in terms of the size of this collection (worst-case or amortized as
-        /// relevant).
-        /// </summary>
-        /// <value>A characterization of the speed of the 
-        /// <code>Count</code> property in this collection.</value>
-        public Speed CountSpeed { get { return collection.CountSpeed; } }
-
-        /// <summary>
-               /// Copy the items of the wrapped collection to an array
-               /// </summary>
-               /// <param name="a">The array</param>
-               /// <param name="i">Starting offset</param>
-               public void CopyTo(T[] a, int i) { collection.CopyTo(a, i); }
-
-        /// <summary>
-        /// Create an array from the items of the wrapped collection
-        /// </summary>
-        /// <returns>The array</returns>
-        public T[] ToArray() { return collection.ToArray(); }
-
-        /// <summary>
-        /// Apply a delegate to all items of the wrapped enumerable.
-        /// </summary>
-        /// <param name="a">The delegate to apply</param>
-        //TODO: change this to throw an exception?
-        public void Apply(Applier<T> a) { collection.Apply(a); }
-
-
-        /// <summary>
-        /// Check if there exists an item  that satisfies a
-        /// specific predicate in the wrapped enumerable.
-        /// </summary>
-        /// <param name="filter">A filter delegate 
-        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
-        /// <returns>True is such an item exists</returns>
-        public bool Exists(Filter<T> filter) { return collection.Exists(filter); }
-
-
-        /// <summary>
-        /// Check if all items in the wrapped enumerable satisfies a specific predicate.
-        /// </summary>
-        /// <param name="filter">A filter delegate 
-        /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
-        /// <returns>True if all items satisfies the predicate</returns>
-        public bool All(Filter<T> filter) { return collection.All(filter); }
-        #endregion
-    }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for a directed collection
-       ///
-       /// <p>This is mainly interesting as a base of other guard classes</p>
-       /// </summary>
-       public class GuardedDirectedCollectionValue<T>: GuardedCollectionValue<T>, IDirectedCollectionValue<T>
-       {
-               #region Fields
-
-               IDirectedCollectionValue<T> directedcollection;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a directed collection in a read-only wrapper
-               /// </summary>
-               /// <param name="directedcollection">the collection to wrap</param>
-               public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection) : 
-                       base(directedcollection)
-               { this.directedcollection = directedcollection; }
-
-               #endregion
-
-               #region IDirectedCollection<T> Members
-
-               /// <summary>
-               /// Get a collection that enumerates the wrapped collection in the opposite direction
-               /// </summary>
-               /// <returns>The mirrored collection</returns>
-               public IDirectedCollectionValue<T> Backwards()
-               { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
-
-               #endregion
-
-               #region IDirectedEnumerable<T> Members
-
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
-               { return Backwards(); }
-
-
-               /// <summary>
-               /// <code>Forwards</code> if same, else <code>Backwards</code>
-               /// </summary>
-               /// <value>The enumeration direction relative to the original collection.</value>
-               public EnumerationDirection Direction
-               { get { return directedcollection.Direction; } }
-
-               #endregion
-       }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for an ICollection&lt;T&gt;.
-       /// <see cref="T:C5.ICollection!1"/>
-       ///
-       /// <p>Suitable for wrapping hash tables, <see cref="T:C5.HashSet!1"/>
-       /// and <see cref="T:C5.HashBag!1"/>  </p>
-       /// </summary>
-       public class GuardedCollection<T>: GuardedCollectionValue<T>, ICollection<T>
-       {
-               #region Fields
-
-               ICollection<T> collection;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap an ICollection&lt;T&gt; in a read-only wrapper
-               /// </summary>
-               /// <param name="collection">the collection to wrap</param>
-               public GuardedCollection(ICollection<T> collection)
-                       :base(collection)
-               { this.collection = collection; }
-
-               #endregion
-
-               #region ICollection<T> Members
-
-               /// <summary>
-               /// (This is a read-only wrapper)
-               /// </summary>
-               /// <value>True</value>
-               public bool IsReadOnly { get { return true; } }
-
-
-               /// <summary> </summary>
-               /// <value>Speed of wrapped collection</value>
-               public Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
-
-
-               int ICollection<T>.GetHashCode()
-               { return ((ICollection<T>)collection).GetHashCode(); }
-
-
-               bool ICollection<T>.Equals(ICollection<T> that)
-               { return ((ICollection<T>)collection).Equals(that); }
-
-
-               /// <summary>
-               /// Check if an item is in the wrapped collection
-               /// </summary>
-               /// <param name="item">The item</param>
-               /// <returns>True if found</returns>
-               public bool Contains(T item) { return collection.Contains(item); }
-
-
-               /// <summary>
-               /// Count the number of times an item appears in the wrapped collection
-               /// </summary>
-               /// <param name="item">The item</param>
-               /// <returns>The number of copies</returns>
-               public int ContainsCount(T item) { return collection.ContainsCount(item); }
-
-
-               /// <summary>
-               /// Check if all items in the argument is in the wrapped collection
-               /// </summary>
-               /// <param name="items">The items</param>
-               /// <returns>True if so</returns>
-               public bool ContainsAll(MSG.IEnumerable<T> items) { return collection.ContainsAll(items); }
-
-
-               /// <summary>
-               /// Search for an item in the wrapped collection
-               /// </summary>
-               /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
-               /// <returns></returns>
-               public bool Find(ref T item) { return collection.Find(ref item); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public bool FindOrAdd(ref T item)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public bool Update(T item)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public bool UpdateOrAdd(T item)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public bool Remove(T item)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public bool RemoveWithReturn(ref T item)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               public void RemoveAllCopies(T item)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="items"></param>
-               public void RemoveAll(MSG.IEnumerable<T> items)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               public void Clear()
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="items"></param>
-               public void RetainAll(MSG.IEnumerable<T> items)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// Check  wrapped collection for internal consistency
-               /// </summary>
-               /// <returns>True if check passed</returns>
-               public bool Check() { return collection.Check(); }
-
-               #endregion
-
-               #region ISink<T> Members
-
-               /// <summary> </summary>
-               /// <value>False if wrapped collection has set semantics</value>
-        public bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
-
-
-        /// <summary> </summary>
-               /// <value>The sync root of the wrapped collection</value>
-               public object SyncRoot { get { return collection.SyncRoot; } }
-
-
-               /// <summary> </summary>
-               /// <value>True if wrapped collection is empty</value>
-               public bool IsEmpty { get { return collection.IsEmpty; } }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public bool Add(T item)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-        /// <summary>
-        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-        /// </summary>
-        /// <param name="items"></param>
-        public void AddAll(MSG.IEnumerable<T> items)
-        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-        /// <summary>
-        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-        /// </summary>
-        /// <param name="items"></param>
-        /*public*/ void C5.IExtensible<T>.AddAll<U>(MSG.IEnumerable<U> items) //where U : T
-        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-        #endregion
-    }
-
-
-       /// <summary>
-       /// A read-only wrapper for a sequenced collection
-       ///
-       /// <p>This is mainly interesting as a base of other guard classes</p>
-       /// </summary>
-       public class GuardedSequenced<T>: GuardedCollection<T>, ISequenced<T>
-       {
-               #region Fields
-
-               ISequenced<T> sequenced;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a sequenced collection in a read-only wrapper
-               /// </summary>
-               /// <param name="sorted"></param>
-               public GuardedSequenced(ISequenced<T> sorted):base(sorted) { this.sequenced = sorted; }
-
-               #endregion
-
-               #region ISequenced<T> Members
-
-               int ISequenced<T>.GetHashCode()
-               { return ((ISequenced<T>)sequenced).GetHashCode(); }
-
-
-               bool ISequenced<T>.Equals(ISequenced<T> that)
-               { return ((ISequenced<T>)sequenced).Equals(that); }
-
-               #endregion
-
-               #region IEditableCollection<T> Members
-
-               int ICollection<T>.GetHashCode()
-               { return ((ICollection<T>)sequenced).GetHashCode(); }
-
-
-               bool ICollection<T>.Equals(ICollection<T> that)
-               { return ((ICollection<T>)sequenced).Equals(that); }
-
-               #endregion
-
-               #region IDirectedCollection<T> Members
-
-               /// <summary>
-               /// Get a collection that enumerates the wrapped collection in the opposite direction
-               /// </summary>
-               /// <returns>The mirrored collection</returns>
-               public IDirectedCollectionValue<T> Backwards()
-               { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
-
-               #endregion
-
-               #region IDirectedEnumerable<T> Members
-
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
-               { return Backwards(); }
-
-
-
-               /// <summary>
-               /// <code>Forwards</code> if same, else <code>Backwards</code>
-               /// </summary>
-               /// <value>The enumeration direction relative to the original collection.</value>
-               public EnumerationDirection Direction
-               { get { return EnumerationDirection.Forwards; } }
-
-               #endregion
-       }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for a sorted collection
-       ///
-       /// <p>This is mainly interesting as a base of other guard classes</p>
-       /// </summary>
-       public class GuardedSorted<T>: GuardedSequenced<T>, ISorted<T>
-       {
-               #region Fields
-
-               ISorted<T> sorted;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a sorted collection in a read-only wrapper
-               /// </summary>
-               /// <param name="sorted"></param>
-               public GuardedSorted(ISorted<T> sorted):base(sorted) { this.sorted = sorted; }
-
-               #endregion
-
-        #region IEditableCollection Members
-
-               int ICollection<T>.GetHashCode()
-               { return ((ICollection<T>)sorted).GetHashCode(); }
-
-
-               bool ICollection<T>.Equals(ICollection<T> that)
-               { return ((ICollection<T>)sorted).Equals(that); }
-
-               #endregion
-
-               #region ISequenced<T> Members
-
-               int ISequenced<T>.GetHashCode()
-               { return ((ISequenced<T>)sorted).GetHashCode(); }
-
-
-               bool ISequenced<T>.Equals(ISequenced<T> that)
-               { return ((ISequenced<T>)sorted).Equals(that); }
-
-
-               #endregion
-
-               #region ISorted<T> Members
-
-               /// <summary>
-               /// Find the predecessor of the item in the wrapped sorted collection
-               /// </summary>
-               /// <param name="item">The item</param>
-               /// <returns>The predecessor</returns>
-               public T Predecessor(T item) { return sorted.Predecessor(item); }
-
-
-               /// <summary>
-               /// Find the Successor of the item in the wrapped sorted collection
-               /// </summary>
-               /// <param name="item">The item</param>
-               /// <returns>The Successor</returns>
-               public T Successor(T item) { return sorted.Successor(item); }
-
-
-               /// <summary>
-               /// Find the weak predecessor of the item in the wrapped sorted collection
-               /// </summary>
-               /// <param name="item">The item</param>
-               /// <returns>The weak predecessor</returns>
-               public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
-
-
-               /// <summary>
-               /// Find the weak Successor of the item in the wrapped sorted collection
-               /// </summary>
-               /// <param name="item">The item</param>
-               /// <returns>The weak Successor</returns>
-               public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
-
-
-               /// <summary>
-               /// Run Cut on the wrapped sorted collection
-               /// </summary>
-               /// <param name="c"></param>
-               /// <param name="low"></param>
-               /// <param name="lval"></param>
-               /// <param name="high"></param>
-               /// <param name="hval"></param>
-               /// <returns></returns>
-               public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
-               { return sorted.Cut(c, out low, out lval, out high, out hval); }
-
-
-               /// <summary>
-               /// Get the specified range from the wrapped collection. 
-               /// (The current implementation erroneously does not wrap the result.)
-               /// </summary>
-               /// <param name="bot"></param>
-               /// <returns></returns>
-               public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
-
-
-               /// <summary>
-               /// Get the specified range from the wrapped collection. 
-               /// (The current implementation erroneously does not wrap the result.)
-               /// </summary>
-               /// <param name="bot"></param>
-               /// <param name="top"></param>
-               /// <returns></returns>
-               public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
-               { return sorted.RangeFromTo(bot, top); }
-
-
-               /// <summary>
-               /// Get the specified range from the wrapped collection. 
-               /// (The current implementation erroneously does not wrap the result.)
-               /// </summary>
-               /// <param name="top"></param>
-               /// <returns></returns>
-               public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
-
-
-               /// <summary>
-               /// Get the specified range from the wrapped collection. 
-               /// (The current implementation erroneously does not wrap the result.)
-               /// </summary>
-               /// <returns></returns>
-               public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="items"></param>
-               public void AddSorted(MSG.IEnumerable<T> items)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="low"></param>
-               public void RemoveRangeFrom(T low)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="low"></param>
-               /// <param name="hi"></param>
-               public void RemoveRangeFromTo(T low, T hi)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="hi"></param>
-               public void RemoveRangeTo(T hi)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-               #endregion
-
-               #region IPriorityQueue<T> Members
-
-               /// <summary>
-               /// Find the minimum of the wrapped collection
-               /// </summary>
-               /// <returns>The minimum</returns>
-               public T FindMin() { return sorted.FindMin(); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <returns></returns>
-               public T DeleteMin()
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// Find the maximum of the wrapped collection
-               /// </summary>
-               /// <returns>The maximum</returns>
-               public T FindMax() { return sorted.FindMax(); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <returns></returns>
-               public T DeleteMax()
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-        /// <summary>
-        /// The comparer object supplied at creation time for the underlying collection
-        /// </summary>
-        /// <value>The comparer</value>
-        public IComparer<T> Comparer { get { return sorted.Comparer; } }
-        #endregion
-
-
-               #region IDirectedEnumerable<T> Members
-
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
-               { return Backwards(); }
-
-               #endregion
-       }
-
-
-
-       /// <summary>
-       /// Read-only wrapper for indexed sorted collections
-       ///
-       /// <p>Suitable for wrapping TreeSet, TreeBag and SortedArray</p>
-       /// </summary>
-       public class GuardedIndexedSorted<T>: GuardedSorted<T>, IIndexedSorted<T>
-       {
-               #region Fields
-
-               IIndexedSorted<T> indexedsorted;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap an indexed sorted collection in a read-only wrapper
-               /// </summary>
-               /// <param name="list">the indexed sorted collection</param>
-               public GuardedIndexedSorted(IIndexedSorted<T> list):base(list)
-               { this.indexedsorted = list; }
-
-               #endregion
-
-               #region IIndexedSorted<T> Members
-
-               /// <summary>
-               /// Get the specified range from the wrapped collection. 
-               /// (The current implementation erroneously does not wrap the result.)
-               /// </summary>
-               /// <param name="bot"></param>
-               /// <returns></returns>
-               public new IDirectedCollectionValue<T> RangeFrom(T bot)
-               { return indexedsorted.RangeFrom(bot); }
-
-
-               /// <summary>
-               /// Get the specified range from the wrapped collection. 
-               /// (The current implementation erroneously does not wrap the result.)
-               /// </summary>
-               /// <param name="bot"></param>
-               /// <param name="top"></param>
-               /// <returns></returns>
-               public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
-               { return indexedsorted.RangeFromTo(bot, top); }
-
-
-               /// <summary>
-               /// Get the specified range from the wrapped collection. 
-               /// (The current implementation erroneously does not wrap the result.)
-               /// </summary>
-               /// <param name="top"></param>
-               /// <returns></returns>
-               public new IDirectedCollectionValue<T> RangeTo(T top)
-               { return indexedsorted.RangeTo(top); }
-
-
-               /// <summary>
-               /// Report the number of items in the specified range of the wrapped collection
-               /// </summary>
-               /// <param name="bot"></param>
-               /// <returns></returns>
-               public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
-
-
-               /// <summary>
-               /// Report the number of items in the specified range of the wrapped collection
-               /// </summary>
-               /// <param name="bot"></param>
-               /// <param name="top"></param>
-               /// <returns></returns>
-               public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
-
-
-               /// <summary>
-               /// Report the number of items in the specified range of the wrapped collection
-               /// </summary>
-               /// <param name="top"></param>
-               /// <returns></returns>
-               public int CountTo(T top) { return indexedsorted.CountTo(top); }
-
-
-               /// <summary>
-               /// Run FindAll on the wrapped collection with the indicated filter.
-               /// The result will <b>not</b> be read-only.
-               /// </summary>
-               /// <param name="f"></param>
-               /// <returns></returns>
-               public IIndexedSorted<T> FindAll(Filter<T> f)
-               { return indexedsorted.FindAll(f); }
-
-
-               /// <summary>
-               /// Run Map on the wrapped collection with the indicated mapper.
-               /// The result will <b>not</b> be read-only.
-               /// </summary>
-               /// <param name="m"></param>
-               /// <param name="c">The comparer to use in the result</param>
-               /// <returns></returns>
-               public IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c)
-               { return indexedsorted.Map<V>(m, c); }
-
-               #endregion
-
-               #region IIndexed<T> Members
-
-               /// <summary>
-               /// 
-               /// </summary>
-               /// <value>The i'th item of the wrapped sorted collection</value>
-               public T this[int i] { get { return indexedsorted[i]; } }
-
-
-               /// <summary> </summary>
-               /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
-               public IDirectedCollectionValue<T> this[int start, int end]
-               { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
-
-
-               /// <summary>
-               /// Find the (first) index of an item in the wrapped collection
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
-
-
-               /// <summary>
-               /// Find the last index of an item in the wrapped collection
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="i"></param>
-               /// <returns></returns>
-               public T RemoveAt(int i)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="start"></param>
-               /// <param name="count"></param>
-               public void RemoveInterval(int start, int count)
-               { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-               #endregion
-
-               #region ISequenced<T> Members
-
-               int ISequenced<T>.GetHashCode()
-               { return ((ISequenced<T>)indexedsorted).GetHashCode(); }
-
-
-               bool ISequenced<T>.Equals(ISequenced<T> that)
-               { return ((ISequenced<T>)indexedsorted).Equals(that); }
-
-               #endregion
-
-               #region IEditableCollection<T> Members
-
-               int ICollection<T>.GetHashCode()
-               { return ((ICollection<T>)indexedsorted).GetHashCode(); }
-
-
-               bool ICollection<T>.Equals(ICollection<T> that)
-               { return ((ICollection<T>)indexedsorted).Equals(that); }
-
-               #endregion
-
-               #region IDirectedEnumerable<T> Members
-
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
-               { return Backwards(); }
-
-               #endregion
-       }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for a generic list collection
-       /// <p>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
-       /// <see cref="T:C5.LinkedList!1"/>, 
-       /// <see cref="T:C5.HashedLinkedList!1"/>, 
-       /// <see cref="T:C5.ArrayList!1"/> or
-       /// <see cref="T:C5.HashedArray!1"/>.
-       /// </p>
-       /// </summary>
-       public class GuardedList<T>: GuardedSequenced<T>, IList<T>
-       {
-               #region Fields
-
-               IList<T> list;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a list in a read-only wrapper
-               /// </summary>
-               /// <param name="list">The list</param>
-               public GuardedList(IList<T> list) : base (list) { this.list = list; }
-
-               #endregion
-
-               #region IList<T> Members
-
-               /// <summary>
-               /// 
-               /// </summary>
-               /// <value>The first item of the wrapped list</value>
-               public T First { get { return list.First; } }
-
-
-               /// <summary>
-               /// 
-               /// </summary>
-               /// <value>The last item of the wrapped list</value>
-               public T Last { get { return list.Last; } }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> if used as setter
-               /// </summary>
-               /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
-               public bool FIFO
-               {
-                       get { return list.FIFO; }
-                       set { throw new InvalidOperationException("List is read only"); }
-               }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> if used as setter
-               /// </summary>
-               /// <value>The i'th item of the wrapped list</value>
-               public T this[int i]
-               {
-                       get { return list[i]; }
-                       set { throw new InvalidOperationException("List is read only"); }
-               }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="i"></param>
-               /// <param name="item"></param>
-               public void Insert(int i, T item)
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               public void InsertFirst(T item)
-               { throw new InvalidOperationException("List is read only"); }
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               public void InsertLast(T item)
-               { throw new InvalidOperationException("List is read only"); }
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <param name="target"></param>
-               public void InsertBefore(T item, T target)
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="item"></param>
-               /// <param name="target"></param>
-               public void InsertAfter(T item, T target)
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="i"></param>
-               /// <param name="items"></param>
-               public void InsertAll(int i, MSG.IEnumerable<T> items)
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
-               /// </summary>
-               /// <param name="filter">The filter to use</param>
-               /// <returns></returns>
-               public IList<T> FindAll(Filter<T> filter) { return list.FindAll(filter); }
-
-
-               /// <summary>
-               /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
-               /// </summary>
-        /// <typeparam name="V">The type of items of the new list</typeparam>
-        /// <param name="mapper">The mapper to use.</param>
-        /// <returns>The mapped list</returns>
-        public IList<V> Map<V>(Mapper<T, V> mapper) { return list.Map<V>(mapper); }
-
-        /// <summary>
-        /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
-        /// </summary>
-        /// <typeparam name="V">The type of items of the new list</typeparam>
-        /// <param name="mapper">The delegate defining the map.</param>
-        /// <param name="hasher">The hasher to use for the new list</param>
-        /// <returns>The new list.</returns>
-        public IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher) { return list.Map<V>(mapper, hasher); }
-
-        /// <summary>
-        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <returns></returns>
-               public T Remove() { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <returns></returns>
-               public T RemoveFirst() { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <returns></returns>
-               public T RemoveLast() { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// Create the indicated view on the wrapped list and wrap it read-only.
-               /// </summary>
-               /// <param name="start"></param>
-               /// <param name="count"></param>
-               /// <returns></returns>
-               public IList<T> View(int start, int count)
-               {
-                       return new GuardedList<T>(list.View(start, count));
-               }
-
-
-               //TODO: This is wrong!
-               /// <summary>
-               /// (This is wrong functionality)
-               /// </summary>
-        /// <value>The wrapped underlying list of the wrapped view </value>
-        public IList<T> Underlying { get { return new GuardedList<T>(list.Underlying); } }
-
-
-        /// <summary>
-               /// 
-               /// </summary>
-               /// <value>The offset of the wrapped list as a view.</value>
-               public int Offset { get { return list.Offset; } }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="offset"></param>
-               public void Slide(int offset) { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="offset"></param>
-               /// <param name="size"></param>
-               public void Slide(int offset, int size) { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               public void Reverse() { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="start"></param>
-               /// <param name="count"></param>
-               public void Reverse(int start, int count)
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// Check if wrapped list is sorted
-               /// </summary>
-               /// <param name="c">The sorting order to use</param>
-               /// <returns>True if sorted</returns>
-               public bool IsSorted(IComparer<T> c) { return list.IsSorted(c); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="c"></param>
-               public void Sort(IComparer<T> c)
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               public void Shuffle()
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="rnd"></param>
-               public void Shuffle(Random rnd)
-               { throw new InvalidOperationException("List is read only"); }
-
-               #endregion
-
-               #region IIndexed<T> Members
-
-               /// <summary> </summary>
-               /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
-               public IDirectedCollectionValue<T> this[int start, int end]
-               { get { return new GuardedDirectedCollectionValue<T>(list[start, end]); } }
-
-
-               /// <summary>
-               /// Find the (first) index of an item in the wrapped collection
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public int IndexOf(T item) { return list.IndexOf(item); }
-
-
-               /// <summary>
-               /// Find the last index of an item in the wrapped collection
-               /// </summary>
-               /// <param name="item"></param>
-               /// <returns></returns>
-               public int LastIndexOf(T item) { return list.LastIndexOf(item); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="i"></param>
-               /// <returns></returns>
-               public T RemoveAt(int i)
-               { throw new InvalidOperationException("List is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="start"></param>
-               /// <param name="count"></param>
-               public void RemoveInterval(int start, int count)
-               { throw new InvalidOperationException("List is read only"); }
-
-               #endregion
-
-               #region ISequenced<T> Members
-
-               int ISequenced<T>.GetHashCode()
-               { return ((ISequenced<T>)list).GetHashCode(); }
-
-
-               bool ISequenced<T>.Equals(ISequenced<T> that)
-               { return ((ISequenced<T>)list).Equals(that); }
-
-               #endregion
-
-               #region IEditableCollection<T> Members
-
-               int ICollection<T>.GetHashCode()
-               { return ((ICollection<T>)list).GetHashCode(); }
-
-
-               bool ICollection<T>.Equals(ICollection<T> that)
-               { return ((ICollection<T>)list).Equals(that); }
-
-               #endregion
-
-               #region IDirectedEnumerable<T> Members
-
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
-               { return Backwards(); }
-
-               #endregion
-
-        #region IStack<T> Members
-
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-        /// <returns>-</returns>
-        public void Push(T item)
-        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-        /// <returns>-</returns>
-        public T Pop()
-        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-                #endregion
-
-        #region IQueue<T> Members
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-        /// <returns>-</returns>
-        public void EnQueue(T item)
-        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-        /// <returns>-</returns>
-        public T DeQueue()
-        { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
-
-                #endregion
-
-    }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for a dictionary.
-       ///
-       /// <p>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary!2"/></p>
-       /// </summary>
-       public class GuardedDictionary<K,V>: GuardedEnumerable<KeyValuePair<K,V>>, IDictionary<K,V>
-       {
-               #region Fields
-
-               IDictionary<K,V> dict;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a dictionary in a read-only wrapper
-               /// </summary>
-               /// <param name="dict">the dictionary</param>
-               public GuardedDictionary(IDictionary<K,V> dict) : base(dict) { this.dict = dict; }
-
-               #endregion
-
-               #region IDictionary<K,V> Members
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a
-               /// read-only wrappper if used as a setter
-               /// </summary>
-               /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
-               public V this[K key]
-               {
-                       get { return dict[key]; }
-                       set { throw new InvalidOperationException("Dictionary is read only"); }
-               }
-
-
-               /// <summary> </summary>
-               /// <value>The size of the wrapped dictionary</value>
-               public int Count { get { return dict.Count; } }
-
-
-               /// <summary>
-               /// (This is a read-only wrapper)
-               /// </summary>
-               /// <value>True</value>
-               public bool IsReadOnly { get { return true; } }
-
-
-               /// <summary> </summary>
-               /// <value>The sync root of the wrapped dictionary</value>
-               public object SyncRoot { get { return dict.SyncRoot; } }
-
-
-               //TODO: guard with a read-only wrapper? Probably so!
-               /// <summary> </summary>
-               /// <value>The collection of keys of the wrapped dictionary</value>
-               public ICollectionValue<K> Keys
-               { get { return dict.Keys; } }
-
-
-               /// <summary> </summary>
-               /// <value>The collection of values of the wrapped dictionary</value>
-               public ICollectionValue<V> Values { get { return dict.Values; } }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="key"></param>
-               /// <param name="val"></param>
-               public void Add(K key, V val)
-               { throw new InvalidOperationException("Dictionary is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="key"></param>
-               /// <returns></returns>
-               public bool Remove(K key)
-               { throw new InvalidOperationException("Dictionary is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="key"></param>
-               /// <param name="val"></param>
-               /// <returns></returns>
-               public bool Remove(K key, out V val)
-               { throw new InvalidOperationException("Dictionary is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               public void Clear()
-               { throw new InvalidOperationException("Dictionary is read only"); }
-
-
-               /// <summary>
-               /// Check if the wrapped dictionary contains a specific key
-               /// </summary>
-               /// <param name="key">The key</param>
-               /// <returns>True if it does</returns>
-               public bool Contains(K key) { return dict.Contains(key); }
-
-
-               /// <summary>
-               /// Search for a key in the wrapped dictionary, reporting the value if found
-               /// </summary>
-               /// <param name="key">The key</param>
-               /// <param name="val">On exit: the value if found</param>
-               /// <returns>True if found</returns>
-               public bool Find(K key, out V val) { return dict.Find(key, out val); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="key"></param>
-               /// <param name="val"></param>
-               /// <returns></returns>
-               public bool Update(K key, V val)
-               { throw new InvalidOperationException("Dictionary is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="key"></param>
-               /// <param name="val"></param>
-               /// <returns></returns>
-               public bool FindOrAdd(K key, ref V val)
-               { throw new InvalidOperationException("Dictionary is read only"); }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
-               /// </summary>
-               /// <param name="key"></param>
-               /// <param name="val"></param>
-               /// <returns></returns>
-               public bool UpdateOrAdd(K key, V val)
-               { throw new InvalidOperationException("Dictionary is read only"); }
-
-
-               /// <summary>
-               /// Check the internal consistency of the wrapped dictionary
-               /// </summary>
-               /// <returns>True if check passed</returns>
-               public bool Check() { return dict.Check(); }
-
-               #endregion
-       }
-
-
-
-       /// <summary>
-       /// A read-only wrapper for a sorted dictionary.
-       ///
-       /// <p>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary!2"/></p>
-       /// </summary>
-       public class GuardedSortedDictionary<K,V>: GuardedDictionary<K,V>, ISortedDictionary<K,V>
-       {
-               #region Fields
-
-               ISortedDictionary<K,V> sorteddict;
-
-               #endregion
-
-               #region Constructor
-
-               /// <summary>
-               /// Wrap a sorted dictionary in a read-only wrapper
-               /// </summary>
-               /// <param name="sorteddict">the dictionary</param>
-               public GuardedSortedDictionary(ISortedDictionary<K,V> sorteddict) :base(sorteddict)
-               { this.sorteddict = sorteddict; }
-
-               #endregion
-
-               #region ISortedDictionary<K,V> Members
-
-               /// <summary>
-               /// Get the entry in the wrapped dictionary whose key is the
-               /// predecessor of a specified key.
-               /// </summary>
-               /// <param name="key">The key</param>
-               /// <returns>The entry</returns>
-               public KeyValuePair<K,V> Predecessor(K key)
-               { return sorteddict.Predecessor(key); }
-
-
-               /// <summary>
-               /// Get the entry in the wrapped dictionary whose key is the
-               /// successor of a specified key.
-               /// </summary>
-               /// <param name="key">The key</param>
-               /// <returns>The entry</returns>
-               public KeyValuePair<K,V> Successor(K key)
-               { return sorteddict.Successor(key); }
-
-
-               /// <summary>
-               /// Get the entry in the wrapped dictionary whose key is the
-               /// weak predecessor of a specified key.
-               /// </summary>
-               /// <param name="key">The key</param>
-               /// <returns>The entry</returns>
-               public KeyValuePair<K,V> WeakPredecessor(K key)
-               { return sorteddict.WeakPredecessor(key); }
-
-
-               /// <summary>
-               /// Get the entry in the wrapped dictionary whose key is the
-               /// weak successor of a specified key.
-               /// </summary>
-               /// <param name="key">The key</param>
-               /// <returns>The entry</returns>
-               public KeyValuePair<K,V> WeakSuccessor(K key)
-               { return sorteddict.WeakSuccessor(key); }
-
-               #endregion
-       }
-
-}
-#endif
diff --git a/mcs/class/Mono.C5/arrays/ArrayList.cs b/mcs/class/Mono.C5/arrays/ArrayList.cs
deleted file mode 100644 (file)
index cc7a050..0000000
+++ /dev/null
@@ -1,1298 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A list collection based on a plain dynamic array data structure.\r
-       /// Expansion of the internal array is performed by doubling on demand. \r
-       /// The internal array is only shrinked by the Clear method. \r
-       ///\r
-       /// <p>When the FIFO property is set to false this class works fine as a stack of T.\r
-       /// When the FIFO property is set to true the class will function as a (FIFO) queue\r
-       /// but very inefficiently, use a LinkedList (<see cref="T:C5.LinkedList!1"/>) instead.</p>\r
-       /// </summary>\r
-       public class ArrayList<T>: ArrayBase<T>, IList<T>\r
-       {\r
-               #region Fields\r
-\r
-               /// <summary>\r
-               /// The underlying list if we are a view, null else.\r
-               /// </summary>\r
-               protected ArrayList<T> underlying;\r
-\r
-               /// <summary>\r
-               /// The size of the underlying list.\r
-               /// </summary>\r
-               protected int underlyingsize;\r
-\r
-               /// <summary>\r
-               /// The underlying field of the FIFO property\r
-               /// </summary>\r
-               protected bool fIFO = true;\r
-\r
-               #endregion\r
-\r
-               #region Util\r
-\r
-               bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }\r
-\r
-\r
-               /// <summary>\r
-               /// Double the size of the internal array.\r
-               /// </summary>\r
-               protected override void expand()\r
-               { expand(2 * array.Length, underlyingsize); }\r
-\r
-\r
-               /// <summary>\r
-               /// Expand the internal array, resetting the index of the first unused element.\r
-               /// </summary>\r
-               /// <param name="newcapacity">The new capacity (will be rouded upwards to a power of 2).</param>\r
-               /// <param name="newsize">The new count of </param>\r
-               protected override void expand(int newcapacity, int newsize)\r
-               {\r
-                       base.expand(newcapacity, newsize);\r
-                       if (underlying != null)\r
-                               underlying.array = array;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if it is valid to perform updates and increment stamp.\r
-               /// <exception cref="InvalidOperationException"/> if check fails.\r
-               /// </summary>\r
-               protected override void updatecheck()\r
-               {\r
-                       modifycheck();\r
-                       base.updatecheck();\r
-                       if (underlying != null)\r
-                               underlying.stamp++;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if we are a view that the underlying list has only been updated through us.\r
-               /// <exception cref="InvalidOperationException"/> if check fails.\r
-               /// <br/>\r
-               /// This method should be called from enumerators etc to guard against \r
-               /// modification of the base collection.\r
-               /// </summary>\r
-               protected void modifycheck()\r
-               {\r
-                       if (underlying != null && stamp != underlying.stamp)\r
-                               throw new InvalidOperationException("underlying list was modified");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check that the list has not been updated since a particular time.\r
-               /// <exception cref="InvalidOperationException"/> if check fails.\r
-               /// </summary>\r
-               /// <param name="stamp">The stamp indicating the time.</param>\r
-               protected override void modifycheck(int stamp)\r
-               {\r
-                       modifycheck();\r
-                       if (this.stamp != stamp)\r
-                               throw new InvalidOperationException("Collection was modified");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Increment or decrement the private size fields\r
-               /// </summary>\r
-               /// <param name="delta">Increment (with sign)</param>\r
-               protected void addtosize(int delta)\r
-               {\r
-                       size += delta;\r
-                       underlyingsize += delta;\r
-                       if (underlying != null)\r
-                       {\r
-                               underlying.size += delta;\r
-                               underlying.underlyingsize += delta;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of IndexOf without modification checks.\r
-               /// </summary>\r
-               /// <param name="item">Item to look for</param>\r
-               /// <returns>The index of first occurrence</returns>\r
-               protected virtual int indexOf(T item)\r
-               {\r
-                       for (int i = 0; i < size; i++)\r
-                               if (equals(item, array[offset + i]))\r
-                                       return i;\r
-\r
-                       return -1;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of LastIndexOf without modification checks.\r
-               /// </summary>\r
-               /// <param name="item">Item to look for</param>\r
-               /// <returns>The index of last occurrence</returns>\r
-               protected virtual int lastIndexOf(T item)\r
-               {\r
-                       for (int i = size - 1; i >= 0; i--)\r
-                               if (equals(item, array[offset + i]))\r
-                                       return i;\r
-\r
-                       return -1;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of Insert with no modification checks.\r
-               /// </summary>\r
-               /// <param name="i">Index to insert at</param>\r
-               /// <param name="item">Item to insert</param>\r
-               protected override void insert(int i, T item)\r
-               {\r
-                       if (underlyingsize == array.Length)\r
-                               expand();\r
-\r
-                       i += offset;\r
-                       if (i < underlyingsize)\r
-                               Array.Copy(array, i, array, i + 1, underlyingsize - i);\r
-\r
-                       array[i] = item;\r
-                       addtosize(1);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of RemoveAt with no modification checks.\r
-               /// </summary>\r
-               /// <param name="i">Index to remove at</param>\r
-               /// <returns>The removed item</returns>\r
-               protected virtual T removeAt(int i)\r
-               {\r
-                       i += offset;\r
-\r
-                       T retval = array[i];\r
-\r
-                       addtosize(-1);\r
-                       if (underlyingsize > i)\r
-                               Array.Copy(array, i + 1, array, i, underlyingsize - i);\r
-\r
-                       array[underlyingsize] = default(T);\r
-                       return retval;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-               /// <summary>\r
-               /// Create an array list with default item hasher and initial capacity 8 items.\r
-               /// </summary>\r
-               public ArrayList() : this(8) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an array list with external item hasher and initial capacity 8 items.\r
-               /// </summary>\r
-               /// <param name="hasher">The external hasher</param>\r
-               public ArrayList(IHasher<T> hasher) : this(8,hasher) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an array list with default item hasher and prescribed initial capacity.\r
-               /// </summary>\r
-               /// <param name="capacity">The prescribed capacity</param>\r
-               public ArrayList(int capacity) : this(capacity,HasherBuilder.ByPrototype<T>.Examine()) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an array list with external item hasher and prescribed initial capacity.\r
-               /// </summary>\r
-               /// <param name="capacity">The prescribed capacity</param>\r
-               /// <param name="hasher">The external hasher</param>\r
-               public ArrayList(int capacity, IHasher<T> hasher) : base(capacity,hasher) { }\r
-\r
-               #endregion\r
-\r
-        #region IList<T> Members\r
-\r
-               /// <summary>\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <value>The first item in this list.</value>\r
-               [Tested]\r
-               public virtual T First\r
-               {\r
-                       [Tested]get\r
-                       {\r
-                               modifycheck();\r
-                               if (size == 0)\r
-                                       throw new InvalidOperationException("List is empty");\r
-\r
-                               return array[offset];\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <value>The last item in this list.</value>\r
-               [Tested]\r
-               public virtual T Last\r
-               {\r
-                       [Tested]get\r
-                       {\r
-                               modifycheck();\r
-                               if (size == 0)\r
-                                       throw new InvalidOperationException("List is empty");\r
-\r
-                               return array[offset + size - 1];\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Since <code>Add(T item)</code> always add at the end of the list,\r
-               /// this describes if list has FIFO or LIFO semantics.\r
-               /// </summary>\r
-               /// <value>True if the <code>Remove()</code> operation removes from the\r
-               /// start of the list, false if it removes from the end.</value>\r
-               [Tested]\r
-               public virtual bool FIFO\r
-               {\r
-                       [Tested]\r
-                       get { modifycheck(); return fIFO; }\r
-                       [Tested]\r
-                       set { updatecheck(); fIFO = value; }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// On this list, this indexer is read/write.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <value>The i'th item of this list.</value>\r
-               /// <param name="i">The index of the item to fetch or store.</param>\r
-               [Tested]\r
-               public virtual T this[int i]\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-                               modifycheck();\r
-                               if (i < 0 || i >= size)\r
-                                       throw new IndexOutOfRangeException();\r
-\r
-                               return array[offset + i];\r
-                       }\r
-                       [Tested]\r
-                       set\r
-                       {\r
-                               updatecheck();\r
-                               if (i < 0 || i >= size)\r
-                                       throw new IndexOutOfRangeException();\r
-\r
-                               array[offset + i] = value;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at a specific index location in this list. \r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt; the size of the collection.</summary>\r
-               /// <param name="i">The index at which to insert.</param>\r
-               /// <param name="item">The item to insert.</param>\r
-               [Tested]\r
-               public virtual void Insert(int i, T item)\r
-               {\r
-                       updatecheck();\r
-                       if (i < 0 || i > size)\r
-                               throw new IndexOutOfRangeException();\r
-\r
-                       insert(i, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert into this list all items from an enumerable collection starting \r
-               /// at a particular index.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt; the size of the collection.\r
-               /// </summary>\r
-               /// <param name="i">Index to start inserting at</param>\r
-               /// <param name="items">Items to insert</param>\r
-               [Tested]\r
-               public virtual void InsertAll(int i, MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-                       if (i < 0 || i > size)\r
-                               throw new IndexOutOfRangeException();\r
-\r
-                       int toadd = EnumerableBase<T>.countItems(items);\r
-\r
-                       if (toadd + underlyingsize > array.Length)\r
-                               expand(toadd + underlyingsize, underlyingsize);\r
-\r
-                       i += offset;\r
-                       if (underlyingsize > i)\r
-                               Array.Copy(array, i, array, i + toadd, underlyingsize - i);\r
-\r
-                       foreach (T item in items)\r
-                               array[i++] = item;\r
-\r
-                       addtosize(toadd);\r
-               }\r
-\r
-        internal virtual void InsertAll<U>(int i, MSG.IEnumerable<U> items) where U:T\r
-        {\r
-            updatecheck();\r
-            if (i < 0 || i > size)\r
-                throw new IndexOutOfRangeException();\r
-\r
-            int toadd = EnumerableBase<U>.countItems(items);\r
-\r
-            if (toadd + underlyingsize > array.Length)\r
-                expand(toadd + underlyingsize, underlyingsize);\r
-\r
-            i += offset;\r
-            if (underlyingsize > i)\r
-                Array.Copy(array, i, array, i + toadd, underlyingsize - i);\r
-\r
-            foreach (T item in items)\r
-                array[i++] = item;\r
-\r
-            addtosize(toadd);\r
-        }\r
-\r
-        /// <summary>\r
-               /// Insert an item right before the first occurrence of some target item.\r
-               /// <exception cref="ArgumentException"/> if target     is not found.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target before which to insert.</param>\r
-               [Tested]\r
-               public virtual void InsertBefore(T item, T target)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int i = indexOf(target);\r
-\r
-                       if (i == -1)\r
-                               throw new ArgumentException("Target item not found");\r
-\r
-                       insert(i, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item right after the last(???) occurrence of some target item.\r
-               /// <exception cref="ArgumentException"/> if target     is not found.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target after which to insert.</param>\r
-               [Tested]\r
-               public virtual void InsertAfter(T item, T target)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int i = lastIndexOf(target);\r
-\r
-                       if (i == -1)\r
-                               throw new ArgumentException("Target item not found");\r
-\r
-                       insert(i + 1, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at the front of this list;\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               [Tested]\r
-               public virtual void InsertFirst(T item)\r
-               {\r
-                       updatecheck();\r
-                       insert(0, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at the back of this list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               [Tested]\r
-               public virtual void InsertLast(T item)\r
-               {\r
-                       updatecheck();\r
-                       insert(size, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new list consisting of the items of this list satisfying a \r
-               /// certain predicate.\r
-               /// </summary>\r
-               /// <param name="filter">The filter delegate defining the predicate.</param>\r
-               /// <returns>The new list.</returns>\r
-               [Tested]\r
-               public virtual IList<T> FindAll(Filter<T> filter)\r
-               {\r
-                       modifycheck();\r
-\r
-                       ArrayList<T> res = new ArrayList<T>(itemhasher);\r
-                       int j = 0, rescap = res.array.Length;\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                       {\r
-                               T a = array[offset + i];\r
-\r
-                               if (filter(a))\r
-                               {\r
-                                       if (j == rescap) res.expand(rescap = 2 * rescap, j);\r
-\r
-                                       res.array[j++] = a;\r
-                               }\r
-                       }\r
-\r
-                       res.underlyingsize = res.size = j;\r
-                       return res;\r
-               }\r
-\r
-\r
-        /// <summary>\r
-        /// Create a new list consisting of the results of mapping all items of this\r
-        /// list. The new list will use the default hasher for the item type V.\r
-        /// </summary>\r
-        /// <typeparam name="V">The type of items of the new list</typeparam>\r
-        /// <param name="mapper">The delegate defining the map.</param>\r
-        /// <returns>The new list.</returns>\r
-        [Tested]\r
-        public virtual IList<V> Map<V>(Mapper<T, V> mapper)\r
-        {\r
-            modifycheck();\r
-\r
-            ArrayList<V> res = new ArrayList<V>(size);\r
-\r
-            return map<V>(mapper, res);\r
-        }\r
-\r
-        /// <summary>\r
-        /// Create a new list consisting of the results of mapping all items of this\r
-        /// list. The new list will use a specified hasher for the item type.\r
-        /// </summary>\r
-        /// <typeparam name="V">The type of items of the new list</typeparam>\r
-        /// <param name="mapper">The delegate defining the map.</param>\r
-        /// <param name="hasher">The hasher to use for the new list</param>\r
-        /// <returns>The new list.</returns>\r
-        public virtual IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher)\r
-        {\r
-            modifycheck();\r
-\r
-            ArrayList<V> res = new ArrayList<V>(size,hasher);\r
-\r
-            return map<V>(mapper, res);\r
-        }\r
-\r
-        private IList<V> map<V>(Mapper<T, V> mapper, ArrayList<V> res)\r
-        {\r
-            if (size > 0)\r
-                for (int i = 0; i < size; i++)\r
-                    res.array[i] = mapper(array[offset + i]);\r
-\r
-            res.underlyingsize = res.size = size;\r
-            return res;\r
-        }\r
-\r
-/// <summary>\r
-        /// Remove one item from the list: from the front if <code>FIFO</code>\r
-               /// is true, else from the back.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public virtual T Remove() { return fIFO ? RemoveFirst() : RemoveLast(); }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one item from the fromnt of the list.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public virtual T RemoveFirst()\r
-               {\r
-                       updatecheck();\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("List is empty");\r
-\r
-                       return removeAt(0);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one item from the back of the list.\r
-               /// </summary>\r
-               /// <exception cref="InvalidOperationException"> if this list is empty.</exception>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public virtual T RemoveLast()\r
-               {\r
-                       updatecheck();\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("List is empty");\r
-\r
-                       return removeAt(size - 1);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a list view on this list. \r
-        /// <exception cref="ArgumentOutOfRangeException"/> if the start or count is negative\r
-        /// <exception cref="ArgumentException"/> if the range does not fit within list.\r
-        /// </summary>\r
-        /// <param name="start">The index in this list of the start of the view.</param>\r
-               /// <param name="count">The size of the view.</param>\r
-               /// <returns>The new list view.</returns>\r
-               [Tested]\r
-               public virtual IList<T> View(int start, int count)\r
-               {\r
-            modifycheck();\r
-            checkRange(start, count);\r
-            \r
-            ArrayList<T> retval = (ArrayList<T>)MemberwiseClone();\r
-\r
-            retval.underlying = underlying != null ? underlying : this;\r
-                       retval.offset = start;\r
-                       retval.size = count;\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Null if this list is not a view.\r
-               /// </summary>\r
-        /// <value>Underlying list for view.</value>\r
-        [Tested]\r
-               public IList<T> Underlying { [Tested]get { return underlying; } }\r
-\r
-\r
-               /// <summary>\r
-               /// </summary>\r
-               /// <value>Offset for this list view or 0 for an underlying list.</value>\r
-               [Tested]\r
-               public int Offset { [Tested]get { return offset; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Slide this list view along the underlying list.\r
-               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
-               /// would bring either end of the view outside the underlying list.\r
-               /// </summary>\r
-               /// <param name="offset">The signed amount to slide: positive to slide\r
-               /// towards the end.</param>\r
-               [Tested]\r
-               public virtual void Slide(int offset)\r
-               {\r
-                       modifycheck();\r
-                       if (underlying == null)\r
-                               throw new InvalidOperationException("Not a view");\r
-\r
-                       int newoffset = this.offset + offset;\r
-\r
-                       if (newoffset < 0 || newoffset + size > underlyingsize)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       this.offset = newoffset;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Slide this list view along the underlying list, changing its size.\r
-               /// <exception cref="InvalidOperationException"/> if this list is not a view.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the operation\r
-               /// would bring either end of the view outside the underlying list.\r
-               /// </summary>\r
-               /// <param name="offset">The signed amount to slide: positive to slide\r
-               /// towards the end.</param>\r
-               /// <param name="size">The new size of the view.</param>\r
-               [Tested]\r
-               public virtual void Slide(int offset, int size)\r
-               {\r
-                       modifycheck();\r
-                       if (underlying == null)\r
-                               throw new InvalidOperationException("Not a view");\r
-\r
-                       int newoffset = this.offset + offset;\r
-                       int newsize = size;\r
-\r
-                       if (newoffset < 0 || newsize < 0 || newoffset + newsize > underlyingsize)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       this.offset = newoffset;\r
-                       this.size = newsize;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Reverst the list so the items are in the opposite sequence order.\r
-               /// </summary>\r
-               [Tested]\r
-               public virtual void Reverse() { Reverse(0, size); }\r
-\r
-\r
-               /// <summary>\r
-               /// Reverst part of the list so the items are in the opposite sequence order.\r
-               /// <exception cref="ArgumentException"/> if the count is negative.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
-               /// into the list.\r
-               /// </summary>\r
-               /// <param name="start">The index of the start of the part to reverse.</param>\r
-               /// <param name="count">The size of the part to reverse.</param>\r
-               [Tested]\r
-               public virtual void Reverse(int start, int count)\r
-               {\r
-                       updatecheck();\r
-                       checkRange(start, count);\r
-                       start += offset;\r
-                       for (int i = 0, length = count / 2, end = start + count - 1; i < length; i++)\r
-                       {\r
-                               T swap = array[start + i];\r
-\r
-                               array[start + i] = array[end - i];\r
-                               array[end - i] = swap;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this list is sorted according to a specific sorting order.\r
-               /// </summary>\r
-               /// <param name="c">The comparer defining the sorting order.</param>\r
-               /// <returns>True if the list is sorted, else false.</returns>\r
-               [Tested]\r
-               public virtual bool IsSorted(IComparer<T> c)\r
-               {\r
-                       modifycheck();\r
-                       for (int i = offset + 1, end = offset + size; i < end; i++)\r
-                               if (c.Compare(array[i - 1], array[i]) > 0)\r
-                                       return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Sort the items of the list according to a specific sorting order.\r
-               /// </summary>\r
-               /// <param name="c">The comparer defining the sorting order.</param>\r
-               [Tested]\r
-               public virtual void Sort(IComparer<T> c)\r
-               {\r
-                       updatecheck();\r
-                       Sorting.IntroSort<T>(array, offset, offset + size, c);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Randonmly shuffle the items of this list. \r
-               /// </summary>\r
-               public virtual void Shuffle() { Shuffle(new C5Random()); }\r
-\r
-\r
-               /// <summary>\r
-               /// Shuffle the items of this list according to a specific random source.\r
-               /// </summary>\r
-               /// <param name="rnd">The random source.</param>\r
-               public virtual void Shuffle(Random rnd)\r
-               {\r
-                       updatecheck();\r
-                       for (int i = offset, top = offset + size, end = top - 1; i < end; i++)\r
-                       {\r
-                               int j = rnd.Next(i, top);\r
-\r
-                               if (j != i)\r
-                               {\r
-                                       T tmp = array[i];\r
-\r
-                                       array[i] = array[j];\r
-                                       array[j] = tmp;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IIndexed<T> Members\r
-\r
-               /// <summary>\r
-               /// Search for an item in the list going forwrds from the start.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of item from start.</returns>\r
-               [Tested]\r
-               public virtual int IndexOf(T item) { modifycheck(); return indexOf(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Search for an item in the list going backwords from the end.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of of item from the end.</returns>\r
-               [Tested]\r
-               public virtual int LastIndexOf(T item) { modifycheck(); return lastIndexOf(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the item at a specific position of the list.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <param name="i">The index of the item to remove.</param>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public virtual T RemoveAt(int i)\r
-               {\r
-                       updatecheck();\r
-                       if (i < 0 || i >= size)\r
-                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
-\r
-                       return removeAt(i);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in an index interval.\r
-               /// <exception cref="IndexOutOfRangeException"/>???. \r
-               /// </summary>\r
-               /// <param name="start">The index of the first item to remove.</param>\r
-               /// <param name="count">The number of items to remove.</param>\r
-               [Tested]\r
-               public virtual void RemoveInterval(int start, int count)\r
-               {\r
-                       updatecheck();\r
-                       checkRange(start, count);\r
-                       start += offset;\r
-                       Array.Copy(array, start + count, array, start, underlyingsize - start - count);\r
-                       addtosize(-count);\r
-                       Array.Clear(array, underlyingsize, count);\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISequenced<T> Members\r
-\r
-\r
-               int ISequenced<T>.GetHashCode()\r
-               { modifycheck(); return sequencedhashcode(); }\r
-\r
-\r
-               bool ISequenced<T>.Equals(ISequenced<T> that)\r
-               { modifycheck(); return sequencedequals(that); }\r
-\r
-               #endregion\r
-\r
-               #region ICollection<T> Members\r
-\r
-               /// <summary>\r
-               /// The value is symbolic indicating the type of asymptotic complexity\r
-               /// in terms of the size of this collection (worst-case or amortized as\r
-               /// relevant).\r
-               /// </summary>\r
-               /// <value>Speed.Linear</value>\r
-               [Tested]\r
-               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Linear; } }\r
-\r
-\r
-               int ICollection<T>.GetHashCode()\r
-               { modifycheck(); return unsequencedhashcode(); }\r
-\r
-\r
-               bool ICollection<T>.Equals(ICollection<T> that)\r
-               { modifycheck(); return unsequencedequals(that); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains (an item equivalent to according to the\r
-               /// itemhasher) a particular value.\r
-               /// </summary>\r
-               /// <param name="item">The value to check for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public virtual bool Contains(T item)\r
-               { modifycheck(); return indexOf(item) >= 0; }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public virtual bool Find(ref T item)\r
-               {\r
-                       modifycheck();\r
-\r
-                       int i;\r
-\r
-                       if ((i = indexOf(item)) >= 0)\r
-                       {\r
-                               item = array[offset + i];\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value. This will only update the first \r
-               /// mathching item.\r
-               /// </summary>\r
-               /// <param name="item">Value to update.</param>\r
-               /// <returns>True if the item was found and hence updated.</returns>\r
-               [Tested]\r
-               public virtual bool Update(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int i;\r
-\r
-                       if ((i = indexOf(item)) >= 0)\r
-                       {\r
-                               array[offset + i] = item;\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found. Else, add the item to the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the item was found (hence not added).</returns>\r
-               [Tested]\r
-               public virtual bool FindOrAdd(ref T item)\r
-               {\r
-                       updatecheck();\r
-                       if (Find(ref item))\r
-                               return true;\r
-\r
-                       Add(item);\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value. This will only update the first \r
-               /// mathching item.\r
-               /// </summary>\r
-               /// <param name="item">Value to update.</param>\r
-               /// <returns>True if the item was found and hence updated.</returns>\r
-               [Tested]\r
-               public virtual bool UpdateOrAdd(T item)\r
-               {\r
-                       updatecheck();\r
-                       if (Update(item))\r
-                               return true;\r
-\r
-                       Add(item);\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the first copy of a particular item from this collection. \r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public virtual bool Remove(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int i = indexOf(item);\r
-\r
-                       if (i < 0)\r
-                               return false;\r
-\r
-                       removeAt(i);\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the first copy of a particular item from this collection if found.\r
-               /// If an item was removed, report a binary copy of the actual item removed in \r
-               /// the argument.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove on input.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public virtual bool RemoveWithReturn(ref T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int i = indexOf(item);\r
-\r
-                       if (i < 0)\r
-                               return false;\r
-\r
-                       item = removeAt(i);\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in another collection from this one, taking multiplicities into account.\r
-               /// Matching items will be removed from the front. Current implementation is not optimal.\r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public virtual void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int[] toremove = new int[(size >>5) + 1];\r
-\r
-                       foreach (T item in items)\r
-                               for (int i = 0; i < size; i++)\r
-                                       if ((toremove[i >>5] & (1 << (i & 31))) == 0 && equals(array[offset + i], item))\r
-                                       {\r
-                                               toremove[i >>5] |= 1 << (i & 31);\r
-                                               break;\r
-                                       }\r
-\r
-                       int j = offset;\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                               if ((toremove[i >>5] & (1 << (i & 31))) == 0)\r
-                                       array[j++] = array[offset + i];\r
-\r
-                       int removed = offset + size - j;\r
-\r
-                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
-                       addtosize(-removed);\r
-                       Array.Clear(array, underlyingsize, removed);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from this collection, resetting internal array size.\r
-               /// </summary>\r
-               [Tested]\r
-               public override void Clear()\r
-               {\r
-                       updatecheck();\r
-                       if (underlying == null)\r
-                       {\r
-                               array = new T[8];\r
-                               underlyingsize = size = 0;\r
-                       }\r
-                       else\r
-                       {\r
-                               underlying.RemoveInterval(offset, size);\r
-                               size = 0;\r
-                               underlyingsize = underlying.size;\r
-                               stamp = underlying.stamp;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items not in some other collection from this one, taking multiplicities into account.\r
-               /// Items are retained front first.  Current implementation is not optimal.\r
-               /// </summary>\r
-               /// <param name="items">The items to retain.</param>\r
-               [Tested]\r
-               public virtual void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int[] toretain = new int[(size >>5) + 1];\r
-\r
-                       foreach (T item in items)\r
-                               for (int i = 0; i < size; i++)\r
-                                       if ((toretain[i >>5] & (1 << (i & 31))) == 0 && equals(array[offset + i], item))\r
-                                       {\r
-                                               toretain[i >>5] |= 1 << (i & 31);\r
-                                               break;\r
-                                       }\r
-\r
-                       int j = offset;\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                               if ((toretain[i >>5] & (1 << (i & 31))) != 0)\r
-                                       array[j++] = array[i + offset];\r
-\r
-                       int removed = offset + size - j;\r
-\r
-                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
-                       addtosize(-removed);\r
-                       Array.Clear(array, underlyingsize, removed);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains all the values in another collection,\r
-               /// taking multiplicities into account.\r
-               /// Current implementation is not optimal.\r
-               /// </summary>\r
-               /// <param name="items">The </param>\r
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
-               [Tested]\r
-               public virtual bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       modifycheck();\r
-\r
-                       int[] matched = new int[(size >>5) + 1];\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               for (int i = 0; i < size; i++)\r
-                                       if ((matched[i >>5] & (1 << (i & 31))) == 0 && equals(array[i + offset], item))\r
-                                       {\r
-                                               matched[i >>5] |= 1 << (i & 31);\r
-                                               goto next;\r
-                                       }\r
-\r
-                               return false;\r
-                       next :\r
-                               ;\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Count the number of items of the collection equal to a particular value.\r
-               /// Returns 0 if and only if the value is not in the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to count.</param>\r
-               /// <returns>The number of copies found.</returns>\r
-               [Tested]\r
-               public virtual int ContainsCount(T item)\r
-               {\r
-                       modifycheck();\r
-\r
-                       int count = 0;\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                               if (equals(item, array[offset + i]))\r
-                                       count++;\r
-\r
-                       return count;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items equal to a given one.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               [Tested]\r
-               public virtual void RemoveAllCopies(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int j = offset;\r
-\r
-                       for (int i = offset, end = offset + size; i < end; i++)\r
-                               if (!equals(item, array[i]))\r
-                                       array[j++] = array[i];\r
-\r
-                       int removed = offset + size - j;\r
-\r
-                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
-                       addtosize(-removed);\r
-                       Array.Clear(array, underlyingsize, removed);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this array list.\r
-               /// </summary>\r
-               /// <returns>True if check does not fail.</returns>\r
-               [Tested]\r
-               public override bool Check()\r
-               {\r
-                       bool retval = true;\r
-\r
-                       if (underlyingsize > array.Length)\r
-                       {\r
-                               Console.WriteLine("underlyingsize ({0}) > array.Length ({1})", size, array.Length);\r
-                               return false;\r
-                       }\r
-\r
-                       if (offset + size > underlyingsize)\r
-                       {\r
-                               Console.WriteLine("offset({0})+size({1}) > underlyingsize ({2})", offset, size, underlyingsize);\r
-                               return false;\r
-                       }\r
-\r
-                       if (offset < 0)\r
-                       {\r
-                               Console.WriteLine("offset({0}) < 0", offset);\r
-                               return false;\r
-                       }\r
-\r
-                       for (int i = 0; i < underlyingsize; i++)\r
-                       {\r
-                               if ((object)(array[i]) == null)\r
-                               {\r
-                                       Console.WriteLine("Bad element: null at (base)index {0}", i);\r
-                                       retval = false;\r
-                               }\r
-                       }\r
-\r
-                       for (int i = underlyingsize, length = array.Length; i < length; i++)\r
-                       {\r
-                               if (!equals(array[i], default(T)))\r
-                               {\r
-                                       Console.WriteLine("Bad element: != default(T) at (base)index {0}", i);\r
-                                       retval = false;\r
-                               }\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IExtensible<T> Members\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True, indicating array list has bag semantics.</value>\r
-               [Tested]\r
-               public virtual bool AllowsDuplicates { [Tested]get { return true; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to end of this list.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True</returns>\r
-               [Tested]\r
-               public virtual bool Add(T item)\r
-               {\r
-                       updatecheck();\r
-                       insert(size, item);\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add the elements from another collection to this collection. \r
-               /// </summary>\r
-               /// <param name="items">The items to add.</param>\r
-               [Tested]\r
-               public virtual void AddAll(MSG.IEnumerable<T> items) { InsertAll(size, items); }\r
-\r
-        /*public virtual*/ void C5.IExtensible<T>.AddAll<U>(MSG.IEnumerable<U> items) //where U : T \r
-        {\r
-            InsertAll(size, items);\r
-        }\r
-\r
-               #endregion\r
-\r
-               #region IDirectedEnumerable<T> Members\r
-\r
-               /// <summary>\r
-               /// Create a collection containing the same items as this collection, but\r
-               /// whose enumerator will enumerate the items backwards. The new collection\r
-               /// will become invalid if the original is modified. Method typicaly used as in\r
-               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
-               /// </summary>\r
-               /// <returns>The backwards collection.</returns>\r
-               [Tested]\r
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
-\r
-               #endregion\r
-\r
-        #region IStack<T> Members\r
-\r
-        /// <summary>\r
-        /// Push an item to the top of the stack.\r
-        /// </summary>\r
-        /// <param name="item">The item</param>\r
-        [Tested]\r
-        public void Push(T item)\r
-        {\r
-            Add(item);\r
-        }\r
-\r
-        /// <summary>\r
-        /// Pop the item at the top of the stack from the stack.\r
-        /// </summary>\r
-        /// <returns>The popped item.</returns>\r
-        [Tested]\r
-        public T Pop()\r
-        {\r
-            return RemoveLast();\r
-        }\r
-\r
-        #endregion\r
-\r
-        #region IQueue<T> Members\r
-\r
-        /// <summary>\r
-        /// Enqueue an item at the back of the queue. \r
-        /// </summary>\r
-        /// <param name="item">The item</param>\r
-        [Tested]\r
-        public void EnQueue(T item)\r
-        {\r
-            Add(item);\r
-        }\r
-\r
-        /// <summary>\r
-        /// Dequeue an item from the front of the queue.\r
-        /// </summary>\r
-        /// <returns>The item</returns>\r
-        [Tested]\r
-        public T DeQueue()\r
-        {\r
-            return RemoveFirst();\r
-        }\r
-\r
-        #endregion\r
-    }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/arrays/HashedArray.cs b/mcs/class/Mono.C5/arrays/HashedArray.cs
deleted file mode 100644 (file)
index c5538d9..0000000
+++ /dev/null
@@ -1,638 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A set collection based on a dynamic  array combined with a hash index\r
-       /// for item to index lookup.\r
-       /// </summary>\r
-       public class HashedArrayList<T>: ArrayList<T>, IList<T>\r
-       {\r
-               #region Fields\r
-\r
-               HashSet<KeyValuePair<T,int>> index;\r
-\r
-               #endregion\r
-\r
-               #region Util\r
-\r
-               private void reindex(int start) { reindex(start, underlyingsize); }\r
-\r
-\r
-               private void reindex(int start, int end)\r
-               {\r
-                       for (int j = start; j < end; j++)\r
-                               index.Update(new KeyValuePair<T,int>(array[j], j));\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of IndexOf without modification checks.\r
-               /// </summary>\r
-               /// <param name="item">Item to look for</param>\r
-               /// <returns>The index of first occurrence</returns>\r
-               protected override int indexOf(T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item);\r
-\r
-                       if (!index.Find(ref p) || p.value < offset || p.value >= offset + size)\r
-                               return -1;\r
-\r
-                       return p.value - offset;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of LastIndexOf without modification checks.\r
-               /// </summary>\r
-               /// <param name="item">Item to look for</param>\r
-               /// <returns>The index of last occurrence</returns>\r
-               protected override int lastIndexOf(T item) { return indexOf(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of Insert with no modification checks.\r
-               /// <exception cref="ArgumentException"/> if item already in list.\r
-               /// </summary>\r
-               /// <param name="i">Index to insert at</param>\r
-               /// <param name="item">Item to insert</param>\r
-               protected override void insert(int i, T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, offset + i);\r
-\r
-                       if (index.FindOrAdd(ref p))\r
-                               throw new ArgumentException("Item already in indexed list");\r
-\r
-                       base.insert(i, item);\r
-                       reindex(i + 1);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Internal version of RemoveAt with no modification checks.\r
-               /// </summary>\r
-               /// <param name="i">Index to remove at</param>\r
-               /// <returns>The removed item</returns>\r
-               protected override T removeAt(int i)\r
-               {\r
-                       T val = base.removeAt(i);\r
-\r
-                       index.Remove(new KeyValuePair<T,int>(val));\r
-                       reindex(offset + i);\r
-                       return val;\r
-               }\r
-\r
-\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-               /// <summary>\r
-               /// Create a hashed array list with the natural hasher \r
-               /// </summary>\r
-               public HashedArrayList() : this(8) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hashed array list with the natural hasher and specified capacity\r
-               /// </summary>\r
-               /// <param name="cap">The initial capacity</param>\r
-               public HashedArrayList(int cap) : this(cap,HasherBuilder.ByPrototype<T>.Examine()) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hashed array list with an external hasher\r
-               /// </summary>\r
-               /// <param name="hasher">The external hasher</param>\r
-               public HashedArrayList(IHasher<T> hasher) : this(8,hasher) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hashed array list with an external hasher and specified capacity\r
-               /// </summary>\r
-               /// <param name="capacity">The initial capacity</param>\r
-               /// <param name="hasher">The external hasher</param>\r
-               public HashedArrayList(int capacity, IHasher<T> hasher) : base(capacity, hasher)\r
-               {\r
-                       index = new HashSet<KeyValuePair<T,int>>(new KeyValuePairHasher<T,int>(hasher));\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IList<T> Members\r
-\r
-               /// <summary>\r
-               /// Insert into this list all items from an enumerable collection starting \r
-               /// at a particular index.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt; the size of the collection.\r
-               /// <exception cref="InvalidOperationException"/> if one of the items to insert is\r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="i">Index to start inserting at</param>\r
-               /// <param name="items">Items to insert</param>\r
-               [Tested]\r
-               public override void InsertAll(int i, MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-                       if (i < 0 || i > size)\r
-                               throw new IndexOutOfRangeException();\r
-\r
-                       i += offset;\r
-\r
-                       int j = i, toadd;\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               p.key = item;\r
-                               p.value = j;\r
-                               if (!index.FindOrAdd(ref p))    j++;\r
-                       }\r
-\r
-                       toadd = j - i;\r
-                       if (toadd + underlyingsize > array.Length)\r
-                               expand(toadd + underlyingsize, underlyingsize);\r
-\r
-                       if (underlyingsize > i)\r
-                               Array.Copy(array, i, array, j, underlyingsize - i);\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               p.key = item;\r
-                               index.Find(ref p);\r
-                               if (i <= p.value && p.value < i + toadd)\r
-                                       array[p.value] = item;\r
-                       }\r
-\r
-                       addtosize(toadd);\r
-                       reindex(j);\r
-               }\r
-\r
-        internal override void InsertAll<U>(int i, MSG.IEnumerable<U> items) //where U:T\r
-        {\r
-            updatecheck();\r
-            if (i < 0 || i > size)\r
-                throw new IndexOutOfRangeException();\r
-\r
-            i += offset;\r
-\r
-            int j = i, toadd;\r
-            KeyValuePair<T, int> p = new KeyValuePair<T, int>();\r
-\r
-            foreach (T item in items)\r
-            {\r
-                p.key = item;\r
-                p.value = j;\r
-                if (!index.FindOrAdd(ref p)) j++;\r
-            }\r
-\r
-            toadd = j - i;\r
-            if (toadd + underlyingsize > array.Length)\r
-                expand(toadd + underlyingsize, underlyingsize);\r
-\r
-            if (underlyingsize > i)\r
-                Array.Copy(array, i, array, j, underlyingsize - i);\r
-\r
-            foreach (T item in items)\r
-            {\r
-                p.key = item;\r
-                index.Find(ref p);\r
-                if (i <= p.value && p.value < i + toadd)\r
-                    array[p.value] = item;\r
-            }\r
-\r
-            addtosize(toadd);\r
-            reindex(j);\r
-        }\r
-\r
-        /// <summary>\r
-               /// Insert an item right before the first occurrence of some target item.\r
-               /// <exception cref="ArgumentException"/> if target     is not found.\r
-               /// <exception cref="InvalidOperationException"/> if the item to insert is\r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target before which to insert.</param>\r
-               [Tested]\r
-               public override void InsertBefore(T item, T target)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int ind = indexOf(target);\r
-\r
-                       if (ind < 0)\r
-                               throw new ArgumentException("Target item not found");\r
-\r
-                       insert(ind, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item right after the last(???) occurrence of some target item.\r
-               /// <exception cref="ArgumentException"/> if target     is not found.\r
-               /// <exception cref="InvalidOperationException"/> if the item to insert is\r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target after which to insert.</param>\r
-               [Tested]\r
-               public override void InsertAfter(T item, T target)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int ind = indexOf(target);\r
-\r
-                       if (ind < 0)\r
-                               throw new ArgumentException("Target item not found");\r
-\r
-                       insert(ind + 1, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a list view on this list. \r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the view would not fit into\r
-               /// this list.\r
-               /// </summary>\r
-               /// <param name="start">The index in this list of the start of the view.</param>\r
-               /// <param name="count">The size of the view.</param>\r
-               /// <returns>The new list view.</returns>\r
-               [Tested]\r
-               public override IList<T> View(int start, int count)\r
-               {\r
-                       HashedArrayList<T> retval = (HashedArrayList<T>)MemberwiseClone();\r
-\r
-                       retval.underlying = underlying != null ? underlying : this;\r
-                       retval.offset = start;\r
-                       retval.size = count;\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Reverst part of the list so the items are in the opposite sequence order.\r
-               /// <exception cref="ArgumentException"/> if the count is negative.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
-               /// into the list.\r
-               /// </summary>\r
-               /// <param name="start">The index of the start of the part to reverse.</param>\r
-               /// <param name="count">The size of the part to reverse.</param>\r
-               [Tested]\r
-               public override void Reverse(int start, int count)\r
-               {\r
-                       base.Reverse(start, count);\r
-                       reindex(offset + start, offset + start + count);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Sort the items of the list according to a specific sorting order.\r
-               /// </summary>\r
-               /// <param name="c">The comparer defining the sorting order.</param>\r
-               [Tested]\r
-               public override void Sort(IComparer<T> c)\r
-               {\r
-                       base.Sort(c);\r
-                       reindex(offset, offset + size);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Shuffle the items of this list according to a specific random source.\r
-               /// </summary>\r
-               /// <param name="rnd">The random source.</param>\r
-               public override void Shuffle(Random rnd)\r
-               {\r
-                       base.Shuffle(rnd);\r
-                       reindex(offset, offset + size);\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IIndexed<T> Members\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in an index interval.\r
-               /// <exception cref="IndexOutOfRangeException"/>???. \r
-               /// </summary>\r
-               /// <param name="start">The index of the first item to remove.</param>\r
-               /// <param name="count">The number of items to remove.</param>\r
-               [Tested]\r
-               public override void RemoveInterval(int start, int count)\r
-               {\r
-                       updatecheck();\r
-\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
-\r
-                       for (int i = offset + start, end = offset + start + count; i < end; i++)\r
-                       {\r
-                               p.key = array[i];\r
-                               index.Remove(p);\r
-                       }\r
-\r
-                       base.RemoveInterval(start, count);\r
-                       reindex(offset + start);\r
-               }\r
-\r
-               #endregion\r
-        \r
-               #region ISequenced<T> Members\r
-\r
-               int ISequenced<T>.GetHashCode()\r
-               { modifycheck(); return sequencedhashcode(); }\r
-\r
-\r
-               bool ISequenced<T>.Equals(ISequenced<T> that)\r
-               { modifycheck(); return sequencedequals(that); }\r
-\r
-\r
-       #endregion\r
-        \r
-               #region IEditableCollection<T> Members\r
-\r
-               /// <summary>\r
-               /// The value is symbolic indicating the type of asymptotic complexity\r
-               /// in terms of the size of this collection (expected).\r
-               /// </summary>\r
-               /// <value>Speed.Constant</value>\r
-               [Tested]\r
-               public override Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains (an item equivalent to according to the\r
-               /// itemhasher) a particular value.\r
-               /// </summary>\r
-               /// <param name="item">The value to check for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public override bool Contains(T item)\r
-               { modifycheck(); return indexOf(item) >= 0; }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the first copy of a particular item from this collection. \r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public override bool Remove(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int ind = indexOf(item);\r
-\r
-                       if (ind < 0)\r
-                               return false;\r
-\r
-                       removeAt(ind);\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in another collection from this one, taking multiplicities into account.\r
-               /// Matching items will be removed from the front. Current implementation is not optimal.\r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public override void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               p.key = item;\r
-                               if (index.Find(ref p) && offset <= p.value && p.value < offset + size)\r
-                                       index.Remove(p);\r
-                       }\r
-\r
-                       int removed = underlyingsize - index.Count, j = offset;\r
-\r
-                       for (int i = offset; i < underlyingsize; i++)\r
-                       {\r
-                               p.key = array[i];\r
-                               p.value = j;\r
-                               if (index.Update(p)) { array[j++] = p.key; }\r
-                       }\r
-\r
-                       addtosize(-removed);\r
-                       Array.Clear(array, underlyingsize, removed);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from this collection, resetting internal array size.\r
-               /// </summary>\r
-               [Tested]\r
-               public override void Clear()\r
-               {\r
-                       updatecheck();\r
-                       if (underlying == null)\r
-                       {\r
-                               index.Clear();\r
-                               base.Clear();\r
-                       }\r
-                       else\r
-                       {\r
-                               for (int i = offset, end = offset + size; i < end; i++)\r
-                                       index.Remove(new KeyValuePair<T,int>(array[i]));\r
-\r
-                               base.Clear();\r
-                               reindex(offset);\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items not in some other collection from this one.\r
-               /// </summary>\r
-               /// <param name="items">The items to retain.</param>\r
-               [Tested]\r
-               public override void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       HashSet<T> toretain = new HashSet<T>(itemhasher);\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>();\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               p.key = item;\r
-                               if (index.Find(ref p) && offset <= p.value && p.value < offset + size)\r
-                                       toretain.Add(item);\r
-                       }\r
-\r
-                       int removed = size - toretain.Count, j = offset;\r
-\r
-                       for (int i = offset; i < offset + size; i++)\r
-                       {\r
-                               p.key = array[i];\r
-                               p.value = j;\r
-                               if (toretain.Contains(p.key))\r
-                               {\r
-                                       index.Update(p);\r
-                                       array[j++] = p.key;\r
-                               }\r
-                               else\r
-                               {\r
-                                       index.Remove(p);\r
-                               }\r
-                       }\r
-\r
-                       Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
-                       addtosize(-removed);\r
-                       reindex(j);\r
-                       Array.Clear(array, underlyingsize, removed);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains all the values in another collection.\r
-               /// </summary>\r
-               /// <param name="items">The </param>\r
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
-               [Tested]\r
-               public override bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       modifycheck();\r
-                       foreach (T item in items)\r
-                               if (indexOf(item) < 0)\r
-                                       return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Count the number of items of the collection equal to a particular value.\r
-               /// Returns 0 if and only if the value is not in the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to count.</param>\r
-               /// <returns>The number of copies found (0 or 1).</returns>\r
-               [Tested]\r
-               public override int ContainsCount(T item)\r
-               { modifycheck(); return indexOf(item) >= 0 ? 1 : 0; }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items equal to a given one.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               [Tested]\r
-               public override void RemoveAllCopies(T item) { Remove(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this array list.\r
-               /// </summary>\r
-               /// <returns>True if check does not fail.</returns>\r
-               [Tested]\r
-               public override bool Check()\r
-               {\r
-                       if (!base.Check())\r
-                               return false;\r
-\r
-                       bool retval = true;\r
-\r
-                       if (underlyingsize != index.Count)\r
-                       {\r
-                               Console.WriteLine("size ({0})!= index.Count ({1})", size, index.Count);\r
-                               retval = false;\r
-                       }\r
-\r
-                       for (int i = 0; i < underlyingsize; i++)\r
-                       {\r
-                               KeyValuePair<T,int> p = new KeyValuePair<T,int>(array[i]);\r
-\r
-                               if (!index.Find(ref p))\r
-                               {\r
-                                       Console.WriteLine("Item {1} at {0} not in hashindex", i, array[i]);\r
-                                       retval = false;\r
-                               }\r
-\r
-                               if (p.value != i)\r
-                               {\r
-                                       Console.WriteLine("Item {1} at {0} has hashindex {2}", i, array[i], p.value);\r
-                                       retval = false;\r
-                               }\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-\r
-\r
-               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
-\r
-\r
-               bool ICollection<T>.Equals(ICollection<T> that)\r
-               { return unsequencedequals(that); }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>False, indicating hashed array list has set semantics.</value>\r
-               [Tested]\r
-               public override bool AllowsDuplicates { [Tested]get { return false; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to end of this list if not already in list.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True if item was added</returns>\r
-               [Tested]\r
-               public override bool Add(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, size);\r
-\r
-                       if (index.FindOrAdd(ref p))\r
-                               return false;\r
-\r
-                       base.insert(size, item);\r
-                       reindex(size);\r
-                       return true;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IDirectedEnumerable<T> Members\r
-\r
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
-\r
-               #endregion\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/arrays/SortedArray.cs b/mcs/class/Mono.C5/arrays/SortedArray.cs
deleted file mode 100644 (file)
index 77478fb..0000000
+++ /dev/null
@@ -1,1232 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A collection class implementing a sorted dynamic array data structure.\r
-       /// </summary>\r
-       public class SortedArray<T>: ArrayBase<T>, IIndexedSorted<T>\r
-       {\r
-               #region Features\r
-               /// <summary>\r
-               /// A debugging artifact. To be removed.\r
-               /// </summary>\r
-               [Flags]\r
-               public enum Feature: short\r
-               {\r
-                       /// <summary>\r
-                       /// A debugging artifact. To be removed.\r
-                       /// </summary>\r
-                       Standard = 0\r
-               }\r
-\r
-\r
-               static Feature features = Feature.Standard;\r
-\r
-\r
-               /// <summary>\r
-               /// A debugging artifact. To be removed.\r
-               /// </summary>\r
-               /// <value></value>\r
-               public static Feature Features { get { return features; } }\r
-\r
-               #endregion\r
-               \r
-               #region Fields\r
-\r
-               IComparer<T> comparer;\r
-\r
-               #endregion\r
-               \r
-               #region Util\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="item">The item to search for</param>\r
-               /// <param name="mid">The least index, mid, for which array[mid] >= item</param>\r
-               /// <returns>True if item found</returns>\r
-               private bool binarySearch(T item, out int mid)\r
-               {\r
-                       int bot = 0, top = size;\r
-\r
-                       mid = top / 2;\r
-                       while (top > bot)\r
-                       {\r
-                               int c;\r
-\r
-                               if ((c = comparer.Compare(array[mid], item)) == 0)\r
-                                       return true;\r
-\r
-                               if (c > 0)\r
-                               { top = mid; }\r
-                               else\r
-                               { bot = mid + 1; }\r
-\r
-                               mid = (bot + top) / 2;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-               private int indexOf(T item)\r
-               {\r
-                       int ind;\r
-\r
-                       if (binarySearch(item, out ind))\r
-                               return ind;\r
-\r
-                       return -1;\r
-               }\r
-\r
-               #endregion\r
-               \r
-               #region Constructors\r
-\r
-               /// <summary>\r
-               /// Create a dynamic sorted array with a natural comparer\r
-               /// </summary>\r
-               public SortedArray() : this(8) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a dynamic sorted array with a natural comparer\r
-               /// and prescribed initial capacity.\r
-               /// </summary>\r
-               /// <param name="capacity">The capacity</param>\r
-               public SortedArray(int capacity) \r
-                       : this(ComparerBuilder.FromComparable<T>.Examine()) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a dynamic sorted array with an external comparer\r
-               /// </summary>\r
-               /// <param name="c">The comparer</param>\r
-               public SortedArray(IComparer<T> c) \r
-                       : this(8,c) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a dynamic sorted array with an external comparer\r
-               /// and prescribed initial capacity.\r
-               /// </summary>\r
-               /// <param name="capacity">The capacity</param>\r
-               /// <param name="c">The comparer</param>\r
-               public SortedArray(int capacity, IComparer<T> c) \r
-                       : this(capacity, c, HasherBuilder.ByPrototype<T>.Examine()) { }\r
-\r
-               /// <summary>\r
-               /// Create a dynamic sorted array with an external comparer, an external hasher\r
-               /// and prescribed initial capacity.\r
-               /// </summary>\r
-               /// <param name="capacity">The capacity</param>\r
-               /// <param name="c">The comparer</param>\r
-               /// <param name="h">The hasher (compatible)</param>\r
-               public SortedArray(int capacity, IComparer<T> c, IHasher<T> h) \r
-                       : base(capacity, h) { comparer = c; }\r
-\r
-               #endregion\r
-               \r
-               #region IIndexedSorted<T> Members\r
-\r
-               /// <summary>\r
-               /// Determine the number of items at or above a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountFrom(T bot)\r
-               {\r
-                       int lo;\r
-\r
-                       binarySearch(bot, out lo);\r
-                       return size - lo;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountFromTo(T bot, T top)\r
-               {\r
-                       int lo, hi;\r
-\r
-                       binarySearch(bot, out lo);\r
-                       binarySearch(top, out hi);\r
-                       return hi > lo ? hi - lo : 0;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountTo(T top)\r
-               {\r
-                       int hi;\r
-\r
-                       binarySearch(top, out hi);\r
-                       return hi;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items greater than or equal to a supplied value.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeFrom(T bot)\r
-               {\r
-                       int lo;\r
-\r
-                       binarySearch(bot, out lo);\r
-                       return new Range(this, lo, size - lo, true);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items between two supplied values.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)\r
-               {\r
-                       int lo, hi;\r
-\r
-                       binarySearch(bot, out lo);\r
-                       binarySearch(top, out hi);\r
-\r
-                       int sz = hi - lo;\r
-\r
-                       return new Range(this, lo, sz, true);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items less than a supplied value.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeTo(T top)\r
-               {\r
-                       int hi;\r
-\r
-                       binarySearch(top, out hi);\r
-                       return new Range(this, 0, hi, true);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the items of this\r
-               /// indexed sorted collection satisfying a certain predicate.\r
-               /// </summary>\r
-               /// <param name="f">The filter delegate defining the predicate.</param>\r
-               /// <returns>The new indexed sorted collection.</returns>\r
-               [Tested]\r
-               public IIndexedSorted<T> FindAll(Filter<T> f)\r
-               {\r
-                       SortedArray<T> res = new SortedArray<T>(comparer);\r
-                       int j = 0, rescap = res.array.Length;\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                       {\r
-                               T a = array[i];\r
-\r
-                               if (f(a))\r
-                               {\r
-                                       if (j == rescap) res.expand(rescap = 2 * rescap, j);\r
-\r
-                                       res.array[j++] = a;\r
-                               }\r
-                       }\r
-\r
-                       res.size = j;\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the results of\r
-               /// mapping all items of this list.\r
-               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
-               /// the items of this collection (with respect to the two given comparison \r
-               /// relations).\r
-               /// </summary>\r
-               /// <param name="m">The delegate definging the map.</param>\r
-               /// <param name="c">The comparion relation to use for the result.</param>\r
-               /// <returns>The new sorted collection.</returns>\r
-               [Tested]\r
-               public IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c)\r
-               {\r
-                       SortedArray<V> res = new SortedArray<V>(size, c);\r
-\r
-                       if (size > 0)\r
-                       {\r
-                               V oldv = res.array[0] = m(array[0]), newv;\r
-\r
-                               for (int i = 1; i < size; i++)\r
-                               {\r
-                                       if (c.Compare(oldv, newv = res.array[i] = m(array[i])) >= 0)\r
-                                               throw new ArgumentException("mapper not monotonic");\r
-\r
-                                       oldv = newv;\r
-                               }\r
-                       }\r
-\r
-                       res.size = size;\r
-                       return res;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISorted<T> Members\r
-\r
-               /// <summary>\r
-               /// Find the strict predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than or equal to the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the predecessor for.</param>\r
-               /// <returns>The predecessor.</returns>\r
-               [Tested]\r
-               public T Predecessor(T item)\r
-               {\r
-                       int lo;\r
-\r
-                       binarySearch(item, out lo);\r
-                       if (lo == 0)\r
-                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
-\r
-                       return array[lo - 1];\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the strict successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than or equal to the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the successor for.</param>\r
-               /// <returns>The successor.</returns>\r
-               [Tested]\r
-               public T Successor(T item)\r
-               {\r
-                       int hi;\r
-\r
-                       if (binarySearch(item, out hi)) hi++;\r
-\r
-                       if (hi >= size)\r
-                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
-\r
-                       return array[hi];\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak predecessor for.</param>\r
-               /// <returns>The weak predecessor.</returns>\r
-               [Tested]\r
-               public T WeakPredecessor(T item)\r
-               {\r
-                       int lo;\r
-\r
-                       if (!binarySearch(item, out lo)) lo--;\r
-\r
-                       if (lo < 0)\r
-                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
-\r
-                       return array[lo];\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak successor for.</param>\r
-               /// <returns>The weak successor.</returns>\r
-               [Tested]\r
-               public T WeakSuccessor(T item)\r
-               {\r
-                       int hi;\r
-\r
-                       binarySearch(item, out hi);\r
-                       if (hi >= size)\r
-                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
-\r
-                       return array[hi];\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Perform a search in the sorted collection for the ranges in which a\r
-               /// non-decreasing function from the item type to <code>int</code> is\r
-               /// negative, zero respectively positive. If the supplied cut function is\r
-               /// not non-decreasing, the result of this call is undefined.\r
-               /// </summary>\r
-               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
-               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
-               /// the <code>c.CompareTo(T that)</code> method.</param>\r
-               /// <param name="low">Returns the largest item in the collection, where the\r
-               /// cut function is negative (if any).</param>\r
-               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
-               /// on this collection.</param>\r
-               /// <param name="high">Returns the least item in the collection, where the\r
-               /// cut function is positive (if any).</param>\r
-               /// <param name="highIsValid">True if the cut function is positive somewhere\r
-               /// on this collection.</param>\r
-               /// <returns></returns>\r
-               [Tested]\r
-               public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)\r
-               {\r
-                       int lbest = -1, rbest = size;\r
-\r
-                       low = default(T);\r
-                       lowIsValid = false;\r
-                       high = default(T);\r
-                       highIsValid = false;\r
-\r
-                       int bot = 0, top = size, mid, comp = -1, sol;\r
-\r
-                       mid = top / 2;\r
-                       while (top > bot)\r
-                       {\r
-                               if ((comp = c.CompareTo(array[mid])) == 0)\r
-                                       break;\r
-\r
-                               if (comp < 0)\r
-                               { rbest = top = mid; }\r
-                               else\r
-                               { lbest = mid; bot = mid + 1; }\r
-\r
-                               mid = (bot + top) / 2;\r
-                       }\r
-\r
-                       if (comp != 0)\r
-                       {\r
-                               if (lbest >= 0) { lowIsValid = true; low = array[lbest]; }\r
-\r
-                               if (rbest < size) { highIsValid = true; high = array[rbest]; }\r
-\r
-                               return false;\r
-                       }\r
-\r
-                       sol = mid;\r
-                       bot = sol - 1;\r
-\r
-                       //Invariant: c.Compare(array[x]) < 0  when rbest <= x < size \r
-                       //           c.Compare(array[x]) >= 0 when x < bot)\r
-                       //(Assuming c.Compare monotonic)\r
-                       while (rbest > bot)\r
-                       {\r
-                               mid = (bot + rbest) / 2;\r
-                               if (c.CompareTo(array[mid]) < 0)\r
-                               { rbest = mid; }\r
-                               else\r
-                               { bot = mid + 1; }\r
-                       }\r
-\r
-                       if (rbest < size) { highIsValid = true; high = array[rbest]; }\r
-\r
-                       top = sol + 1;\r
-\r
-                       //Invariant: c.Compare(array[x]) > 0  when 0 <= x <= lbest\r
-                       //           c.Compare(array[x]) <= 0 when x>top)\r
-                       //(Assuming c.Compare monotonic)\r
-                       while (top > lbest)\r
-                       {\r
-                               mid = (lbest + top + 1) / 2;\r
-                               if (c.CompareTo(array[mid]) > 0)\r
-                               { lbest = mid; }\r
-                               else\r
-                               { top = mid - 1; }\r
-                       }\r
-\r
-                       if (lbest >= 0) { lowIsValid = true; low = array[lbest]; }\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot)\r
-               { return RangeFrom(bot); }\r
-\r
-\r
-               IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top)\r
-               { return RangeFromTo(bot, top); }\r
-\r
-\r
-               IDirectedEnumerable<T> ISorted<T>.RangeTo(T top)\r
-               { return RangeTo(top); }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a directed collection with the same items as this collection.\r
-               /// </summary>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeAll()\r
-               { return new Range(this, 0, size, true); }\r
-\r
-\r
-               /// <summary>\r
-               /// Add all the items from another collection with an enumeration order that \r
-               /// is increasing in the items.\r
-               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
-               /// not to be in increasing order.\r
-               /// </summary>\r
-               /// <param name="items">The collection to add.</param>\r
-               [Tested]\r
-               public void AddSorted(MSG.IEnumerable<T> items)\r
-               {\r
-                       //Unless items have <=1 elements we would expect it to be\r
-                       //too expensive to do repeated inserts, thus:\r
-                       updatecheck();\r
-\r
-                       int j = 0, i = 0, c = -1, itemcount = EnumerableBase<T>.countItems(items);\r
-                       SortedArray<T> res = new SortedArray<T>(size + itemcount, comparer);\r
-                       T lastitem = default(T);\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               while (i < size && (c = comparer.Compare(array[i], item)) <= 0)\r
-                               {\r
-                                       lastitem = res.array[j++] = array[i++];\r
-                                       if (c == 0)\r
-                                               goto next;\r
-                               }\r
-\r
-                               if (j > 0 && comparer.Compare(lastitem, item) >= 0)\r
-                                       throw new ArgumentException("Argument not sorted");\r
-\r
-                               lastitem = res.array[j++] = item;\r
-                       next :\r
-                               c = -1;\r
-                       }\r
-\r
-                       while (i < size) res.array[j++] = array[i++];\r
-\r
-                       size = j;\r
-                       array = res.array;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection above or at a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeFrom(T low)\r
-               {\r
-                       int lowind;\r
-\r
-                       binarySearch(low, out lowind);\r
-                       if (lowind == size)\r
-                               return;\r
-\r
-                       Array.Clear(array, lowind, size - lowind);\r
-                       size = lowind;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeFromTo(T low, T hi)\r
-               {\r
-                       int lowind, highind;\r
-\r
-                       binarySearch(low, out lowind);\r
-                       binarySearch(hi, out highind);\r
-                       if (highind <= lowind)\r
-                               return;\r
-\r
-                       Array.Copy(array, highind, array, lowind, size - highind);\r
-                       Array.Clear(array, size - highind + lowind, highind - lowind);\r
-                       size -= highind - lowind;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeTo(T hi)\r
-               {\r
-                       int highind;\r
-\r
-                       binarySearch(hi, out highind);\r
-                       if (highind == 0)\r
-                               return;\r
-\r
-                       Array.Copy(array, highind, array, 0, size - highind);\r
-                       Array.Clear(array, size - highind, highind);\r
-                       size = size - highind;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISequenced<T> Members\r
-\r
-               int ISequenced<T>.GetHashCode() { return sequencedhashcode(); }\r
-\r
-\r
-               bool ISequenced<T>.Equals(ISequenced<T> that) { return sequencedequals(that); }\r
-               \r
-               #endregion\r
-\r
-               #region IEditableCollection<T> Members\r
-               /// <summary>\r
-               /// The value is symbolic indicating the type of asymptotic complexity\r
-               /// in terms of the size of this collection (worst-case).\r
-               /// </summary>\r
-               /// <value>Speed.Log</value>\r
-               [Tested]\r
-               public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }\r
-\r
-\r
-               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
-\r
-\r
-               bool ICollection<T>.Equals(ICollection<T> that) \r
-               { return unsequencedequals(that); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains (an item equivalent to according to the\r
-               /// itemhasher) a particular value.\r
-               /// </summary>\r
-               /// <param name="item">The value to check for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public bool Contains(T item)\r
-               {\r
-                       int ind;\r
-\r
-                       return binarySearch(item, out ind);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public bool Find(ref T item)\r
-               {\r
-                       int ind;\r
-\r
-                       if (binarySearch(item, out ind))\r
-                       {\r
-                               item = array[ind];\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               //This should probably just be bool Add(ref T item); !!!\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found. Else, add the item to the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the item was added (hence not found).</returns>\r
-               [Tested]\r
-               public bool FindOrAdd(ref T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int ind;\r
-\r
-                       if (binarySearch(item, out ind))\r
-                       {\r
-                               item = array[ind];\r
-                               return true;\r
-                       }\r
-\r
-                       if (size == array.Length - 1) expand();\r
-\r
-                       Array.Copy(array, ind, array, ind + 1, size - ind);\r
-                       array[ind] = item;\r
-                       size++;\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
-               /// it is implementation dependent if this updates all equivalent copies in\r
-               /// the collection or just one.\r
-               /// </summary>\r
-               /// <param name="item">Value to update.</param>\r
-               /// <returns>True if the item was found and hence updated.</returns>\r
-               [Tested]\r
-               public bool Update(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int ind;\r
-\r
-                       if (binarySearch(item, out ind))\r
-                       {\r
-                               array[ind] = item;\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value; else add the value to the collection. \r
-               /// </summary>\r
-               /// <param name="item">Value to add or update.</param>\r
-               /// <returns>True if the item was found and updated (hence not added).</returns>\r
-               [Tested]\r
-               public bool UpdateOrAdd(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int ind;\r
-\r
-                       if (binarySearch(item, out ind))\r
-                       {\r
-                               array[ind] = item;\r
-                               return true;\r
-                       }\r
-\r
-                       if (size == array.Length - 1) expand();\r
-\r
-                       Array.Copy(array, ind, array, ind + 1, size - ind);\r
-                       array[ind] = item;\r
-                       size++;\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection. If the collection has bag\r
-               /// semantics only one copy equivalent to the supplied item is removed. \r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public bool Remove(T item)\r
-               {\r
-                       int ind;\r
-\r
-                       updatecheck();\r
-                       if (binarySearch(item, out ind))\r
-                       {\r
-                               Array.Copy(array, ind + 1, array, ind, size - ind - 1);\r
-                               array[--size] = default(T);\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection if found. If the collection\r
-               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
-               /// which one is implementation dependent. \r
-               /// If an item was removed, report a binary copy of the actual item removed in \r
-               /// the argument.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove on input.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public bool RemoveWithReturn(ref T item)\r
-               {\r
-                       int ind;\r
-\r
-                       updatecheck();\r
-                       if (binarySearch(item, out ind))\r
-                       {\r
-                               item = array[ind];\r
-                               Array.Copy(array, ind + 1, array, ind, size - ind - 1);\r
-                               array[--size] = default(T);\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in another collection from this one. \r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       //This is O(m*logn) with n bits extra storage\r
-                       //(Not better to collect the m items and sort them)\r
-                       updatecheck();\r
-\r
-                       int[] toremove = new int[(size >>5) + 1];\r
-                       int ind, j = 0;\r
-\r
-                       foreach (T item in items)\r
-                               if (binarySearch(item, out ind))\r
-                                       toremove[ind >>5] |= 1 << (ind & 31);\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                               if ((toremove[i >>5] & (1 << (i & 31))) == 0)\r
-                                       array[j++] = array[i];\r
-\r
-                       Array.Clear(array, j, size - j);\r
-                       size = j;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items not in some other collection from this one. \r
-               /// </summary>\r
-               /// <param name="items">The items to retain.</param>\r
-               [Tested]\r
-               public void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       //This is O(m*logn) with n bits extra storage\r
-                       //(Not better to collect the m items and sort them)\r
-                       updatecheck();\r
-\r
-                       int[] toretain = new int[(size >>5) + 1];\r
-                       int ind, j = 0;\r
-\r
-                       foreach (T item in items)\r
-                               if (binarySearch(item, out ind))\r
-                                       toretain[ind >>5] |= 1 << (ind & 31);\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                               if ((toretain[i >>5] & (1 << (i & 31))) != 0)\r
-                                       array[j++] = array[i];\r
-\r
-                       Array.Clear(array, j, size - j);\r
-                       size = j;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains all the values in another collection.\r
-               /// Multiplicities are not taken into account.\r
-               /// </summary>\r
-               /// <param name="items">The </param>\r
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
-               [Tested]\r
-               public bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       int tmp;\r
-\r
-                       foreach (T item in items)\r
-                               if (!binarySearch(item, out tmp))\r
-                                       return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Count the number of items of the collection equal to a particular value.\r
-               /// Returns 0 if and only if the value is not in the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to count.</param>\r
-               /// <returns>The number of copies found (0 or 1).</returns>\r
-               [Tested]\r
-               public int ContainsCount(T item)\r
-               {\r
-                       int tmp;\r
-\r
-                       return binarySearch(item, out tmp) ? 1 : 0;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all (0 or 1) items equivalent to a given value.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               [Tested]\r
-               public void RemoveAllCopies(T item) { Remove(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this collection.\r
-               /// Only avaliable in DEBUG builds???\r
-               /// </summary>\r
-               /// <returns>True if check does not fail.</returns>\r
-               [Tested]\r
-               public override bool Check()\r
-               {\r
-                       bool retval = true;\r
-\r
-                       if (size > array.Length)\r
-                       {\r
-                               Console.WriteLine("Bad size ({0}) > array.Length ({1})", size, array.Length);\r
-                               return false;\r
-                       }\r
-\r
-                       for (int i = 0; i < size; i++)\r
-                       {\r
-                               if ((object)(array[i]) == null)\r
-                               {\r
-                                       Console.WriteLine("Bad element: null at index {0}", i);\r
-                                       return false;\r
-                               }\r
-\r
-                               if (i > 0 && comparer.Compare(array[i], array[i - 1]) <= 0)\r
-                               {\r
-                                       Console.WriteLine("Inversion at index {0}", i);\r
-                                       retval = false;\r
-                               }\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>False since this collection has set semantics</value>\r
-               [Tested]\r
-               public bool AllowsDuplicates { [Tested]get { return false; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to this collection if possible. If this collection has set\r
-               /// semantics, the item will be added if not already in the collection. If\r
-               /// bag semantics, the item will always be added.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True if item was added.</returns>\r
-               [Tested]\r
-               public bool Add(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int ind;\r
-\r
-                       if (binarySearch(item, out ind)) return false;\r
-\r
-                       insert(ind, item);\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add the elements from another collection to this collection. If this\r
-               /// collection has set semantics, only items not already in the collection\r
-               /// will be added.\r
-               /// </summary>\r
-               /// <param name="items">The items to add.</param>\r
-               [Tested]\r
-               public void AddAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       int toadd = EnumerableBase<T>.countItems(items), newsize = array.Length;\r
-\r
-                       while (newsize < size + toadd) { newsize *= 2; }\r
-\r
-                       T[] newarr = new T[newsize];\r
-\r
-                       toadd = 0;\r
-                       foreach (T item in items) newarr[size + toadd++] = item;\r
-\r
-                       Sorting.IntroSort<T>(newarr, size, size + toadd, comparer);\r
-\r
-                       int j = 0, i = 0;\r
-                       T lastitem = default(T);\r
-\r
-                       //The following eliminates duplicates (including duplicates in input)\r
-                       //while merging the old and new collection\r
-                       for (int k = size, klimit = size + toadd; k < klimit; k++)\r
-                       {\r
-                               while (i < size && comparer.Compare(array[i], newarr[k]) <= 0)\r
-                                       lastitem = newarr[j++] = array[i++];\r
-\r
-                               if (j == 0 || comparer.Compare(lastitem, newarr[k]) < 0)\r
-                                       lastitem = newarr[j++] = newarr[k];\r
-                       }\r
-\r
-                       while (i < size) newarr[j++] = array[i++];\r
-\r
-                       Array.Clear(newarr, j, size + toadd - j);\r
-                       size = j;\r
-                       array = newarr;\r
-               }\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. Since this\r
-        /// collection has set semantics, only items not already in the collection\r
-        /// will be added.\r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
-        {\r
-            int toadd = EnumerableBase<U>.countItems(items), newsize = array.Length;\r
-\r
-            while (newsize < size + toadd) { newsize *= 2; }\r
-\r
-            T[] newarr = new T[newsize];\r
-\r
-            toadd = 0;\r
-            foreach (T item in items) newarr[size + toadd++] = item;\r
-\r
-            Sorting.IntroSort<T>(newarr, size, size + toadd, comparer);\r
-\r
-            int j = 0, i = 0;\r
-            T lastitem = default(T);\r
-\r
-            //The following eliminates duplicates (including duplicates in input)\r
-            //while merging the old and new collection\r
-            for (int k = size, klimit = size + toadd; k < klimit; k++)\r
-            {\r
-                while (i < size && comparer.Compare(array[i], newarr[k]) <= 0)\r
-                    lastitem = newarr[j++] = array[i++];\r
-\r
-                if (j == 0 || comparer.Compare(lastitem, newarr[k]) < 0)\r
-                    lastitem = newarr[j++] = newarr[k];\r
-            }\r
-\r
-            while (i < size) newarr[j++] = array[i++];\r
-\r
-            Array.Clear(newarr, j, size + toadd - j);\r
-            size = j;\r
-            array = newarr;\r
-        }\r
-\r
-        #endregion\r
-\r
-               #region IPriorityQueue<T> Members\r
-\r
-               /// <summary>\r
-               /// Find the current least item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The least item.</returns>\r
-               [Tested]\r
-               public T FindMin()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       return array[0];\r
-               }\r
-               \r
-               /// <summary>\r
-               /// Remove the least item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMin()\r
-               {\r
-                       updatecheck();\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       T retval = array[0];\r
-\r
-                       size--;\r
-                       Array.Copy(array, 1, array, 0, size);\r
-                       array[size] = default(T);\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the current largest item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The largest item.</returns>\r
-               [Tested]\r
-               public T FindMax()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       return array[size - 1];\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the largest item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMax()\r
-               {\r
-                       updatecheck();\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       T retval = array[size - 1];\r
-\r
-                       size--;\r
-                       array[size] = default(T);\r
-                       return retval;\r
-               }\r
-\r
-        /// <summary>\r
-        /// The comparer object supplied at creation time for this collection\r
-        /// </summary>\r
-        /// <value>The comparer</value>\r
-        public IComparer<T> Comparer { get { return comparer; } }\r
-\r
-               #endregion\r
-\r
-               #region IIndexed<T> Members\r
-\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <value>The i'th item of this list.</value>\r
-               /// <param name="i">the index to lookup</param>\r
-               [Tested]\r
-               public T this[int i]\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-                               if (i < 0 || i >= size)\r
-                                       throw new IndexOutOfRangeException();\r
-\r
-                               return array[i];\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going forwrds from the start.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of item from start.</returns>\r
-               [Tested]\r
-               public int IndexOf(T item) { return indexOf(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going backwords from the end.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of of item from the end.</returns>\r
-               [Tested]\r
-               public int LastIndexOf(T item){ return indexOf(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the item at a specific position of the list.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <param name="i">The index of the item to remove.</param>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T RemoveAt(int i)\r
-               {\r
-                       if (i < 0 || i >= size)\r
-                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
-\r
-                       updatecheck();\r
-\r
-                       T retval = array[i];\r
-\r
-                       size--;\r
-                       Array.Copy(array, i + 1, array, i, size - i);\r
-                       array[size] = default(T);\r
-                       return retval;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Remove all items in an index interval.\r
-               /// <exception cref="IndexOutOfRangeException"/>???. \r
-               /// </summary>\r
-               /// <param name="start">The index of the first item to remove.</param>\r
-               /// <param name="count">The number of items to remove.</param>\r
-               [Tested]\r
-               public void RemoveInterval(int start, int count)\r
-               {\r
-                       updatecheck();\r
-                       checkRange(start, count);\r
-                       Array.Copy(array, start + count, array, start, size - start - count);\r
-                       size -= count;\r
-                       Array.Clear(array, size, count);\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IDirectedEnumerable<T> Members\r
-\r
-               /// <summary>\r
-               /// Create a collection containing the same items as this collection, but\r
-               /// whose enumerator will enumerate the items backwards. The new collection\r
-               /// will become invalid if the original is modified. Method typicaly used as in\r
-               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
-               /// </summary>\r
-               /// <returns>The backwards collection.</returns>\r
-               [Tested]\r
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\r
-               { return Backwards(); }\r
-\r
-               #endregion\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/hashing/HashBag.cs b/mcs/class/Mono.C5/hashing/HashBag.cs
deleted file mode 100644 (file)
index 080da67..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A bag collection based on a hash table of (item,count) pairs. \r
-       /// </summary>\r
-       public class HashBag<T>: CollectionBase<T>, ICollection<T>\r
-       {\r
-               #region Fields\r
-               HashSet<KeyValuePair<T,int>> dict;\r
-               #endregion\r
-\r
-               #region Constructors\r
-               /// <summary>\r
-               /// Create a hash bag with the deafult item hasher.\r
-               /// </summary>\r
-               public HashBag()\r
-               {\r
-                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
-                       dict = new HashSet<KeyValuePair<T,int>>();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hash bag with an external item hasher.\r
-               /// </summary>\r
-               /// <param name="h">The external hasher.</param>\r
-               public HashBag(IHasher<T> h)\r
-               {\r
-                       itemhasher = h;\r
-                       dict = new HashSet<KeyValuePair<T,int>>(new KeyValuePairHasher<T,int>(h));\r
-               }\r
-               #endregion\r
-\r
-               #region IEditableCollection<T> Members\r
-\r
-               /// <summary>\r
-               /// The complexity of the Contains operation\r
-               /// </summary>\r
-               /// <value>Always returns Speed.Constant</value>\r
-               [Tested]\r
-               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }\r
-\r
-\r
-               [Tested]\r
-               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
-\r
-\r
-               [Tested]\r
-               bool ICollection<T>.Equals(ICollection<T> that)\r
-               { return unsequencedequals(that); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item is in the bag \r
-               /// </summary>\r
-               /// <param name="item">The item to look for</param>\r
-               /// <returns>True if bag contains item</returns>\r
-               [Tested]\r
-               public virtual bool Contains(T item)\r
-               { return dict.Contains(new KeyValuePair<T,int>(item, 0)); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a given one) is in the bag and\r
-               /// if so report the actual item object found.\r
-               /// </summary>\r
-               /// <param name="item">On entry, the item to look for.\r
-               /// On exit the item found, if any</param>\r
-               /// <returns>True if bag contains item</returns>\r
-               [Tested]\r
-               public virtual bool Find(ref T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
-\r
-                       if (dict.Find(ref p))\r
-                       {\r
-                               item = p.key;\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a given one) is in the bag and\r
-               /// if so replace the item object in the bag with the supplied one.\r
-               /// </summary>\r
-               /// <param name="item">The item object to update with</param>\r
-               /// <returns>True if item was found (and updated)</returns>\r
-               [Tested]\r
-               public virtual bool Update(T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
-\r
-                       updatecheck();\r
-\r
-                       //Note: we cannot just do dict.Update. There is of course a way\r
-                       //around if we use the implementation of hashset -which we do not want to do.\r
-                       //The hashbag is moreover mainly a proof of concept\r
-                       if (dict.Find(ref p))\r
-                       {\r
-                               p.key = item;\r
-                               dict.Update(p);\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a given one) is in the bag.\r
-               /// If found, report the actual item object in the bag,\r
-               /// else add the supplied one.\r
-               /// </summary>\r
-               /// <param name="item">On entry, the item to look for or add.\r
-               /// On exit the actual object found, if any.</param>\r
-               /// <returns>True if item was found</returns>\r
-               [Tested]\r
-               public virtual bool FindOrAdd(ref T item)\r
-               {\r
-                       updatecheck();\r
-                       if (Find(ref item))\r
-                               return true;\r
-\r
-                       Add(item);\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a supplied one) is in the bag and\r
-               /// if so replace the item object in the set with the supplied one; else\r
-               /// add the supplied one.\r
-               /// </summary>\r
-               /// <param name="item">The item to look for and update or add</param>\r
-               /// <returns>True if item was updated</returns>\r
-               [Tested]\r
-               public virtual bool UpdateOrAdd(T item)\r
-               {\r
-                       updatecheck();\r
-                       if (Update(item))\r
-                               return true;\r
-\r
-                       Add(item);\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one copy af an item from the bag\r
-               /// </summary>\r
-               /// <param name="item">The item to remove</param>\r
-               /// <returns>True if item was (found and) removed </returns>\r
-               [Tested]\r
-               public virtual bool Remove(T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
-\r
-                       updatecheck();\r
-                       if (dict.Find(ref p))\r
-                       {\r
-                               size--;\r
-                               if (p.value == 1)\r
-                                       dict.Remove(p);\r
-                               else\r
-                               {\r
-                                       p.value--;\r
-                                       dict.Update(p);\r
-                               }\r
-\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one copy of an item from the bag, reporting the actual matching item object.\r
-               /// </summary>\r
-               /// <param name="item">On entry the item to remove.\r
-               /// On exit, the actual removed item object.</param>\r
-               /// <returns>True if item was found.</returns>\r
-               [Tested]\r
-               public virtual bool RemoveWithReturn(ref T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
-\r
-                       updatecheck();\r
-                       if (dict.Find(ref p))\r
-                       {\r
-                               item = p.key;\r
-                               size--;\r
-                               if (p.value == 1)\r
-                                       dict.Remove(p);\r
-                               else\r
-                               {\r
-                                       p.value--;\r
-                                       dict.Update(p);\r
-                               }\r
-\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Remove all items in a supplied collection from this bag, counting multiplicities.\r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public virtual void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-                       foreach (T item in items)\r
-                               Remove(item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from the bag, resetting internal table to initial size.\r
-               /// </summary>\r
-               [Tested]\r
-               public virtual void Clear()\r
-               {\r
-                       updatecheck();\r
-                       dict.Clear();\r
-                       size = 0;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items *not* in a supplied collection from this bag,\r
-               /// counting multiplicities.\r
-               /// </summary>\r
-               /// <param name="items">The items to retain</param>\r
-               [Tested]\r
-               public virtual void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       HashBag<T> res = new HashBag<T>(itemhasher);\r
-\r
-                       foreach (T item in items)\r
-                               if (res.ContainsCount(item) < ContainsCount(item))\r
-                                       res.Add(item);\r
-\r
-                       dict = res.dict;\r
-                       size = res.size;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if all items in a supplied collection is in this bag\r
-               /// (counting multiplicities). \r
-               /// </summary>\r
-               /// <param name="items">The items to look for.</param>\r
-               /// <returns>True if all items are found.</returns>\r
-               [Tested]\r
-               public virtual bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       HashBag<T> res = new HashBag<T>(itemhasher);\r
-\r
-                       foreach (T item in items)\r
-                               if (res.ContainsCount(item) < ContainsCount(item))\r
-                                       res.Add(item);\r
-                               else\r
-                                       return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an array containing all items in this bag (in enumeration order).\r
-               /// </summary>\r
-               /// <returns>The array</returns>\r
-               [Tested]\r
-               public override T[] ToArray()\r
-               {\r
-                       T[] res = new T[size];\r
-                       int ind = 0;\r
-\r
-                       foreach (KeyValuePair<T,int> p in dict)\r
-                               for (int i = 0; i < p.value; i++)\r
-                                       res[ind++] = p.key;\r
-\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Count the number of times an item is in this set.\r
-               /// </summary>\r
-               /// <param name="item">The item to look for.</param>\r
-               /// <returns>The count</returns>\r
-               [Tested]\r
-               public virtual int ContainsCount(T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
-\r
-                       if (dict.Find(ref p))\r
-                               return p.value;\r
-\r
-                       return 0;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all copies of item from this set.\r
-               /// </summary>\r
-               /// <param name="item">The item to remove</param>\r
-               [Tested]\r
-               public virtual void RemoveAllCopies(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 0);\r
-\r
-                       if (dict.Find(ref p))\r
-                       {\r
-                               size -= p.value;\r
-                               dict.Remove(p);\r
-                       }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ICollection<T> Members\r
-\r
-\r
-               /// <summary>\r
-               /// Copy the items of this bag to part of an array.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if i is negative.\r
-               /// <exception cref="ArgumentException"/> if the array does not have room for the items.\r
-               /// </summary>\r
-               /// <param name="a">The array to copy to</param>\r
-               /// <param name="i">The starting index.</param>\r
-               [Tested]\r
-               public override void CopyTo(T[] a, int i)\r
-               {\r
-                       if (i < 0)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       if (i + size > a.Length)\r
-                               throw new ArgumentException();\r
-\r
-                       foreach (KeyValuePair<T,int> p in dict)\r
-                               for (int j = 0; j < p.value; j++)\r
-                                       a[i++] = p.key;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-\r
-               /// <summary>\r
-               /// Report if this is a set collection.\r
-               /// </summary>\r
-               /// <value>Always true</value>\r
-               [Tested]\r
-               public virtual bool AllowsDuplicates { [Tested] get { return true; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to this bag.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>Always true</returns>\r
-               [Tested]\r
-               public virtual bool Add(T item)\r
-               {\r
-                       KeyValuePair<T,int> p = new KeyValuePair<T,int>(item, 1);\r
-\r
-                       updatecheck();\r
-                       if (dict.Find(ref p))\r
-                       {\r
-                               p.value++;\r
-                               dict.Update(p);\r
-                       }\r
-                       else\r
-                               dict.Add(p);\r
-\r
-                       size++;\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add all items of a collection to this set.\r
-               /// </summary>\r
-               /// <param name="items">The items to add</param>\r
-               [Tested]\r
-        public virtual void AddAll(MSG.IEnumerable<T> items)\r
-        {\r
-            foreach (T item in items)\r
-                Add(item);\r
-        }\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. \r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        public virtual void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
-        {\r
-            foreach (T item in items)\r
-                Add(item);\r
-        }\r
-\r
-        #endregion\r
-\r
-               #region IEnumerable<T> Members\r
-               /// <summary>\r
-               /// Create an enumerator for this bag.\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               [Tested]\r
-               public override MSG.IEnumerator<T> GetEnumerator()\r
-               {\r
-                       int left;\r
-                       int mystamp = stamp;\r
-\r
-                       foreach (KeyValuePair<T,int> p in dict)\r
-                       {\r
-                               left = p.value;\r
-                               while (left > 0)\r
-                               {\r
-                                       if (mystamp != stamp)\r
-                                               throw new InvalidOperationException("Collection was changed");\r
-\r
-                                       left--;\r
-                                       yield return p.key;\r
-                               }\r
-                       }\r
-               }\r
-               #endregion\r
-\r
-               #region Diagnostics\r
-               /// <summary>\r
-               /// Test internal structure of data (invariants)\r
-               /// </summary>\r
-               /// <returns>True if pass</returns>\r
-               [Tested]\r
-               public virtual bool Check()\r
-               {\r
-                       bool retval = dict.Check();\r
-                       int count = 0;\r
-\r
-                       foreach (KeyValuePair<T,int> p in dict)\r
-                               count += p.value;\r
-\r
-                       if (count != size)\r
-                       {\r
-                               Console.WriteLine("count({0}) != size({1})", count, size);\r
-                               retval = false;\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-               #endregion\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/hashing/HashDictionary.cs b/mcs/class/Mono.C5/hashing/HashDictionary.cs
deleted file mode 100644 (file)
index 325aee1..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A generic dictionary class based on a hash set class <see cref="T:C5.HashSet!1"/>.\r
-       /// </summary>\r
-       public class HashDictionary<K,V>: DictionaryBase<K,V>, IDictionary<K,V>\r
-       {\r
-               /// <summary>\r
-               /// Create a hash dictionary using a default hasher for the keys.\r
-               /// Initial capacity of internal table will be 16 entries and threshold for \r
-               /// expansion is 66% fill.\r
-               /// </summary>\r
-               public HashDictionary()\r
-               {\r
-                       pairs = new HashSet<KeyValuePair<K,V>>(new KeyValuePairHasher<K,V>());\r
-               }\r
-\r
-               /// <summary>\r
-               /// Create a hash dictionary using a custom hasher for the keys.\r
-               /// Initial capacity of internal table will be 16 entries and threshold for \r
-               /// expansion is 66% fill.\r
-               /// </summary>\r
-               /// <param name="h">The external key hasher</param>\r
-               public HashDictionary(IHasher<K> h)\r
-               {\r
-                       pairs = new HashSet<KeyValuePair<K,V>>(new KeyValuePairHasher<K,V>(h));\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hash dictionary using a custom hasher and prescribing the \r
-               /// initial size of the dictionary and a non-default threshold for internal table expansion.\r
-               /// </summary>\r
-               /// <param name="capacity">The initial capacity. Will be rounded upwards to nearest\r
-               /// power of 2, at least 16.</param>\r
-               /// <param name="fill">The expansion threshold. Must be between 10% and 90%.</param>\r
-               /// <param name="h">The external key hasher</param>\r
-               public HashDictionary(int capacity, double fill, IHasher<K> h)\r
-               {\r
-                       KeyValuePairHasher<K,V> kvph = new KeyValuePairHasher<K,V>(h);\r
-\r
-                       pairs = new HashSet<KeyValuePair<K,V>>(capacity, fill, kvph);\r
-               }\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/hashing/HashTable.cs b/mcs/class/Mono.C5/hashing/HashTable.cs
deleted file mode 100644 (file)
index bc734d9..0000000
+++ /dev/null
@@ -1,1442 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-#define LINEARPROBING\r
-#define REFBUCKETnot\r
-#define SHRINKnot\r
-#define INTERHASHERnot\r
-#define RANDOMINTERHASHER\r
\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A set collection class based on linear hashing\r
-       /// </summary>\r
-       public class HashSet<T>: CollectionBase<T>, ICollection<T>\r
-       {\r
-               #region Feature\r
-               /// <summary>\r
-               /// Enum class to assist printing of compilation alternatives.\r
-               /// </summary>\r
-               [Flags]\r
-               public enum Feature: short\r
-               {\r
-                       /// <summary>\r
-                       /// Nothing\r
-                       /// </summary>\r
-                       Dummy = 0,\r
-                       /// <summary>\r
-                       /// Buckets are of reference type\r
-                       /// </summary>\r
-                       RefTypeBucket = 1,\r
-                       /// <summary>\r
-                       /// Primary buckets are of value type\r
-                       /// </summary>\r
-                       ValueTypeBucket = 2,\r
-                       /// <summary>\r
-                       /// Using linear probing to resolve index clashes\r
-                       /// </summary>\r
-                       LinearProbing = 4,\r
-                       /// <summary>\r
-                       /// Shrink table when very sparsely filled\r
-                       /// </summary>\r
-                       ShrinkTable = 8,\r
-                       /// <summary>\r
-                       /// Use chaining to resolve index clashes\r
-                       /// </summary>\r
-                       Chaining = 16,\r
-                       /// <summary>\r
-                       /// Use hash function on item hash code\r
-                       /// </summary>\r
-                       InterHasher = 32,\r
-                       /// <summary>\r
-                       /// Use a universal family of hash functions on item hash code\r
-                       /// </summary>\r
-                       RandomInterHasher = 64\r
-               }\r
-\r
-\r
-\r
-               static Feature features = Feature.Dummy\r
-#if REFBUCKET\r
-               | Feature.RefTypeBucket\r
-#else\r
-               | Feature.ValueTypeBucket\r
-#endif\r
-#if SHRINK\r
-               | Feature.ShrinkTable\r
-#endif\r
-#if LINEARPROBING\r
-               | Feature.LinearProbing\r
-#else\r
-               | Feature.Chaining\r
-#endif\r
-#if INTERHASHER\r
-               | Feature.InterHasher\r
-#elif RANDOMINTERHASHER\r
-               | Feature.RandomInterHasher\r
-#endif\r
-               ;\r
-\r
-\r
-               /// <summary>\r
-               /// Show which implementation features was chosen at compilation time\r
-               /// </summary>\r
-               public static Feature Features { get { return features; } }\r
-\r
-               #endregion\r
-\r
-               #region Fields\r
-\r
-               int indexmask, bits, bitsc, origbits; //bitsc==32-bits; indexmask==(1<<bits)-1;\r
-\r
-               Bucket[] table;\r
-\r
-#if !REFBUCKET\r
-               bool defaultvalid = false;\r
-\r
-               T defaultitem;\r
-#endif\r
-               double fillfactor = 0.66;\r
-\r
-               int resizethreshhold;\r
-\r
-#if RANDOMINTERHASHER\r
-#if DEBUG\r
-               uint randomhasher = 1529784659;\r
-#else\r
-               uint randomhasher = (2 * (uint)(new Random()).Next() + 1) * 1529784659;\r
-#endif\r
-#endif\r
-\r
-               #endregion\r
-\r
-               #region Bucket nested class(es)\r
-#if REFBUCKET\r
-               class Bucket\r
-               {\r
-                       internal T item;\r
-\r
-                       internal int hashval; //Cache!\r
-\r
-#if LINEARPROBING\r
-                       internal Bucket(T item, int hashval)\r
-                       {\r
-                               this.item = item;\r
-                               this.hashval = hashval;\r
-                       }\r
-#else\r
-                       internal Bucket overflow;\r
-\r
-                       internal Bucket(T item, int hashval, Bucket overflow)\r
-                       {\r
-                               this.item = item;\r
-                               this.hashval = hashval;\r
-                               this.overflow = overflow;\r
-                       }\r
-#endif\r
-               }\r
-#else\r
-               struct Bucket\r
-               {\r
-                       internal T item;\r
-\r
-                       internal int hashval; //Cache!\r
-\r
-#if LINEARPROBING\r
-                       internal Bucket(T item, int hashval)\r
-                       {\r
-                               this.item = item;\r
-                               this.hashval = hashval;\r
-                       }\r
-#else\r
-                       internal OverflowBucket overflow;\r
-\r
-\r
-                       internal Bucket(T item, int hashval)\r
-                       {\r
-                               this.item = item;\r
-                               this.hashval = hashval;\r
-                               this.overflow = OverflowBuckedefault(T);\r
-                       }\r
-#endif\r
-               }\r
-\r
-\r
-#if !LINEARPROBING\r
-               class OverflowBucket\r
-               {\r
-                       internal T item;\r
-\r
-                       internal int hashval; //Cache!\r
-\r
-                       internal OverflowBucket overflow;\r
-\r
-\r
-                       internal OverflowBucket(T item, int hashval, OverflowBucket overflow)\r
-                       {\r
-                               this.item = item;\r
-                               this.hashval = hashval;\r
-                               this.overflow = overflow;\r
-                       }\r
-               }\r
-#endif\r
-#endif\r
-\r
-               #endregion\r
-\r
-               #region Basic Util\r
-\r
-               bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }\r
-\r
-#if !REFBUCKET\r
-               bool isnull(T item) { return itemhasher.Equals(item, default(T)); }\r
-#endif\r
-\r
-               int gethashcode(T item) { return itemhasher.GetHashCode(item); }\r
-\r
-\r
-               int hv2i(int hashval)\r
-               {\r
-#if INTERHASHER\r
-                       //Note: *inverse  mod 2^32 is -1503427877\r
-                       return (int)(((uint)hashval * 1529784659) >>bitsc); \r
-#elif RANDOMINTERHASHER\r
-                       return (int)(((uint)hashval * randomhasher) >>bitsc); \r
-#else\r
-                       return indexmask & hashval;\r
-#endif\r
-               }\r
-\r
-\r
-               void expand()\r
-               {\r
-                       //Console.WriteLine(String.Format("Expand to {0} bits", bits+1));\r
-                       resize(bits + 1);\r
-               }\r
-\r
-\r
-               void shrink()\r
-               {\r
-                       if (bits > 3)\r
-                       {\r
-                               //Console.WriteLine(String.Format("Shrink to {0} bits", bits - 1));\r
-                               resize(bits - 1);\r
-                       }\r
-               }\r
-\r
-\r
-               void resize(int bits)\r
-               {\r
-                       //Console.WriteLine(String.Format("Resize to {0} bits", bits));\r
-                       this.bits = bits;\r
-                       bitsc = 32 - bits;\r
-                       indexmask = (1 << bits) - 1;\r
-\r
-                       Bucket[] newtable = new Bucket[indexmask + 1];\r
-\r
-                       for (int i = 0, s = table.Length; i < s; i++)\r
-                       {\r
-                               Bucket b = table[i];\r
-\r
-#if LINEARPROBING\r
-#if REFBUCKET\r
-                               if (b != null)\r
-                               {\r
-                                       int j = hv2i(b.hashval);\r
-\r
-                                       while (newtable[j] != null) { j = indexmask & (j + 1); }\r
-\r
-                                       newtable[j] = b;\r
-                               }\r
-#else\r
-                               if (!isnull(b.item))\r
-                               {\r
-                                       int j = hv2i(b.hashval);\r
-\r
-                                       while (!isnull(newtable[j].item)) { j = indexmask & (j + 1); }\r
-\r
-                                       newtable[j] = b;\r
-                               }\r
-#endif\r
-#else\r
-#if REFBUCKET\r
-                               while (b != null)\r
-                               {\r
-                                       int j = hv2i(b.hashval);\r
-\r
-                                       newtable[j] = new Bucket(b.item, b.hashval, newtable[j]);\r
-                                       b = b.overflow;\r
-                               }\r
-#else\r
-                               if (!isnull(b.item))\r
-                               {\r
-                                       insert(b.item, b.hashval, newtable);\r
-\r
-                                       OverflowBucket ob = b.overflow;\r
-\r
-                                       while (ob != null)\r
-                                       {\r
-                                               insert(ob.item, ob.hashval, newtable);\r
-                                               ob = ob.overflow;\r
-                                       }\r
-                               }\r
-#endif\r
-#endif\r
-                       }\r
-\r
-                       table = newtable;\r
-                       resizethreshhold = (int)(table.Length * fillfactor);\r
-                       //Console.WriteLine(String.Format("Resize to {0} bits done", bits));\r
-               }\r
-\r
-#if REFBUCKET \r
-#else\r
-#if LINEARPROBING\r
-#else\r
-               //Only for resize!!!\r
-               private void insert(T item, int hashval, Bucket[] t)\r
-               {\r
-                       int i = hv2i(hashval);\r
-                       Bucket b = t[i];\r
-\r
-                       if (!isnull(b.item))\r
-                       {\r
-                               t[i].overflow = new OverflowBucket(item, hashval, b.overflow);\r
-                       }\r
-                       else\r
-                               t[i] = new Bucket(item, hashval);\r
-               }\r
-#endif\r
-#endif\r
-\r
-               private bool searchoradd(ref T item, bool add, bool update)\r
-               {\r
-#if LINEARPROBING\r
-#if REFBUCKET\r
-                       int hashval = gethashcode(item);\r
-                       int i = hv2i(hashval);\r
-                       Bucket b = table[i];\r
-\r
-                       while (b != null)\r
-                       {\r
-                               if (equals(b.item, item))\r
-                               {\r
-                                       if (update)\r
-                                               b.item = item;\r
-                                       else\r
-                                               item = b.item;\r
-\r
-                                       return true;\r
-                               }\r
-\r
-                               b = table[i = indexmask & (i + 1)];\r
-                       }\r
-\r
-                       if (!add) goto notfound;\r
-\r
-                       table[i] = new Bucket(item, hashval);\r
-                       \r
-#else\r
-                       if (isnull(item))\r
-                       {\r
-                               if (defaultvalid)\r
-                               {\r
-                                       if (update)\r
-                                               defaultitem = item;\r
-                                       else\r
-                                               item = defaultitem;\r
-\r
-                                       return true;\r
-                               }\r
-\r
-                               if (!add) goto notfound;\r
-\r
-                               defaultvalid = true;\r
-                               defaultitem = item;\r
-                       }\r
-                       else\r
-                       {\r
-                               int hashval = gethashcode(item);\r
-                               int i = hv2i(hashval);\r
-                               T t = table[i].item;\r
-\r
-                               while (!isnull(t))\r
-                               {\r
-                                       if (equals(t, item))\r
-                                       {\r
-                                               if (update)\r
-                                                       table[i].item = item;\r
-                                               else\r
-                                                       item = t;\r
-\r
-                                               return true;\r
-                                       }\r
-\r
-                                       t = table[i = indexmask & (i + 1)].item;\r
-                               }\r
-\r
-                               if (!add) goto notfound;\r
-\r
-                               table[i] = new Bucket(item, hashval);\r
-                       }\r
-#endif\r
-#else\r
-#if REFBUCKET\r
-                       int hashval = gethashcode(item);\r
-                       int i = hv2i(hashval);\r
-                       Bucket b = table[i], bold = null;\r
-\r
-                       if (b != null)\r
-                       {\r
-                               while (b != null)\r
-                               {\r
-                                       if (equals(b.item, item))\r
-                                       {\r
-                                               if (update)\r
-                                                       b.item = item;\r
-                                               else\r
-                                                       item = b.item;\r
-\r
-                                               return true;\r
-                                       }\r
-\r
-                                       bold = b;\r
-                                       b = b.overflow;\r
-                               }\r
-\r
-                               if (!add) goto notfound;\r
-\r
-                               bold.overflow = new Bucket(item, hashval, null);\r
-                       }\r
-                       else\r
-                       {\r
-                               if (!add) goto notfound;\r
-\r
-                               table[i] = new Bucket(item, hashval, null);\r
-                       }\r
-#else\r
-                       if (isnull(item))\r
-                       {\r
-                               if (defaultvalid)\r
-                               {\r
-                                       if (update)\r
-                                               defaultitem = item;\r
-                                       else\r
-                                               item = defaultitem;\r
-\r
-                                       return true;\r
-                               }\r
-\r
-                               if (!add) goto notfound;\r
-\r
-                               defaultvalid = true;\r
-                               defaultitem = item;\r
-                       }\r
-                       else\r
-                       {\r
-                               int hashval = gethashcode(item);\r
-                               int i = hv2i(hashval);\r
-                               Bucket b = table[i];\r
-\r
-                               if (!isnull(b.item))\r
-                               {\r
-                                       if (equals(b.item, item))\r
-                                       {\r
-                                               if (update)\r
-                                                       table[i].item = item;\r
-                                               else\r
-                                                       item = b.item;\r
-\r
-                                               return true;\r
-                                       }\r
-\r
-                                       OverflowBucket ob = table[i].overflow;\r
-\r
-                                       if (ob == null)\r
-                                       {\r
-                                               if (!add) goto notfound;\r
-\r
-                                               table[i].overflow = new OverflowBucket(item, hashval, null);\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               while (ob.overflow != null)\r
-                                               {\r
-                                                       if (equals(item, ob.item))\r
-                                                       {\r
-                                                               if (update)\r
-                                                                       ob.item = item;\r
-                                                               else\r
-                                                                       item = ob.item;\r
-\r
-                                                               return true;\r
-                                                       }\r
-\r
-                                                       ob = ob.overflow;\r
-                                               }\r
-\r
-                                               if (equals(item, ob.item))\r
-                                               {\r
-                                                       if (update)\r
-                                                               ob.item = item;\r
-                                                       else\r
-                                                               item = ob.item;\r
-\r
-                                                       return true;\r
-                                               }\r
-\r
-                                               if (!add) goto notfound;\r
-\r
-                                               ob.overflow = new OverflowBucket(item, hashval, null);\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       if (!add) goto notfound;\r
-\r
-                                       table[i] = new Bucket(item, hashval);\r
-                               }\r
-                       }\r
-#endif\r
-#endif\r
-                       size++;\r
-                       if (size > resizethreshhold)\r
-                               expand();\r
-               notfound :\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               private bool remove(ref T item)\r
-               {\r
-                       if (size == 0)\r
-                               return false;\r
-#if LINEARPROBING\r
-#if REFBUCKET\r
-                       int hashval = gethashcode(item);\r
-                       int index = hv2i(hashval);\r
-                       Bucket b = table[index];\r
-\r
-                       while (b != null)\r
-                       {\r
-                               if (equals(item, b.item))\r
-                               {\r
-                                       //ref\r
-                                       item = table[index];\r
-                                       table[index] = null;\r
-\r
-                                       //Algorithm R\r
-                                       int j = (index + 1) & indexmask;\r
-\r
-                                       b = table[j];\r
-                                       while (b != null)\r
-                                       {\r
-                                               int k = hv2i(b.hashval);\r
-\r
-                                               if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index))\r
-                                               //if (index > j ? (j < k && k <= index): (k <= index || j < k) )\r
-                                               {\r
-                                                       table[index] = b;\r
-                                                       table[j] = null;\r
-                                                       index = j;\r
-                                               }\r
-\r
-                                               j = (j + 1) & indexmask;\r
-                                               b = table[j];\r
-                                       }\r
-\r
-                                       goto found;\r
-                               }\r
-\r
-                               b = table[index = indexmask & (index + 1)];\r
-                       }\r
-                       return false;\r
-#else\r
-                       if (isnull(item))\r
-                       {\r
-                               if (!defaultvalid)\r
-                                       return false;\r
-\r
-                               //ref\r
-                               item = defaultitem;\r
-                               defaultvalid = false;\r
-                               defaultitem = default(T); //No spaceleaks!\r
-                       }\r
-                       else\r
-                       {\r
-                               int hashval = gethashcode(item);\r
-                               int index = hv2i(hashval);\r
-                               T t = table[index].item;\r
-\r
-                               while (!isnull(t))\r
-                               {\r
-                                       if (equals(item, t))\r
-                                       {\r
-                                               //ref\r
-                                               item = table[index].item;\r
-                                               table[index].item = default(T);\r
-\r
-                                               //algorithm R\r
-                                               int j = (index + 1) & indexmask;\r
-                                               Bucket b = table[j];\r
-\r
-                                               while (!isnull(b.item))\r
-                                               {\r
-                                                       int k = hv2i(b.hashval);\r
-\r
-                                                       if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index))\r
-                                                       {\r
-                                                               table[index] = b;\r
-                                                               table[j].item = default(T);\r
-                                                               index = j;\r
-                                                       }\r
-\r
-                                                       j = (j + 1) & indexmask;\r
-                                                       b = table[j];\r
-                                               }\r
-\r
-                                               goto found;\r
-                                       }\r
-\r
-                                       t = table[index = indexmask & (index + 1)].item;\r
-                               }\r
-\r
-                               return false;\r
-                       }\r
-#endif\r
-                       found :\r
-#else\r
-#if REFBUCKET\r
-                       int hashval = gethashcode(item);\r
-                       int index = hv2i(hashval);\r
-                       Bucket b = table[index], bold;\r
-\r
-                       if (b == null)\r
-                               return false;\r
-\r
-                       if (equals(item, b.item)) {\r
-                               //ref\r
-                               item = b.item;\r
-                               table[index] = b.overflow;\r
-                               }\r
-                       else\r
-                       {\r
-                               bold = b;\r
-                               b = b.overflow;\r
-                               while (b != null && !equals(item, b.item))\r
-                               {\r
-                                       bold = b;\r
-                                       b = b.overflow;\r
-                               }\r
-\r
-                               if (b == null)\r
-                                       return false;\r
-\r
-                               //ref\r
-                               item = b.item;\r
-                               bold.overflow = b.overflow;\r
-                       }\r
-                       \r
-#else\r
-                       if (isnull(item))\r
-                       {\r
-                               if (!defaultvalid)\r
-                                       return false;\r
-\r
-                               //ref\r
-                               item = defaultitem;\r
-                               defaultvalid = false;\r
-                               defaultitem = default(T); //No spaceleaks!\r
-                       }\r
-                       else\r
-                       {\r
-                               int hashval = gethashcode(item);\r
-                               int index = hv2i(hashval);\r
-                               Bucket b = table[index];\r
-                               OverflowBucket ob = b.overflow;\r
-\r
-                               if (equals(item, b.item))\r
-                               {\r
-                                       //ref\r
-                                       item = b.item;\r
-                                       if (ob == null)\r
-                                       {\r
-                                               table[index] = new Bucket();\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               b = new Bucket(ob.item, ob.hashval);\r
-                                               b.overflow = ob.overflow;\r
-                                               table[index] = b;\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       if (ob == null)\r
-                                               return false;\r
-\r
-                                       if (equals(item, ob.item)) \r
-                                       {\r
-                                               //ref\r
-                                               item=ob.item;\r
-                                               table[index].overflow = ob.overflow;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               while (ob.overflow != null)\r
-                                                       if (equals(item, ob.overflow.item))\r
-                                                       {\r
-                                                               //ref\r
-                                                               item = ob.overflow.item;\r
-                                                               break;\r
-                                                       }\r
-                                                       else\r
-                                                               ob = ob.overflow;\r
-\r
-                                               if (ob.overflow == null)\r
-                                                       return false;\r
-\r
-                                               ob.overflow = ob.overflow.overflow;\r
-                                       }\r
-                               }\r
-                       }\r
-#endif\r
-#endif\r
-                       size--;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               private void clear()\r
-               {\r
-                       bits = origbits;\r
-                       bitsc = 32 - bits;\r
-                       indexmask = (1 << bits) - 1;\r
-                       size = 0;\r
-                       table = new Bucket[indexmask + 1];\r
-                       resizethreshhold = (int)(table.Length * fillfactor);\r
-#if !REFBUCKET\r
-                       defaultitem = default(T);\r
-                       defaultvalid = false;\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-               /// <summary>\r
-               /// Create a hash set with natural item hasher and default fill threshold (66%)\r
-               /// and initial table size (16).\r
-               /// </summary>\r
-               public HashSet() \r
-                       : this(HasherBuilder.ByPrototype<T>.Examine()) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hash set with external item hasher and default fill threshold (66%)\r
-               /// and initial table size (16).\r
-               /// </summary>\r
-               /// <param name="itemhasher">The external item hasher</param>\r
-               public HashSet(IHasher<T> itemhasher) \r
-                       : this(16, itemhasher) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hash set with external item hasher and default fill threshold (66%)\r
-               /// </summary>\r
-               /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>\r
-               /// <param name="itemhasher">The external item hasher</param>\r
-               public HashSet(int capacity, IHasher<T> itemhasher) \r
-                       : this(capacity, 0.66, itemhasher) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hash set with external item hasher.\r
-               /// </summary>\r
-               /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>\r
-               /// <param name="fill">Fill threshold (in range 10% to 90%)</param>\r
-               /// <param name="itemhasher">The external item hasher</param>\r
-               public HashSet(int capacity, double fill, IHasher<T> itemhasher)\r
-               {\r
-                       if (fill < 0.1 || fill > 0.9)\r
-                               throw new ArgumentException("Fill outside valid range [0.1, 0.9]");\r
-\r
-                       if (capacity <= 0)\r
-                               throw new ArgumentException("Non-negative capacity ");\r
-\r
-                       this.itemhasher = itemhasher;\r
-                       origbits = 4;\r
-                       while (capacity - 1 >>origbits > 0) origbits++;\r
-\r
-                       clear();\r
-               }\r
-\r
-\r
-\r
-               #endregion\r
-\r
-               #region IEditableCollection<T> Members\r
-\r
-               /// <summary>\r
-               /// The complexity of the Contains operation\r
-               /// </summary>\r
-               /// <value>Always returns Speed.Constant</value>\r
-               [Tested]\r
-               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }\r
-\r
-\r
-               [Tested]\r
-               int ICollection<T>.GetHashCode()\r
-               { return unsequencedhashcode(); }\r
-\r
-\r
-               [Tested]\r
-               bool ICollection<T>.Equals(ICollection<T> that)\r
-               { return unsequencedequals(that); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item is in the set \r
-               /// </summary>\r
-               /// <param name="item">The item to look for</param>\r
-               /// <returns>True if set contains item</returns>\r
-               [Tested]\r
-               public virtual bool Contains(T item) { return searchoradd(ref item, false, false); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a given one) is in the set and\r
-               /// if so report the actual item object found.\r
-               /// </summary>\r
-               /// <param name="item">On entry, the item to look for.\r
-               /// On exit the item found, if any</param>\r
-               /// <returns>True if set contains item</returns>\r
-               [Tested]\r
-               public virtual bool Find(ref T item) { return searchoradd(ref item, false, false); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a given one) is in the set and\r
-               /// if so replace the item object in the set with the supplied one.\r
-               /// </summary>\r
-               /// <param name="item">The item object to update with</param>\r
-               /// <returns>True if item was found (and updated)</returns>\r
-               [Tested]\r
-               public virtual bool Update(T item)\r
-               { updatecheck(); return searchoradd(ref item, false, true); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a given one) is in the set.\r
-               /// If found, report the actual item object in the set,\r
-               /// else add the supplied one.\r
-               /// </summary>\r
-               /// <param name="item">On entry, the item to look for or add.\r
-               /// On exit the actual object found, if any.</param>\r
-               /// <returns>True if item was found</returns>\r
-               [Tested]\r
-               public virtual bool FindOrAdd(ref T item)\r
-               { updatecheck(); return searchoradd(ref item, true, false); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if an item (collection equal to a supplied one) is in the set and\r
-               /// if so replace the item object in the set with the supplied one; else\r
-               /// add the supplied one.\r
-               /// </summary>\r
-               /// <param name="item">The item to look for and update or add</param>\r
-               /// <returns>True if item was updated</returns>\r
-               [Tested]\r
-               public virtual bool UpdateOrAdd(T item)\r
-               { updatecheck(); return searchoradd(ref item, true, true); }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove an item from the set\r
-               /// </summary>\r
-               /// <param name="item">The item to remove</param>\r
-               /// <returns>True if item was (found and) removed </returns>\r
-               [Tested]\r
-               public virtual bool Remove(T item)\r
-               {\r
-                       updatecheck();\r
-                       if (remove(ref item))\r
-                       {\r
-#if SHRINK\r
-                               if (size<resizethreshhold/2 && resizethreshhold>8)\r
-                                       shrink();\r
-#endif\r
-                               return true;\r
-                       }\r
-                       else\r
-                               return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove an item from the set, reporting the actual matching item object.\r
-               /// </summary>\r
-               /// <param name="item">On entry the item to remove.\r
-               /// On exit, the actual removed item object.</param>\r
-               /// <returns>True if item was found.</returns>\r
-               [Tested]\r
-               public virtual bool RemoveWithReturn(ref T item)\r
-               {\r
-                       updatecheck();\r
-                       if (remove(ref item))\r
-                       {\r
-#if SHRINK\r
-                               if (size<resizethreshhold/2 && resizethreshhold>8)\r
-                                       shrink();\r
-#endif\r
-                               return true;\r
-                       }\r
-                       else\r
-                               return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in a supplied collection from this set.\r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public virtual void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       T jtem;\r
-\r
-                       foreach (T item in items)\r
-                       { jtem = item; remove(ref jtem); }\r
-#if SHRINK\r
-                       if (size < resizethreshhold / 2 && resizethreshhold > 16)\r
-                       {\r
-                               int newlength = table.Length;\r
-\r
-                               while (newlength >= 32 && newlength * fillfactor / 2 > size)\r
-                                       newlength /= 2;\r
-\r
-                               resize(newlength - 1);\r
-                       }\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from the set, resetting internal table to initial size.\r
-               /// </summary>\r
-               [Tested]\r
-               public virtual void Clear()\r
-               {\r
-                       updatecheck();\r
-                       clear();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items *not* in a supplied collection from this set.\r
-               /// </summary>\r
-               /// <param name="items">The items to retain</param>\r
-               [Tested]\r
-               public virtual void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       HashSet<T> t = (HashSet<T>)MemberwiseClone();\r
-\r
-                       t.Clear();\r
-\r
-                       //This only works for sets:\r
-                       foreach (T item in items)\r
-                               if (Contains(item))\r
-                               {\r
-                                       T jtem = item;\r
-\r
-                                       t.searchoradd(ref jtem, true, false);\r
-                               }\r
-\r
-                       table = t.table;\r
-                       size = t.size;\r
-#if !REFBUCKET\r
-                       defaultvalid = t.defaultvalid;\r
-                       defaultitem = t.defaultitem;\r
-#endif\r
-                       indexmask = t.indexmask;\r
-                       resizethreshhold = t.resizethreshhold;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if all items in a supplied collection is in this set\r
-               /// (ignoring multiplicities). \r
-               /// </summary>\r
-               /// <param name="items">The items to look for.</param>\r
-               /// <returns>True if all items are found.</returns>\r
-               [Tested]\r
-               public virtual bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       foreach (T item in items)\r
-                               if (!Contains(item))\r
-                                       return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an array containing all items in this set (in enumeration order).\r
-               /// </summary>\r
-               /// <returns>The array</returns>\r
-               [Tested]\r
-               public override T[] ToArray()\r
-               {\r
-                       T[] res = new T[size];\r
-                       int index = 0;\r
-\r
-#if !REFBUCKET\r
-                       if (defaultvalid)\r
-                               res[index++] = defaultitem;\r
-#endif\r
-                       for (int i = 0; i < table.Length; i++)\r
-                       {\r
-                               Bucket b = table[i];\r
-#if LINEARPROBING\r
-#if REFBUCKET\r
-                               if (b != null)\r
-                                       res[index++] = b.item;\r
-#else\r
-                               if (!isnull(b.item))\r
-                                       res[index++] = b.item;\r
-#endif\r
-#else\r
-#if REFBUCKET\r
-                               while (b != null)\r
-                               {\r
-                                       res[index++] = b.item;\r
-                                       b = b.overflow;\r
-                               }\r
-#else\r
-                               if (!isnull(b.item))\r
-                               {\r
-                                       res[index++] = b.item;\r
-\r
-                                       OverflowBucket ob = b.overflow;\r
-\r
-                                       while (ob != null)\r
-                                       {\r
-                                               res[index++] = ob.item;\r
-                                               ob = ob.overflow;\r
-                                       }\r
-                               }\r
-#endif\r
-#endif\r
-                       }\r
-\r
-                       Debug.Assert(size == index);\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Count the number of times an item is in this set (either 0 or 1).\r
-               /// </summary>\r
-               /// <param name="item">The item to look for.</param>\r
-               /// <returns>1 if item is in set, 0 else</returns>\r
-               [Tested]\r
-               public virtual int ContainsCount(T item) { return Contains(item) ? 1 : 0; }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all (at most 1) copies of item from this set.\r
-               /// </summary>\r
-               /// <param name="item">The item to remove</param>\r
-               [Tested]\r
-               public virtual void RemoveAllCopies(T item) { Remove(item); }\r
-\r
-               #endregion\r
-\r
-               #region IEnumerable<T> Members\r
-\r
-               /// <summary>\r
-               /// Create an enumerator for this set.\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               [Tested]\r
-               public override MSG.IEnumerator<T> GetEnumerator()\r
-               {\r
-                       int index = -1;\r
-                       int mystamp = stamp;\r
-                       int len = table.Length;\r
-\r
-#if LINEARPROBING\r
-#if REFBUCKET\r
-                       while (++index < len)\r
-                       {\r
-                               if (mystamp != stamp) throw new InvalidOperationException();\r
-\r
-                               if (table[index] != null) yield table[index].item;\r
-                       }\r
-#else\r
-                       if (defaultvalid)\r
-                               yield return defaultitem;\r
-\r
-                       while (++index < len)\r
-                       {\r
-                               if (mystamp != stamp) throw new InvalidOperationException();\r
-\r
-                               T item = table[index].item;\r
-\r
-                               if (!isnull(item)) yield return item;\r
-                       }\r
-#endif\r
-#else\r
-#if REFBUCKET\r
-                       Bucket b = null;\r
-#else\r
-                       OverflowBucket ob = null;\r
-\r
-                       if (defaultvalid)\r
-                               yield defaultitem;\r
-#endif\r
-                       while (true)\r
-                       {\r
-                               if (mystamp != stamp)\r
-                                       throw new InvalidOperationException();\r
-\r
-#if REFBUCKET\r
-                               if (b == null || b.overflow == null)\r
-                               {\r
-                                       do\r
-                                       {\r
-                                               if (++index >= len) yield break;\r
-                                       } while (table[index] == null);\r
-\r
-                                       b = table[index];\r
-                                       yield b.item;\r
-                               }\r
-                               else\r
-                               {\r
-                                       b = b.overflow;\r
-                                       yield b.item;\r
-                               }\r
-#else\r
-                               if (ob != null && ob.overflow != null)\r
-                               {\r
-                                       ob = ob.overflow;\r
-                                       yield ob.item;\r
-                               }\r
-                               else if (index >= 0 && ob == null && (ob = table[index].overflow) != null)\r
-                               {\r
-                                       yield ob.item;\r
-                               }\r
-                               else\r
-                               {\r
-                                       do\r
-                                       {\r
-                                               if (++index >= len) yield break;\r
-                                       } while (isnull(table[index].item));\r
-\r
-                                       yield table[index].item;\r
-                                       ob = null;\r
-                               }\r
-#endif\r
-                       }\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-               /// <summary>\r
-               /// Report if this is a set collection.\r
-               /// </summary>\r
-               /// <value>Always false</value>\r
-               [Tested]\r
-               public virtual bool AllowsDuplicates { [Tested]get { return false; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to this set.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True if item was added (i.e. not found)</returns>\r
-               [Tested]\r
-               public virtual bool Add(T item)\r
-               {\r
-                       updatecheck();\r
-                       return !searchoradd(ref item, true, false);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add all items of a collection to this set.\r
-               /// </summary>\r
-               /// <param name="items">The items to add</param>\r
-               [Tested]\r
-               public virtual void AddAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-                       foreach (T item in items)\r
-                       {\r
-                               T jtem = item;\r
-\r
-                               searchoradd(ref jtem, true, false);\r
-                       }\r
-               }\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. Since this\r
-        /// collection has set semantics, only items not already in the collection\r
-        /// will be added.\r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        public virtual void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
-        {\r
-            updatecheck();\r
-            foreach (T item in items)\r
-            {\r
-                T jtem = item;\r
-\r
-                searchoradd(ref jtem, true, false);\r
-            }\r
-        }\r
-\r
-\r
-               #endregion\r
-\r
-               #region Diagnostics\r
-\r
-               /// <summary>\r
-               /// Test internal structure of data (invariants)\r
-               /// </summary>\r
-               /// <returns>True if pass</returns>\r
-               [Tested]\r
-               public virtual bool Check()\r
-               {\r
-                       int count = 0;\r
-#if LINEARPROBING\r
-                       int lasthole = table.Length - 1;\r
-\r
-#if REFBUCKET\r
-                       while (lasthole >= 0 && table[lasthole] != null)\r
-#else\r
-                       while (lasthole >= 0 && !isnull(table[lasthole].item))\r
-#endif\r
-                       {\r
-                               lasthole--;\r
-                               count++;\r
-                       }\r
-\r
-                       if (lasthole < 0)\r
-                       {\r
-                               Console.WriteLine("Table is completely filled!");\r
-                               return false;\r
-                       }\r
-\r
-                       for (int cellindex = lasthole + 1, s = table.Length; cellindex < s; cellindex++)\r
-                       {\r
-                               Bucket b = table[cellindex];\r
-                               int hashindex = hv2i(b.hashval);\r
-\r
-                               if (hashindex <= lasthole || hashindex > cellindex)\r
-                               {\r
-                                       Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, lasthole={4}", b.item, b.hashval, hashindex, cellindex, lasthole);\r
-                                       return false;\r
-                               }\r
-                       }\r
-\r
-                       int latesthole = -1;\r
-\r
-                       for (int cellindex = 0; cellindex < lasthole; cellindex++)\r
-                       {\r
-                               Bucket b = table[cellindex];\r
-\r
-#if REFBUCKET\r
-                               if (b != null)\r
-#else\r
-                               if (!isnull(b.item))\r
-#endif\r
-                               {\r
-                                       count++;\r
-\r
-                                       int hashindex = hv2i(b.hashval);\r
-\r
-                                       if (cellindex < hashindex && hashindex <= lasthole)\r
-                                       {\r
-                                               Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole);\r
-                                               return false;\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       latesthole = cellindex;\r
-                                       break;\r
-                               }\r
-                       }\r
-\r
-                       for (int cellindex = latesthole + 1; cellindex < lasthole; cellindex++)\r
-                       {\r
-                               Bucket b = table[cellindex];\r
-\r
-#if REFBUCKET\r
-                               if (b != null)\r
-#else\r
-                               if (!isnull(b.item))\r
-#endif\r
-                               {\r
-                                       count++;\r
-\r
-                                       int hashindex = hv2i(b.hashval);\r
-\r
-                                       if (hashindex <= latesthole || cellindex < hashindex)\r
-                                       {\r
-                                               Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole);\r
-                                               return false;\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       latesthole = cellindex;\r
-                               }\r
-                       }\r
-\r
-                       return true;\r
-#else\r
-                       bool retval = true;\r
-                       for (int i = 0, s = table.Length; i < s; i++)\r
-                       {\r
-                               int level = 0;\r
-                               Bucket b = table[i];\r
-#if REFBUCKET\r
-                               while (b != null)\r
-                               {\r
-                                       if (i != hv2i(b.hashval))\r
-                                       {\r
-                                               Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);\r
-                                               retval = false;\r
-                                       }\r
-\r
-                                       count++;\r
-                                       level++;\r
-                                       b = b.overflow;\r
-                               }\r
-#else\r
-                               if (!isnull(b.item))\r
-                               {\r
-                                       count++;\r
-                                       if (i != hv2i(b.hashval))\r
-                                       {\r
-                                               Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);\r
-                                               retval = false;\r
-                                       }\r
-\r
-                                       OverflowBucket ob = b.overflow;\r
-\r
-                                       while (ob != null)\r
-                                       {\r
-                                               level++;\r
-                                               count++;\r
-                                               if (i != hv2i(ob.hashval))\r
-                                               {\r
-                                                       Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);\r
-                                                       retval = false;\r
-                                               }\r
-\r
-                                               ob = ob.overflow;\r
-                                       }\r
-                               }\r
-#endif\r
-                       }\r
-\r
-                       if (count != size)\r
-                       {\r
-                               Console.WriteLine("size({0}) != count({1})", size, count);\r
-                               retval = false;\r
-                       }\r
-\r
-                       return retval;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Produce statistics on distribution of bucket sizes. Current implementation is incomplete.\r
-               /// </summary>\r
-               /// <returns>Histogram data.</returns>\r
-               [Tested(via = "Manually")]\r
-               public ISortedDictionary<int,int> BucketSizeDistribution()\r
-               {\r
-                       TreeDictionary<int,int> res = new TreeDictionary<int,int>(new IC());\r
-#if LINEARPROBING\r
-                       return res;\r
-#else\r
-                       for (int i = 0, s = table.Length; i < s; i++)\r
-                       {\r
-                               int count = 0;\r
-#if REFBUCKET\r
-                               Bucket b = table[i];\r
-\r
-                               while (b != null)\r
-                               {\r
-                                       count++;\r
-                                       b = b.overflow;\r
-                               }\r
-#else\r
-                               Bucket b = table[i];\r
-\r
-                               if (!isnull(b.item))\r
-                               {\r
-                                       count = 1;\r
-\r
-                                       OverflowBucket ob = b.overflow;\r
-\r
-                                       while (ob != null)\r
-                                       {\r
-                                               count++;\r
-                                               ob = ob.overflow;\r
-                                       }\r
-                               }\r
-#endif\r
-                               if (res.Contains(count))\r
-                                       res[count]++;\r
-                               else\r
-                                       res[count] = 1;\r
-                       }\r
-\r
-                       return res;\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/heaps/IntervalHeap.cs b/mcs/class/Mono.C5/heaps/IntervalHeap.cs
deleted file mode 100644 (file)
index 2ad5589..0000000
+++ /dev/null
@@ -1,570 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using System.Diagnostics;\r
-using MSG = System.Collections.Generic;\r
-\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A priority queue class based on an interval heap data structure.\r
-       /// </summary>\r
-       public class IntervalHeap<T>: CollectionValueBase<T>, IPriorityQueue<T>\r
-       {\r
-               #region Fields\r
-               struct Interval\r
-               {\r
-                       internal T first, last;\r
-\r
-\r
-                       public override string ToString() { return String.Format("[{0}; {1}]", first, last); }\r
-               }\r
-\r
-\r
-\r
-               object syncroot = new object();\r
-\r
-        int stamp;\r
-\r
-        IComparer<T> comparer;\r
-\r
-               Interval[] heap;\r
-\r
-               int size;\r
-               #endregion\r
-\r
-               #region Util\r
-               void heapifyMin(int i)\r
-               {\r
-                       int j = i, minpt = j;\r
-                       T pv = heap[j].first, min = pv;\r
-\r
-                       while (true)\r
-                       {\r
-                               int l = 2 * j + 1, r = l + 1;\r
-                               T lv, rv, other;\r
-\r
-                               if (2 * l < size && comparer.Compare(lv = heap[l].first, min) < 0) { minpt = l; min = lv; }\r
-\r
-                if (2 * r < size && comparer.Compare(rv = heap[r].first, min) < 0) { minpt = r; min = rv; }\r
-\r
-                if (minpt == j)\r
-                                       break;\r
-\r
-                               other = heap[minpt].last;\r
-                               heap[j].first = min;\r
-                if (2 * minpt + 1 < size && comparer.Compare(pv, other) > 0)\r
-                { heap[minpt].last = pv; pv = other; }\r
-\r
-                               min = pv;\r
-                               j = minpt;\r
-                       }\r
-\r
-                       if (minpt != i)\r
-                               heap[minpt].first = min;\r
-               }\r
-\r
-\r
-               void heapifyMax(int i)\r
-               {\r
-                       int j = i, maxpt = j;\r
-                       T pv = heap[j].last, max = pv;\r
-\r
-                       while (true)\r
-                       {\r
-                               int l = 2 * j + 1, r = l + 1;\r
-                               T lv, rv, other;\r
-\r
-                if (2 * l + 1 < size && comparer.Compare(lv = heap[l].last, max) > 0) { maxpt = l; max = lv; }\r
-\r
-                if (2 * r + 1 < size && comparer.Compare(rv = heap[r].last, max) > 0) { maxpt = r; max = rv; }\r
-\r
-                if (maxpt == j)\r
-                                       break;\r
-\r
-                               other = heap[maxpt].first;\r
-                               heap[j].last = max;\r
-                if (comparer.Compare(pv, other) < 0)\r
-                {\r
-                                       heap[maxpt].first = pv;\r
-                                       pv = other;\r
-                               }\r
-\r
-                               max = pv;\r
-                               j = maxpt;\r
-                       }\r
-\r
-                       if (maxpt != i)\r
-                               heap[maxpt].last = max;\r
-               }\r
-\r
-\r
-               void bubbleUpMin(int i)\r
-               {\r
-                       if (i > 0)\r
-                       {\r
-                               T min = heap[i].first, iv = min;\r
-                               int p = (i + 1) / 2 - 1;\r
-\r
-                               while (i > 0)\r
-                               {\r
-                    if (comparer.Compare(iv, min = heap[p = (i + 1) / 2 - 1].first) < 0)\r
-                    {\r
-                                               heap[i].first = min; min = iv;\r
-                                               i = p;\r
-                                       }\r
-                                       else\r
-                                               break;\r
-                               }\r
-\r
-                               heap[i].first = iv;\r
-                       }\r
-               }\r
-\r
-\r
-               void bubbleUpMax(int i)\r
-               {\r
-                       if (i > 0)\r
-                       {\r
-                               T max = heap[i].last, iv = max;\r
-                               int p = (i + 1) / 2 - 1;\r
-\r
-                               while (i > 0)\r
-                               {\r
-                    if (comparer.Compare(iv, max = heap[p = (i + 1) / 2 - 1].last) > 0)\r
-                    {\r
-                                               heap[i].last = max; max = iv;\r
-                                               i = p;\r
-                                       }\r
-                                       else\r
-                                               break;\r
-                               }\r
-\r
-                               heap[i].last = iv;\r
-                       }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-               /// <summary>\r
-               /// Create an interval heap with natural item comparer and default initial capacity (16)\r
-               /// </summary>\r
-               public IntervalHeap() : this(16) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an interval heap with external item comparer and default initial capacity (16)\r
-               /// </summary>\r
-               /// <param name="c">The external comparer</param>\r
-               public IntervalHeap(IComparer<T> c) : this(c,16) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an interval heap with natural item comparer and prescribed initial capacity\r
-               /// </summary>\r
-               /// <param name="capacity">The initial capacity</param>\r
-               public IntervalHeap(int capacity)  : this(ComparerBuilder.FromComparable<T>.Examine(),capacity) { }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an interval heap with external item comparer and prescribed initial capacity\r
-               /// </summary>\r
-               /// <param name="c">The external comparer</param>\r
-               /// <param name="capacity">The initial capacity</param>\r
-               public IntervalHeap(IComparer<T> c, int capacity)\r
-               {\r
-                       comparer = c;\r
-\r
-                       int length = 1;\r
-\r
-                       while (length < capacity) length <<= 1;\r
-\r
-                       heap = new Interval[length];\r
-               }\r
-               #endregion\r
-\r
-               #region IPriorityQueue<T> Members\r
-\r
-               /// <summary>\r
-               /// Find the current least item of this priority queue.\r
-               /// <exception cref="InvalidOperationException"/> if queue is empty\r
-               /// </summary>\r
-               /// <returns>The least item.</returns>\r
-               [Tested]\r
-               public T FindMin()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Heap is empty");\r
-\r
-                       return heap[0].first;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the least item from this  priority queue.\r
-               /// <exception cref="InvalidOperationException"/> if queue is empty\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMin()\r
-               {\r
-            stamp++;\r
-            if (size == 0)\r
-                throw new InvalidOperationException("Heap is empty");\r
-\r
-                       T retval = heap[0].first;;\r
-                       if (size == 1)\r
-                       {\r
-                               size = 0;\r
-                               heap[0].first = default(T);\r
-                       }\r
-                       else\r
-                       {\r
-                               int ind = (size - 1) / 2;\r
-\r
-                               if (size % 2 == 0)\r
-                               {\r
-                                       heap[0].first = heap[ind].last;\r
-                                       heap[ind].last = default(T);\r
-                               }\r
-                               else\r
-                               {\r
-                                       heap[0].first = heap[ind].first;\r
-                                       heap[ind].first = default(T);\r
-                               }\r
-\r
-                               size--;\r
-                               heapifyMin(0);\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the current largest item of this priority queue.\r
-               /// <exception cref="InvalidOperationException"/> if queue is empty\r
-               /// </summary>\r
-               /// <returns>The largest item.</returns>\r
-               [Tested]\r
-               public T FindMax()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Heap is empty");\r
-                       else if (size == 1)\r
-                               return heap[0].first;\r
-                       else\r
-                               return heap[0].last;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the largest item from this  priority queue.\r
-               /// <exception cref="InvalidOperationException"/> if queue is empty\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMax()\r
-               {\r
-            stamp++;\r
-            if (size == 0)\r
-                throw new InvalidOperationException("Heap is empty");\r
-\r
-                       T retval;\r
-\r
-                       if (size == 1)\r
-                       {\r
-                               size = 0;\r
-                               retval = heap[0].first;\r
-                               heap[0].first = default(T);\r
-                               return retval;\r
-                       }\r
-                       else\r
-                       {\r
-                               retval = heap[0].last;\r
-\r
-                               int ind = (size - 1) / 2;\r
-\r
-                               if (size % 2 == 0)\r
-                               {\r
-                                       heap[0].last = heap[ind].last;\r
-                                       heap[ind].last = default(T);\r
-                               }\r
-                               else\r
-                               {\r
-                                       heap[0].last = heap[ind].first;\r
-                                       heap[ind].first = default(T);\r
-                               }\r
-\r
-                               size--;\r
-                               heapifyMax(0);\r
-                               return retval;\r
-                       }\r
-               }\r
-\r
-\r
-        /// <summary>\r
-        /// The comparer object supplied at creation time for this collection\r
-        /// </summary>\r
-        /// <value>The comparer</value>\r
-        public IComparer<T> Comparer { get { return comparer; } }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True since this collection has bag semantics</value>\r
-               [Tested]\r
-               public bool AllowsDuplicates { [Tested]get { return true; } }\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>The distinguished object to use for locking to synchronize multithreaded access</value>\r
-               [Tested]\r
-               public object SyncRoot { [Tested]get { return syncroot; } }\r
-\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>True if this collection is empty.</value>\r
-               [Tested]\r
-               public bool IsEmpty { [Tested]get { return size == 0; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to this priority queue.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True</returns>\r
-               [Tested]\r
-               public bool Add(T item)\r
-               {\r
-            stamp++;\r
-            if (size == 0)\r
-                       {\r
-                               size = 1;\r
-                               heap[0].first = item;\r
-                               return true;\r
-                       }\r
-\r
-                       if (size == 2 * heap.Length)\r
-                       {\r
-                               Interval[] newheap = new Interval[2 * heap.Length];\r
-\r
-                               Array.Copy(heap, newheap, heap.Length);\r
-                               heap = newheap;\r
-                       }\r
-\r
-                       if (size % 2 == 0)\r
-                       {\r
-                               int i = size / 2, p = (i + 1) / 2 - 1;\r
-                               T tmp;\r
-\r
-                               size++;\r
-                if (comparer.Compare(item, tmp = heap[p].last) > 0)\r
-                {\r
-                                       heap[i].first = tmp;\r
-                                       heap[p].last = item;\r
-                                       bubbleUpMax(p);\r
-                               }\r
-                               else\r
-                               {\r
-                                       heap[i].first = item;\r
-                    if (comparer.Compare(item, heap[p].first) < 0)\r
-                        bubbleUpMin(i);\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               int i = size / 2;\r
-                               T other = heap[i].first;\r
-\r
-                               size++;\r
-                if (comparer.Compare(item, other) < 0)\r
-                {\r
-                                       heap[i].first = item;\r
-                                       heap[i].last = other;\r
-                                       bubbleUpMin(i);\r
-                               }\r
-                               else\r
-                               {\r
-                                       heap[i].last = item;\r
-                                       bubbleUpMax(i);\r
-                               }\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add the elements from another collection to this collection. \r
-               /// </summary>\r
-               /// <param name="items">The items to add.</param>\r
-               [Tested]\r
-               public void AddAll(MSG.IEnumerable<T> items)\r
-               {\r
-            //TODO: avoid incrementing stamp repeatedly\r
-                       foreach (T item in items)\r
-                               Add(item);\r
-               }\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. \r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
-        {\r
-            //TODO: avoid incrementing stamp repeatedly\r
-            foreach (T item in items)\r
-                Add(item);\r
-        }\r
-\r
-               #endregion\r
-\r
-        #region ICollection<T> members\r
-        /// <summary>\r
-        /// \r
-        /// </summary>\r
-        /// <value>The size of this collection</value>\r
-        [Tested]\r
-        public override int Count { [Tested]get { return size; } }\r
-\r
-\r
-        /// <summary>\r
-        /// The value is symbolic indicating the type of asymptotic complexity\r
-        /// in terms of the size of this collection (worst-case or amortized as\r
-        /// relevant).\r
-        /// </summary>\r
-        /// <value>A characterization of the speed of the \r
-        /// <code>Count</code> property in this collection.</value>\r
-        public override Speed CountSpeed { get { return Speed.Constant; } }\r
-\r
-        /// <summary>\r
-        /// Create an enumerator for the collection\r
-        /// <para>Note: the enumerator does *not* enumerate the items in sorted order, \r
-        /// but in the internal table order.</para>\r
-        /// </summary>\r
-        /// <returns>The enumerator(SIC)</returns>\r
-        [Tested]\r
-        public override MSG.IEnumerator<T> GetEnumerator()\r
-        {\r
-            int mystamp = stamp;\r
-            for (int i = 0; i < size; i++)\r
-            {\r
-                if (mystamp != stamp) throw new InvalidOperationException();\r
-                yield return i % 2 == 0 ? heap[i >> 1].first : heap[i >> 1].last;\r
-            }\r
-            yield break;\r
-        }\r
-\r
-\r
-        #endregion\r
-\r
-\r
-               #region Diagnostics\r
-               private bool check(int i, T min, T max)\r
-               {\r
-                       bool retval = true;\r
-                       Interval interval = heap[i];\r
-                       T first = interval.first, last = interval.last;\r
-\r
-                       if (2 * i + 1 == size)\r
-                       {\r
-                if (comparer.Compare(min, first) > 0)\r
-                {\r
-                                       Console.WriteLine("Cell {0}: parent.first({1}) > first({2})  [size={3}]", i, min, first, size);\r
-                                       retval = false;\r
-                               }\r
-\r
-                if (comparer.Compare(first, max) > 0)\r
-                {\r
-                                       Console.WriteLine("Cell {0}: first({1}) > parent.last({2})  [size={3}]", i, first, max, size);\r
-                                       retval = false;\r
-                               }\r
-\r
-                               return retval;\r
-                       }\r
-                       else\r
-                       {\r
-                if (comparer.Compare(min, first) > 0)\r
-                {\r
-                                       Console.WriteLine("Cell {0}: parent.first({1}) > first({2})  [size={3}]", i, min, first, size);\r
-                                       retval = false;\r
-                               }\r
-\r
-                if (comparer.Compare(first, last) > 0)\r
-                {\r
-                                       Console.WriteLine("Cell {0}: first({1}) > last({2})  [size={3}]", i, first, last, size);\r
-                                       retval = false;\r
-                               }\r
-\r
-                if (comparer.Compare(last, max) > 0)\r
-                {\r
-                                       Console.WriteLine("Cell {0}: last({1}) > parent.last({2})  [size={3}]", i, last, max, size);\r
-                                       retval = false;\r
-                               }\r
-\r
-                               int l = 2 * i + 1, r = l + 1;\r
-\r
-                               if (2 * l < size)\r
-                                       retval = retval && check(l, first, last);\r
-\r
-                               if (2 * r < size)\r
-                                       retval = retval && check(r, first, last);\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this collection.\r
-               /// Only avaliable in DEBUG builds???\r
-               /// </summary>\r
-               /// <returns>True if check does not fail.</returns>\r
-               [Tested]\r
-               public bool Check()\r
-               {\r
-                       if (size == 0)\r
-                               return true;\r
-\r
-                       if (size == 1)\r
-                               return (object)(heap[0].first) != null;\r
-\r
-                       return check(0, heap[0].first, heap[0].last);\r
-               }\r
-\r
-               #endregion\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/linkedlists/HashedLinkedLIst.cs b/mcs/class/Mono.C5/linkedlists/HashedLinkedLIst.cs
deleted file mode 100644 (file)
index dab3239..0000000
+++ /dev/null
@@ -1,1091 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-#define LISTORDERnot\r
-#define EXTLISTORDER\r
-using System;\r
-using System.Diagnostics;\r
-using MSG=System.Collections.Generic;\r
-\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A list collection based on a doubly linked list data structure with \r
-       /// a hash index mapping item to node.\r
-       /// </summary>\r
-       public class HashedLinkedList<T>: LinkedList<T>, IList<T>\r
-       {\r
-               #region Fields\r
-\r
-               HashDictionary<T,Node> dict;\r
-\r
-               //Invariant:  base.underlying == basehashedlist\r
-               HashedLinkedList<T> hashedunderlying;\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-\r
-               void init()\r
-               {\r
-#if LISTORDER || EXTLISTORDER\r
-                       maintaintags = true;\r
-#endif\r
-                       dict = new HashDictionary<T,Node>(itemhasher);\r
-               }\r
-               \r
-\r
-               /// <summary>\r
-               /// Create a hashed linked list with an external item hasher.\r
-               /// </summary>\r
-               /// <param name="itemhasher">The external hasher</param>\r
-               public HashedLinkedList(IHasher<T> itemhasher) : base(itemhasher) { init(); }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a hashed linked list with the natural item hasher.\r
-               /// </summary>\r
-               public HashedLinkedList() : base() { init(); }\r
-\r
-               #endregion\r
-\r
-               #region Util\r
-\r
-               bool contains(T item, out Node node)\r
-               {\r
-                       if (!dict.Find(item,out node))\r
-                               return false;\r
-                       else\r
-                               return insideview(node);\r
-               }\r
-\r
-               \r
-               void insert(Node succ, T item)\r
-               {\r
-                       Node newnode = new Node(item);\r
-\r
-                       if (dict.FindOrAdd(item, ref newnode))\r
-                               throw new ArgumentException("Item already in indexed list");\r
-\r
-                       insertNode(succ, newnode);\r
-               }\r
-\r
-\r
-               private bool dictremove(T item, out Node node)\r
-               {\r
-                       if (hashedunderlying == null)\r
-                       {\r
-                               if (!dict.Remove(item, out node))\r
-                                       return false;\r
-                       }\r
-                       else\r
-                       {\r
-                               //We cannot avoid calling dict twice - have to intersperse the listorder test!\r
-                               if (!contains(item, out node))\r
-                                       return false;\r
-\r
-                               dict.Remove(item);\r
-                       }\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               bool insideview(Node node)\r
-               {\r
-                       if (underlying == null)\r
-                               return true;\r
-\r
-#if LISTORDER\r
-                       if (maintaintags)\r
-                               return (startsentinel.tag < node.tag && (endsentinel.tag == 0 || node.tag < endsentinel.tag));\r
-                       else\r
-#elif EXTLISTORDER\r
-                       if (maintaintags)\r
-                               return (startsentinel.precedes(node) && node.precedes(endsentinel));\r
-                       else\r
-#endif\r
-                       if (2 * size < hashedunderlying.size)\r
-                       {\r
-                               Node cursor = startsentinel.next;\r
-\r
-                               while (cursor != endsentinel)\r
-                               {\r
-                                       if (cursor == node)\r
-                                               return true;\r
-\r
-                                       cursor = cursor.next;\r
-                               }\r
-\r
-                               return false;\r
-                       }\r
-                       else\r
-                       {\r
-                               Node cursor = hashedunderlying.startsentinel.next;\r
-\r
-                               while (cursor != startsentinel.next)\r
-                               {\r
-                                       if (cursor == node)\r
-                                               return false;\r
-\r
-                                       cursor = cursor.next;\r
-                               }\r
-\r
-                               cursor = endsentinel;\r
-                               while (cursor != hashedunderlying.endsentinel)\r
-                               {\r
-                                       if (cursor == node)\r
-                                               return false;\r
-\r
-                                       cursor = cursor.next;\r
-                               }\r
-\r
-                               return true;\r
-                       }\r
-               }\r
-\r
-\r
-               #endregion\r
-\r
-               #region IList<T> Members\r
-\r
-               /// <summary>\r
-               /// On this list, this indexer is read/write.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <value>The i'th item of this list.</value>\r
-               /// <param name="i">The index of the item to fetch or store.</param>\r
-               [Tested]\r
-               public override T this[int i]\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-                               modifycheck();\r
-                               return base[i];\r
-                       }\r
-                       [Tested]\r
-                       set\r
-                       {\r
-                               updatecheck();\r
-\r
-                               Node n = get(i);\r
-\r
-                               if (itemhasher.Equals(value, n.item))\r
-                               {\r
-                                       n.item = value;\r
-                                       dict.Update(value, n);\r
-                               }\r
-                               else if (!dict.FindOrAdd(value, ref n))\r
-                               {\r
-                                       dict.Remove(n.item);\r
-                                       n.item = value;\r
-                               }\r
-                               else\r
-                                       throw new ArgumentException("Item already in indexed list");\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at a specific index location in this list. \r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt; the size of the collection.</summary>\r
-               /// <exception cref="InvalidOperationException"/> if  the item is \r
-               /// already in the list.\r
-               /// <param name="i">The index at which to insert.</param>\r
-               /// <param name="item">The item to insert.</param>\r
-               [Tested]\r
-               public override void Insert(int i, T item)\r
-               {\r
-                       updatecheck();\r
-                       insert(i == size ? endsentinel : get(i), item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert into this list all items from an enumerable collection starting \r
-               /// at a particular index.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt; the size of the collection.\r
-               /// <exception cref="InvalidOperationException"/> if one of the items to insert is\r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="i">Index to start inserting at</param>\r
-               /// <param name="items">Items to insert</param>\r
-               [Tested]\r
-               public override void InsertAll(int i, MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       Node succ, node;\r
-                       int count = 0;\r
-\r
-                       succ = i == size ? endsentinel : get(i);\r
-                       node = succ.prev;\r
-#if LISTORDER\r
-                       //TODO: guard?\r
-                       int taglimit = i == size ? int.MaxValue : succ.tag - 1, thetag = node.tag;\r
-#elif EXTLISTORDER\r
-                       TagGroup taggroup = null;\r
-                       int taglimit = 0, thetag = 0;\r
-\r
-                       if (maintaintags)\r
-                               taggroup = gettaggroup(node, succ, out thetag, out taglimit);\r
-#endif\r
-                       foreach (T item in items)\r
-                       {\r
-                               Node tmp = new Node(item, node, null);\r
-\r
-                               if (!dict.FindOrAdd(item, ref tmp))\r
-                               {\r
-#if LISTORDER\r
-                                       if (maintaintags)\r
-                                               tmp.tag = thetag < taglimit ? ++thetag : thetag;\r
-#elif EXTLISTORDER\r
-                                       if (maintaintags)\r
-                                       {\r
-                                               tmp.tag = thetag < taglimit ? ++thetag : thetag;\r
-                                               tmp.taggroup = taggroup;\r
-                                       }\r
-#endif\r
-                                       node.next = tmp;\r
-                                       count++;\r
-                                       node = tmp;\r
-                               }\r
-                               else\r
-                                       throw new ArgumentException("Item already in indexed list");\r
-                       }\r
-\r
-#if EXTLISTORDER\r
-                       if (maintaintags)\r
-                       {\r
-                               taggroup.count += count;\r
-                               taggroup.first = succ.prev;\r
-                               taggroup.last = node;\r
-                       }\r
-#endif \r
-                       succ.prev = node;\r
-                       node.next = succ;\r
-                       size += count;\r
-                       if (hashedunderlying != null)\r
-                               hashedunderlying.size += count;\r
-#if LISTORDER\r
-                       if (maintaintags && node.tag == node.prev.tag)\r
-                               settag(node);\r
-#elif EXTLISTORDER\r
-                       if (maintaintags)\r
-                       {\r
-                               if (node.tag == node.prev.tag)\r
-                                       splittaggroup(taggroup);\r
-                       }\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item right before the first occurrence of some target item.\r
-               /// <exception cref="ArgumentException"/> if target     is not found\r
-               /// <exception cref="InvalidOperationException"/> if the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target before which to insert.</param>\r
-               [Tested]\r
-               public override void InsertBefore(T item, T target)\r
-               {\r
-                       updatecheck();\r
-\r
-                       Node node;\r
-\r
-                       if (!contains(target, out node))\r
-                               throw new ArgumentException("Target item not found");\r
-\r
-                       insert(node, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item right after the last(???) occurrence of some target item.\r
-               /// <exception cref="ArgumentException"/> if target     is not found\r
-               /// <exception cref="InvalidOperationException"/> if the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               /// <param name="target">The target after which to insert.</param>\r
-               [Tested]\r
-               public override void InsertAfter(T item, T target)\r
-               {\r
-                       updatecheck();\r
-\r
-                       Node node;\r
-\r
-                       if (!contains(target, out node))\r
-                               throw new ArgumentException("Target item not found");\r
-\r
-                       insert(node.next, item);\r
-               }\r
-\r
-\r
-\r
-               /// <summary>\r
-               /// Insert an item at the front of this list.\r
-               /// <exception cref="InvalidOperationException"/> if the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               [Tested]\r
-               public override void InsertFirst(T item)\r
-               {\r
-                       updatecheck();\r
-                       insert(startsentinel.next, item);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Insert an item at the back of this list.\r
-               /// <exception cref="InvalidOperationException"/> if  the item is \r
-               /// already in the list.\r
-               /// </summary>\r
-               /// <param name="item">The item to insert.</param>\r
-               [Tested]\r
-               public override void InsertLast(T item)\r
-               {\r
-                       updatecheck();\r
-                       insert(endsentinel, item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one item from the list: from the front if <code>FIFO</code>\r
-               /// is true, else from the back.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public override T Remove()\r
-               {\r
-                       T retval = base.Remove();\r
-\r
-                       dict.Remove(retval);\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one item from the front of the list.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public override T RemoveFirst()\r
-               {\r
-                       T retval = base.RemoveFirst();\r
-\r
-                       dict.Remove(retval);\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove one item from the back of the list.\r
-               /// <exception cref="InvalidOperationException"/> if this list is empty.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public override T RemoveLast()\r
-               {\r
-                       T retval = base.RemoveLast();\r
-\r
-                       dict.Remove(retval);\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a list view on this list. \r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the view would not fit into\r
-               /// this list.\r
-               /// </summary>\r
-               /// <param name="start">The index in this list of the start of the view.</param>\r
-               /// <param name="count">The size of the view.</param>\r
-               /// <returns>The new list view.</returns>\r
-               [Tested]\r
-               public override IList<T> View(int start, int count)\r
-               {\r
-                       checkRange(start, count);\r
-                       modifycheck();\r
-\r
-                       HashedLinkedList<T> retval = (HashedLinkedList<T>)MemberwiseClone();\r
-\r
-                       retval.underlying = retval.hashedunderlying = hashedunderlying != null ? hashedunderlying : this;\r
-                       retval.offset = start + offset;\r
-                       retval.startsentinel = start == 0 ? startsentinel : get(start - 1);\r
-                       retval.endsentinel = start + count == size ? endsentinel : get(start + count);\r
-                       retval.size = count;\r
-                       return retval;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Reverst part of the list so the items are in the opposite sequence order.\r
-               /// <exception cref="ArgumentException"/> if the count is negative.\r
-               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit\r
-               /// into the list.\r
-               /// </summary>\r
-               /// <param name="start">The index of the start of the part to reverse.</param>\r
-               /// <param name="count">The size of the part to reverse.</param>\r
-               [Tested]\r
-               public override void Reverse(int start, int count)\r
-               {\r
-                       //Duplicating linkedlist<T> code to minimize cache misses\r
-                       updatecheck();\r
-                       checkRange(start, count);\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       Node a = get(start), b = get(start + count - 1);\r
-\r
-                       for (int i = 0; i < count / 2; i++)\r
-                       {\r
-                               T swap = a.item;a.item = b.item;b.item = swap;\r
-                               dict[a.item] = a;dict[b.item] = b;\r
-                               a = a.next;b = b.prev;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Shuffle the items of this list according to a specific random source.\r
-               /// </summary>\r
-               /// <param name="rnd">The random source.</param>\r
-               public override void Shuffle(Random rnd)\r
-               {\r
-                       updatecheck();\r
-\r
-                       ArrayList<T> a = new ArrayList<T>();\r
-\r
-                       a.AddAll(this);\r
-                       a.Shuffle(rnd);\r
-\r
-                       Node cursor = startsentinel.next;\r
-                       int j = 0;\r
-\r
-                       while (cursor != endsentinel)\r
-                       {\r
-                               dict[cursor.item = a[j++]] = cursor;\r
-                               cursor = cursor.next;\r
-                       }\r
-               }\r
-\r
-               #endregion              \r
-\r
-               #region IIndexed<T> Members\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going forwrds from the start.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of item from start.</returns>\r
-               [Tested]\r
-               public override int IndexOf(T item)\r
-               {\r
-                       Node node;\r
-\r
-                       modifycheck();\r
-                       if (!dict.Find(item, out node))\r
-                               return -1;\r
-#if LISTORDER\r
-                       if (maintaintags && !insideview(node))\r
-                               return -1;\r
-#elif EXTLISTORDER\r
-                       if (maintaintags && !insideview(node))\r
-                               return -1;\r
-#endif\r
-                       return base.IndexOf(item);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going backwords from the end.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of of item from the end.</returns>\r
-               [Tested]\r
-               public override int LastIndexOf(T item) { return IndexOf(item); }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the item at a specific position of the list.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <param name="i">The index of the item to remove.</param>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public override T RemoveAt(int i)\r
-               {\r
-                       T retval = base.RemoveAt(i);\r
-\r
-                       dict.Remove(retval);\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in an index interval.\r
-               /// <exception cref="IndexOutOfRangeException"/>???. \r
-               /// </summary>\r
-               /// <param name="start">The index of the first item to remove.</param>\r
-               /// <param name="count">The number of items to remove.</param>\r
-               [Tested]\r
-               public override void RemoveInterval(int start, int count)\r
-               {\r
-                       updatecheck();\r
-                       checkRange(start, count);\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       Node a, b;\r
-\r
-                       if (start <= size - start - count)\r
-                       {\r
-                               b = a = get(start);\r
-#if EXTLISTORDER\r
-                               Node c = a.prev;\r
-#endif\r
-                               for (int i = 0; i < count; i++)\r
-                               {\r
-                                       dict.Remove(b.item); \r
-#if EXTLISTORDER\r
-                                       if (maintaintags)\r
-                                       {\r
-                                               c.next = b;\r
-                                               b.prev = c;\r
-                                               removefromtaggroup(b);\r
-                                       }\r
-#endif\r
-                                       b = b.next;\r
-                               }\r
-\r
-                               a.prev.next = b;\r
-                               b.prev = a.prev;\r
-                       }\r
-                       else\r
-                       {\r
-                               a = b = get(start + count - 1);\r
-#if EXTLISTORDER\r
-                               Node c = b.next;\r
-#endif\r
-                               for (int i = 0; i < count; i++)\r
-                               {\r
-                                       dict.Remove(a.item); \r
-#if EXTLISTORDER\r
-                                       if (maintaintags)\r
-                                       {\r
-                                               c.prev = a;\r
-                                               a.next = c;\r
-                                               removefromtaggroup(a);\r
-                                       }\r
-#endif\r
-                                       a = a.prev;\r
-                               }\r
-\r
-                               a.next = b.next;\r
-                               b.next.prev = a;\r
-                       }\r
-\r
-                       size -= count;\r
-                       if (hashedunderlying != null)\r
-                               hashedunderlying.size -= count;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISequenced<T> Members\r
-\r
-               int ISequenced<T>.GetHashCode()\r
-               { modifycheck(); return sequencedhashcode(); }\r
-\r
-\r
-               bool ISequenced<T>.Equals(ISequenced<T> that)\r
-               { modifycheck(); return sequencedequals(that); }\r
-\r
-               #endregion\r
-\r
-               #region IEditableCollection<T> Members\r
-\r
-\r
-               /// <summary>\r
-               /// The value is symbolic indicating the type of asymptotic complexity\r
-               /// in terms of the size of this collection (worst-case or amortized as\r
-               /// relevant).\r
-               /// </summary>\r
-               /// <value>Speed.Constant</value>\r
-               [Tested]\r
-               public override Speed ContainsSpeed\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-#if LISTORDER || EXTLISTORDER\r
-                               return hashedunderlying == null || maintaintags ? Speed.Constant : Speed.Linear;\r
-#else\r
-                               return basehashedlist == null ? Speed.Constant : Speed.Linear;\r
-#endif\r
-                       }\r
-               }\r
-\r
-\r
-               int ICollection<T>.GetHashCode()\r
-               { modifycheck(); return unsequencedhashcode(); }\r
-\r
-\r
-               bool ICollection<T>.Equals(ICollection<T> that)\r
-               { modifycheck(); return unsequencedequals(that); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains (an item equivalent to according to the\r
-               /// itemhasher) a particular value.\r
-               /// </summary>\r
-               /// <param name="item">The value to check for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public override bool Contains(T item)\r
-               {\r
-                       Node node;\r
-\r
-                       modifycheck();\r
-                       return contains(item, out node);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public override bool Find(ref T item)\r
-               {\r
-                       Node node;\r
-\r
-                       modifycheck();\r
-                       if (contains(item, out node)) { item = node.item; return true; }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value. \r
-               /// </summary>\r
-               /// <param name="item">Value to update.</param>\r
-               /// <returns>True if the item was found and hence updated.</returns>\r
-               [Tested]\r
-               public override bool Update(T item)\r
-               {\r
-                       Node node;\r
-\r
-                       updatecheck();\r
-                       if (contains(item, out node)) { node.item = item; return true; }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found. Else, add the item to the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the item was found (hence not added).</returns>\r
-               [Tested]\r
-               public override bool FindOrAdd(ref T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       //This is an extended myinsert:\r
-                       Node node = new Node(item);\r
-\r
-                       if (!dict.FindOrAdd(item, ref node))\r
-                       {\r
-                               insertNode(endsentinel, node);\r
-                               return false;\r
-                       }\r
-\r
-                       if (!insideview(node))\r
-                               throw new ArgumentException("Item alredy in indexed list but outside view");\r
-\r
-                       item = node.item;\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value; else add the value to the collection. \r
-               /// </summary>\r
-               /// <param name="item">Value to add or update.</param>\r
-               /// <returns>True if the item was found and updated (hence not added).</returns>\r
-               [Tested]\r
-               public override bool UpdateOrAdd(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       Node node = new Node(item);\r
-\r
-                       /*if (basehashedlist == null)\r
-                       {\r
-                               if (!dict.UpdateOrAdd(item, node))\r
-                                       return false;\r
-                       }\r
-                       else\r
-                       {*/\r
-                               //NOTE: it is hard to do this without double access to the dictionary\r
-                               //in the update case\r
-                               if (dict.FindOrAdd(item, ref node))\r
-                               {\r
-                                       if (!insideview(node))\r
-                                               throw new ArgumentException("Item in indexed list but outside view");\r
-\r
-                                       //dict.Update(item, node);\r
-                                       node.item = item;\r
-                                       return true;\r
-                               }\r
-                       //}\r
-\r
-                       insertNode(endsentinel, node);\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection. \r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public override bool Remove(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       Node node;\r
-\r
-                       if (!dictremove(item, out node))\r
-                               return false;\r
-\r
-                       remove(node);\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection if found. \r
-               /// If an item was removed, report a binary copy of the actual item removed in \r
-               /// the argument.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove on input.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public override bool RemoveWithReturn(ref T item)\r
-               {\r
-                       Node node;\r
-\r
-                       updatecheck();\r
-                       if (!dictremove(item, out node))\r
-                               return false;\r
-\r
-                       item = node.item;\r
-                       remove(node);\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in another collection from this one. \r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public override void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       Node node;\r
-\r
-                       updatecheck();\r
-                       foreach (T item in items)\r
-                               if (dictremove(item, out node))\r
-                                       remove(node);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from this collection.\r
-               /// </summary>\r
-               [Tested]\r
-               public override void Clear()\r
-               {\r
-                       updatecheck();\r
-                       if (hashedunderlying == null)\r
-                               dict.Clear();\r
-                       else\r
-                               foreach (T item in this)\r
-                                       dict.Remove(item);\r
-\r
-                       base.Clear();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items not in some other collection from this one. \r
-               /// </summary>\r
-               /// <param name="items">The items to retain.</param>\r
-               [Tested]\r
-               public override void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-                       if (hashedunderlying == null)\r
-                       {\r
-                               HashDictionary<T,Node> newdict = new HashDictionary<T,Node>(itemhasher);\r
-\r
-                               foreach (T item in items)\r
-                               {\r
-                                       Node node;\r
-\r
-                                       if (dict.Remove(item, out node))\r
-                                               newdict.Add(item, node);\r
-                               }\r
-\r
-                               foreach (KeyValuePair<T,Node> pair in dict)\r
-                               {\r
-                                       Node n = pair.value, p = n.prev, s = n.next; s.prev = p; p.next = s;\r
-#if EXTLISTORDER\r
-                                       if (maintaintags)\r
-                                               removefromtaggroup(n);\r
-#endif\r
-                               }\r
-\r
-                               dict = newdict;\r
-                               size = dict.Count;\r
-                               //For a small number of items to retain it might be faster to \r
-                               //iterate through the list and splice out the chunks not needed\r
-                       }\r
-                       else\r
-                       {\r
-                               HashSet<T> newdict = new HashSet<T>(itemhasher);\r
-\r
-                               foreach (T item in this)\r
-                                       newdict.Add(item);\r
-\r
-                               foreach (T item in items)\r
-                                       newdict.Remove(item);\r
-\r
-                               Node n = startsentinel.next;\r
-\r
-                               while (n != endsentinel)\r
-                               {\r
-                                       if (newdict.Contains(n.item))\r
-                                       {\r
-                                               dict.Remove(n.item);\r
-                                               remove(n);\r
-                                       }\r
-\r
-                                       n = n.next;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains all the values in another collection\r
-               /// Multiplicities\r
-               /// are not taken into account.\r
-               /// </summary>\r
-               /// <param name="items">The </param>\r
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
-               [Tested]\r
-               public override bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       Node node;\r
-\r
-                       modifycheck();\r
-                       foreach (T item in items)\r
-                               if (!contains(item, out node))\r
-                                       return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Count the number of items of the collection equal to a particular value.\r
-               /// Returns 0 if and only if the value is not in the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to count.</param>\r
-               /// <returns>The number of copies found.</returns>\r
-               [Tested]\r
-               public override int ContainsCount(T item) { return Contains(item) ? 1 : 0; }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items equivalent to a given value.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               [Tested]\r
-               public override void RemoveAllCopies(T item) { Remove(item); }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <value>False since this collection has set semantics.</value>\r
-               [Tested]\r
-        public override bool AllowsDuplicates { [Tested]get { return false; } }\r
-\r
-\r
-        //This is *not* the same as AddLast!!\r
-               /// <summary>\r
-               /// Add an item to this collection if possible. Since this collection has set\r
-               /// semantics, the item will be added if not already in the collection. \r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True if item was added.</returns>\r
-               [Tested]\r
-               public override bool Add(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       Node node = new Node(item);\r
-\r
-                       if (!dict.FindOrAdd(item, ref node))\r
-                       {\r
-                               insertNode(endsentinel, node);\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               //Note: this is *not* equivalent to InsertRange int this Set situation!!!\r
-               /// <summary>\r
-               /// Add the elements from another collection to this collection.\r
-               /// Only items not already in the collection\r
-               /// will be added.\r
-               /// </summary>\r
-               /// <param name="items">The items to add.</param>\r
-               [Tested]\r
-               public override void AddAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-                       foreach (T item in items)\r
-                       {\r
-                               Node node = new Node(item);\r
-\r
-                               if (!dict.FindOrAdd(item, ref node))\r
-                                       insertNode(endsentinel, node);\r
-                       }\r
-               }\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. \r
-        /// Only items not already in the collection\r
-        /// will be added.\r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        public override void AddAll<U>(MSG.IEnumerable<U> items) //where U:T\r
-        {\r
-            updatecheck();\r
-            foreach (T item in items)\r
-            {\r
-                Node node = new Node(item);\r
-\r
-                if (!dict.FindOrAdd(item, ref node))\r
-                    insertNode(endsentinel, node);\r
-            }\r
-        }\r
-\r
-        #endregion\r
-\r
-               #region IDirectedEnumerable<T> Members\r
-\r
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
-\r
-\r
-               #endregion\r
-\r
-               #region Diagnostics\r
-               /// <summary>\r
-               /// Check the integrity of the internal data structures of this collection.\r
-               /// Only avaliable in DEBUG builds???\r
-               /// </summary>\r
-               /// <returns>True if check does not fail.</returns>\r
-               [Tested]\r
-               public override bool Check()\r
-               {\r
-                       if (!base.Check())\r
-                               return false;\r
-\r
-                       bool retval = true;\r
-\r
-                       if (hashedunderlying == null)\r
-                       {\r
-                               if (size != dict.Count)\r
-                               {\r
-                                       Console.WriteLine("list.size ({0}) != dict.Count ({1})", size, dict.Count);\r
-                                       retval = false;\r
-                               }\r
-\r
-                               Node n = startsentinel.next, n2;\r
-\r
-                               while (n != endsentinel)\r
-                               {\r
-                                       if (!dict.Find(n.item, out n2))\r
-                                       {\r
-                                               Console.WriteLine("Item in list but not dict: {0}", n.item);\r
-                                               retval = false;\r
-                                       }\r
-                                       else if (n != n2)\r
-                                       {\r
-                                               Console.WriteLine("Wrong node in dict for item: {0}", n.item);\r
-                                               retval = false;\r
-                                       }\r
-\r
-                                       n = n.next;\r
-                               }\r
-                       }\r
-\r
-                       return retval;\r
-               }\r
-               #endregion\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/linkedlists/LinkedList.cs b/mcs/class/Mono.C5/linkedlists/LinkedList.cs
deleted file mode 100644 (file)
index ebb9ae1..0000000
+++ /dev/null
@@ -1,2670 +0,0 @@
-#if NET_2_0
-/*
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-*/
-
-#define LISTORDERnot
-#define EXTLISTORDER
-using System;
-using System.Diagnostics;
-using MSG=System.Collections.Generic;
-
-namespace C5
-{
-       /// <summary>
-       /// A list collection class based on a doubly linked list data structure.
-       /// </summary>
-       public class LinkedList<T>: SequencedBase<T>, IList<T>
-       {
-               #region Fields
-               /// <summary>
-               /// IExtensible.Add(T) always does AddLast(T), fIFO determines 
-               /// if T Remove() does RemoveFirst() or RemoveLast()
-               /// </summary>
-               bool fIFO = true;
-
-#if LISTORDER || EXTLISTORDER
-               /// <summary>
-               /// True if we maintain tags for node ordering (false for plain linked list, true for hashed linked list).
-               /// </summary>
-               protected bool maintaintags = false;
-#endif
-
-#if EXTLISTORDER
-               int taggroups;
-#endif
-
-               //Invariant:  startsentinel != null && endsentinel != null
-               //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel
-               //Else:      startsentinel.next == First && endsentinel.prev == Last)
-               /// <summary>
-               /// Node to the left of first node 
-               /// </summary>
-               protected Node startsentinel;
-               /// <summary>
-               /// Node to the right of last node
-               /// </summary>
-               protected Node endsentinel;
-               /// <summary>
-               /// Offset of this view in underlying list
-               /// </summary>
-               protected int offset;
-
-               /// <summary>
-               /// underlying list of theis view (or null)
-               /// </summary>
-               protected LinkedList<T> underlying;
-
-               #endregion
-
-               #region Util
-
-               bool equals(T i1, T i2) { return itemhasher.Equals(i1, i2); }
-
-
-               /// <summary>
-               /// Check if it is valid to perform updates and increment stamp.
-               /// <exception cref="InvalidOperationException"/> if check fails.
-               /// <br/>This method should be called at the start of any public modifying methods.
-               /// </summary>
-               protected override void updatecheck()
-               {
-                       modifycheck();
-                       base.updatecheck();
-                       if (underlying != null)
-                               underlying.stamp++;
-               }
-
-
-               /// <summary>
-               /// Check if we are a view that the underlyinglist has only been updated through us.
-               /// <exception cref="InvalidOperationException"/> if check fails.
-               /// <br/>
-               /// This method should be called from enumerators etc to guard against 
-               /// modification of the base collection.
-               /// </summary>
-               protected void modifycheck()
-               {
-                       if (underlying != null && stamp != underlying.stamp)
-                               throw new InvalidOperationException("underlying list was modified");
-               }
-
-
-               /// <summary>
-               /// Check that the list has not been updated since a particular time.
-               /// <exception cref="InvalidOperationException"/> if check fails.
-               /// </summary>
-               /// <param name="stamp">The stamp indicating the time.</param>
-               protected override void modifycheck(int stamp)
-               {
-                       modifycheck();
-                       if (this.stamp != stamp)
-                               throw new InvalidOperationException("Collection was modified");
-               }
-
-
-               Node insert(Node succ, T item)
-               {
-                       Node newnode = new Node(item, succ.prev, succ);
-
-                       succ.prev.next = newnode;
-                       succ.prev = newnode;
-                       size++;
-                       if (underlying != null)
-                               underlying.size++;
-
-#if LISTORDER
-                       //TODO: replace with Debug.Assert(!maintaintags)
-                       if (maintaintags)
-                               settag(newnode);
-#elif EXTLISTORDER
-                       if (maintaintags)
-                               settag(newnode);
-#endif
-
-                       return newnode;
-               }
-
-
-               /// <summary>
-               /// Insert a Node before another one. Unchecked internal version.
-               /// </summary>
-               /// <param name="succ">The successor to be</param>
-               /// <param name="newnode">Node to insert</param>
-               protected void insertNode(Node succ, Node newnode)
-               {
-                       newnode.next = succ;
-                       newnode.prev = succ.prev;
-                       succ.prev.next = newnode;
-                       succ.prev = newnode;
-                       size++;
-                       if (underlying != null)
-                               underlying.size++;
-
-#if LISTORDER
-                       if (maintaintags)
-                               settag(newnode);
-#elif EXTLISTORDER
-                       if (maintaintags)
-                               settag(newnode);
-#endif
-               }
-
-
-               /// <summary>
-               /// Remove a node. Unchecked internal version.
-               /// </summary>
-               /// <param name="node">Node to remove</param>
-               /// <returns>The item of the removed node</returns>
-               protected T remove(Node node)
-               {
-                       node.prev.next = node.next;
-                       node.next.prev = node.prev;
-                       size--;
-                       if (underlying != null)
-                               underlying.size--;
-#if EXTLISTORDER
-                       if (maintaintags)
-                               removefromtaggroup(node);
-#endif
-                       return node.item;
-               }
-
-
-
-#if LISTORDER
-               //const int MaxTag = int.MaxValue;
-
-               protected void settag(Node node)
-               {
-                       //Note: the (global) sentinels have tag==0 and all other tags are positive.
-                       Node pred = node.prev, succ = node.next;
-                       if (pred.tag < succ.tag - 1)
-                       {
-                               //Note:
-                               //node.tag-pred.tag = (succ.tag-pred.tag) / 2 > 0
-                //succ.tag-node.tag = succ.tag-pred.tag - (succ.tag-pred.tag) / 2 > 0
-                               node.tag = pred.tag + (succ.tag-pred.tag) / 2;
-                               return;
-                       }
-
-                       if (succ.tag == 0 && pred.tag < int.MaxValue)
-                       {
-                               //Note:
-                               //node.tag-pred.tag = 1 + (int.MaxValue-pred.tag) / 2 > 0
-                               //node.tag <=int.MaxValue
-                               node.tag = pred.tag + 1 + (int.MaxValue - pred.tag) / 2;
-                               return;
-                       }
-
-                       node.tag = node.prev.tag;
-                       redistributetags(node);
-               }
-               
-               private void redistributetags(Node node)
-               {
-                       Node pred = node, succ = node;
-
-                       //Node start = underlying == null ? startsentinel : underlying.startsentinel;
-                       //Node end = underlying == null ? endsentinel : underlying.endsentinel;
-                       double limit = 1, bigt = Math.Pow(size, 1.0/29);//?????
-                       int bits = 1, count = 1, lowmask = 0, himask = 0, target = 0;
-
-                       do
-                       {
-                               bits++;
-                               lowmask = (1 << bits) - 1;
-                               himask = ~lowmask;
-                               target = node.tag & himask;
-                               while (pred.prev.tag > 0 && (pred.prev.tag & himask) == target)
-                               { count++; pred = pred.prev; }
-
-                               while (succ.next.tag > 0 && (succ.next.tag & himask) == target)
-                               { count++; succ = succ.next; }
-
-                               limit *= bigt;
-                       } while (count > limit);
-
-                       //redistibute tags
-                       //Console.WriteLine("Redistributing {0} tags at {1} bits around item {2}", count, bits, node.item);
-
-                       int delta = lowmask / (count+1);
-
-                       for (int i = 1; i <= count; i++)
-                       {
-                               pred.tag = target + i * delta;
-                               //Console.Write("({0} -> {1})", pred.item, pred.tag);
-                               pred = pred.next;
-                       }
-                       //Console.WriteLine("{0}:{1}:{2}/",count,size,Check());
-               }
-#elif EXTLISTORDER
-               const int wordsize = 32;
-
-               const int lobits = 3;
-
-               const int hibits = lobits + 1;
-
-               const int losize = 1 << lobits;
-
-               const int hisize = 1 << hibits;
-
-               const int logwordsize = 5;
-
-
-               /// <summary>
-               /// 
-               /// </summary>
-               /// <param name="pred"></param>
-               /// <param name="succ"></param>
-               /// <param name="lowbound"></param>
-               /// <param name="highbound"></param>
-               /// <returns></returns>
-               protected TagGroup gettaggroup(Node pred, Node succ, out int lowbound, out int highbound)
-               {
-                       TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
-
-                       if (predgroup == succgroup)
-                       {
-                               lowbound = pred.tag + 1;
-                               highbound = succ.tag - 1;
-                               return predgroup;
-                       }
-                       else if (predgroup.first != null)
-                       {
-                               lowbound = pred.tag + 1;
-                               highbound = int.MaxValue;
-                               return predgroup;
-                       }
-                       else if (succgroup.first != null)
-                       {
-                               lowbound = int.MinValue;
-                               highbound = succ.tag - 1;
-                               return succgroup;
-                       }
-                       else
-                       {
-                               lowbound = int.MinValue;
-                               highbound = int.MaxValue;
-                               return new TagGroup();
-                       }
-               }
-
-
-               /// <summary>
-               /// Put a tag on a node (already inserted in the list). Split taggroups and renumber as 
-               /// necessary.
-               /// </summary>
-               /// <param name="node">The node to tag</param>
-               protected void settag(Node node)
-               {
-                       Node pred = node.prev, succ = node.next;
-                       TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
-
-                       if (predgroup == succgroup)
-                       {
-                               node.taggroup = predgroup;
-                               predgroup.count++;
-                               if (pred.tag + 1 == succ.tag)
-                                       splittaggroup(predgroup);
-                               else
-                                       node.tag = (pred.tag + 1) / 2 + (succ.tag - 1) / 2;
-                       }
-                       else if (predgroup.first != null)
-                       {
-                               node.taggroup = predgroup;
-                               predgroup.last = node;
-                               predgroup.count++;
-                               if (pred.tag == int.MaxValue)
-                                       splittaggroup(predgroup);
-                               else
-                                       node.tag = pred.tag / 2 + int.MaxValue / 2 + 1;
-                       }
-                       else if (succgroup.first != null)
-                       {
-                               node.taggroup = succgroup;
-                               succgroup.first = node;
-                               succgroup.count++;
-                               if (succ.tag == int.MinValue)
-                                       splittaggroup(node.taggroup);
-                               else
-                                       node.tag = int.MinValue / 2 + (succ.tag - 1) / 2;
-                       }
-                       else
-                       {
-                               Debug.Assert(taggroups == 0);
-
-                               TagGroup newgroup = new TagGroup();
-
-                               taggroups = 1;
-                               node.taggroup = newgroup;
-                               newgroup.first = newgroup.last = node;
-                               newgroup.count = 1;
-                               return;
-                       }
-               }
-
-
-               /// <summary>
-               /// Remove a node from its taggroup.
-               /// <br/> When this is called, node must already have been removed from the underlying list
-               /// </summary>
-               /// <param name="node">The node to remove</param>
-               protected void removefromtaggroup(Node node)
-               {
-                       //
-                       TagGroup taggroup = node.taggroup;
-
-                       if (--taggroup.count == 0)
-                       {
-                               taggroups--;
-                               return;
-                       }
-
-                       if (node == taggroup.first)
-                               taggroup.first = node.next;
-
-                       if (node == taggroup.last)
-                               taggroup.last = node.prev;
-
-                       //node.taggroup = null;
-                       if (taggroup.count != losize)
-                               return;
-
-                       TagGroup otg;
-
-                       if ((otg = taggroup.first.prev.taggroup).count <= losize)
-                               taggroup.first = otg.first;
-                       else if ((otg = taggroup.last.next.taggroup).count <= losize)
-                               taggroup.last = otg.last;
-                       else
-                               return;
-
-                       Node n = otg.first;
-
-                       for (int i = 0, length = otg.count; i < length; i++)
-                       {
-                               n.taggroup = taggroup;
-                               n = n.next;
-                       }
-
-                       taggroup.count += otg.count;
-                       taggroups--;
-                       n = taggroup.first;
-
-                       const int ofs = wordsize - hibits;
-
-                       for (int i = 0, count = taggroup.count; i < count; i++)
-                       {
-                               n.tag = (i - losize) << ofs; //(i-8)<<28 
-                               n = n.next;
-                       }
-               }
-
-
-               /// <summary>
-               /// Split a tag group to make rom for more tags.
-               /// </summary>
-               /// <param name="taggroup">The tag group</param>
-               protected void splittaggroup(TagGroup taggroup)
-               {
-                       Node n = taggroup.first;
-                       int ptgt = taggroup.first.prev.taggroup.tag;
-                       int ntgt = taggroup.last.next.taggroup.tag;
-
-                       Debug.Assert(ptgt + 1 <= ntgt - 1);
-
-                       int ofs = wordsize - hibits;
-                       int newtgs = taggroup.count / hisize - 1;
-                       int tgtdelta = (int)((ntgt + 0.0 - ptgt) / (newtgs + 2)), tgtag = ptgt;
-
-                       tgtdelta = tgtdelta == 0 ? 1 : tgtdelta;
-                       for (int j = 0; j < newtgs; j++)
-                       {
-                               TagGroup newtaggroup = new TagGroup();
-
-                               newtaggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta);
-                               newtaggroup.first = n;
-                               newtaggroup.count = hisize;
-                               for (int i = 0; i < hisize; i++)
-                               {
-                                       n.taggroup = newtaggroup;
-                                       n.tag = (i - losize) << ofs; //(i-8)<<28 
-                                       n = n.next;
-                               }
-
-                               newtaggroup.last = n.prev;
-                       }
-
-                       int rest = taggroup.count - hisize * newtgs;
-
-                       taggroup.first = n;
-                       taggroup.count = rest;
-                       taggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta);                                    ofs--;
-                       for (int i = 0; i < rest; i++)
-                       {
-                               n.tag = (i - hisize) << ofs; //(i-16)<<27 
-                               n = n.next;
-                       }
-
-                       taggroup.last = n.prev;
-                       taggroups += newtgs;
-                       if (tgtag == ntgt)
-                               redistributetaggroups(taggroup);
-               }
-
-
-               private void redistributetaggroups(TagGroup taggroup)
-               {
-                       TagGroup pred = taggroup, succ = taggroup, tmp;
-                       double limit = 1, bigt = Math.Pow(taggroups, 1.0 / 30);//?????
-                       int bits = 1, count = 1, lowmask = 0, himask = 0, target = 0;
-
-                       do
-                       {
-                               bits++;
-                               lowmask = (1 << bits) - 1;
-                               himask = ~lowmask;
-                               target = taggroup.tag & himask;
-#if FIXME
-                               while ((tmp = pred.first.prev.taggroup).first != null && (tmp.tag & himask) == target)
-                               { count++; pred = tmp; }
-
-                               while ((tmp = succ.last.next.taggroup).last != null && (tmp.tag & himask) == target)
-                               { count++; succ = tmp; }
-#else
-                               for (tmp = pred.first.prev.taggroup; (tmp.first != null) && ((tmp.tag & himask) == target);)
-                               { count++; pred = tmp; }
-
-                               for (tmp = succ.last.next.taggroup; (tmp.last != null) && ((tmp.tag & himask) == target);)
-                               { count++; succ = tmp; }
-#endif
-
-                               limit *= bigt;
-                       } while (count > limit);
-
-                       //redistibute tags
-                       int lob = pred.first.prev.taggroup.tag, upb = succ.last.next.taggroup.tag;
-                       int delta = upb / (count + 1) - lob / (count + 1);
-
-                       Debug.Assert(delta > 0);
-                       for (int i = 0; i < count; i++)
-                       {
-                               pred.tag = lob + (i + 1) * delta;
-                               pred = pred.last.next.taggroup;
-                       }
-               }
-#endif
-
-               #endregion
-
-               #region Constructors
-               /// <summary>
-               /// Create a linked list with en external item hasher
-               /// </summary>
-               /// <param name="itemhasher">The external hasher</param>
-               public LinkedList(IHasher<T> itemhasher)
-               {
-                       this.itemhasher = itemhasher;
-#if EXTLISTORDER               
-                       startsentinel = new Node(default(T));
-                       endsentinel = new Node(default(T));
-                       startsentinel.next = endsentinel;
-                       endsentinel.prev = startsentinel;
-
-                       //It isused that these are different:
-                       startsentinel.taggroup = new TagGroup();
-                       startsentinel.taggroup.tag = int.MinValue;
-                       startsentinel.taggroup.count = 0;
-                       endsentinel.taggroup = new TagGroup();
-                       endsentinel.taggroup.tag = int.MaxValue;
-                       endsentinel.taggroup.count = 0;
-#else
-                       startsentinel = endsentinel = new Node(default(T));
-                       startsentinel.next = endsentinel.prev = startsentinel;
-#endif
-                       size = stamp = 0;
-               }
-
-
-               /// <summary>
-               /// Create a linked list with the nmatural item hasher
-               /// </summary>
-               public LinkedList() : this(HasherBuilder.ByPrototype<T>.Examine()) { }
-
-               #endregion
-
-               #region Nested classes
-
-               /// <summary>
-               /// An individual cell in the linked list
-               /// </summary>
-               protected class Node
-               {
-                       /// <summary>
-                       /// Previous-node reference
-                       /// </summary>
-                       public Node prev;
-
-                       /// <summary>
-                       /// Next-node reference
-                       /// </summary>
-                       public Node next;
-
-                       /// <summary>
-                       /// Node item
-                       /// </summary>
-                       public T item;
-#if LISTORDER
-                       internal int tag;
-#elif EXTLISTORDER
-                       internal int tag;
-
-                       internal TagGroup taggroup;
-
-
-                       internal bool precedes(Node that)
-                       {
-                               //Debug.Assert(taggroup != null, "taggroup field null");
-                               //Debug.Assert(that.taggroup != null, "that.taggroup field null");
-                               int t1 = taggroup.tag;
-                               int t2 = that.taggroup.tag;
-
-                               return t1 < t2 ? true : t1 > t2 ? false : tag < that.tag;
-                       }
-#endif
-                       /// <summary>
-                       /// Create node
-                       /// </summary>
-                       /// <param name="item">Item to insert</param>
-                       [Tested]
-                       public Node(T item)
-                       {
-                               this.item = item;
-                       }
-
-
-                       /// <summary>
-                       /// Create node, specifying predecessor and successor
-                       /// </summary>
-                       /// <param name="item"></param>
-                       /// <param name="prev"></param>
-                       /// <param name="next"></param>
-                       [Tested]
-                       public Node(T item, Node prev, Node next)
-                       {
-                               this.item = item; this.prev = prev; this.next = next;
-                       }
-
-
-                       /// <summary>
-                       /// Pretty print node
-                       /// </summary>
-                       /// <returns>Formatted node</returns>
-                       public override string ToString()
-                       {
-#if LISTORDER || EXTLISTORDER
-                               return String.Format("Node: (item={0}, tag={1})", item, tag);
-#else
-                               return String.Format("Node(item={0})", item);
-#endif
-                       }
-               }
-
-#if EXTLISTORDER               
-               /// <summary>
-               /// A group of nodes with the same high tag. Purpose is to be
-               /// able to tell the sequence order of two nodes without having to scan through
-               /// the list.
-               /// </summary>
-               protected class TagGroup
-               {
-                       internal int tag, count;
-
-                       internal Node first, last;
-
-
-                       /// <summary>
-                       /// Pretty print a tag group
-                       /// </summary>
-                       /// <returns>Formatted tag group</returns>
-                       public override string ToString()
-                       { return String.Format("TagGroup(tag={0}, cnt={1}, fst={2}, lst={3})", tag, count, first, last); }
-               }
-#endif
-
-               #endregion 
-
-               #region Range nested class
-
-               class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>
-               {
-                       int start, count, stamp;
-
-                       LinkedList<T> list;
-
-                       bool forwards;
-
-
-                       internal Range(LinkedList<T> list, int start, int count, bool forwards)
-                       {
-                               this.list = list;this.stamp = list.stamp;
-                               this.start = start;this.count = count;this.forwards = forwards;
-                       }
-
-
-                       [Tested]
-                       public override int Count { [Tested]get { list.modifycheck(stamp); return count; } }
-
-
-            public override Speed CountSpeed { get { list.modifycheck(stamp); return Speed.Constant; } }
-
-            [Tested]
-                       public override MSG.IEnumerator<T> GetEnumerator()
-                       {
-                               int togo = count;
-
-                               list.modifycheck(stamp);
-                               if (togo == 0)
-                                       yield break;
-
-                               Node cursor = forwards ? list.get(start) : list.get(start + count - 1);
-
-                               yield return cursor.item;
-                               while (--togo > 0)
-                               {
-                                       cursor = forwards ? cursor.next : cursor.prev;
-                                       list.modifycheck(stamp);
-                                       yield return cursor.item;
-                               }
-                       }
-
-
-                       [Tested]
-                       public IDirectedCollectionValue<T> Backwards()
-                       {
-                               list.modifycheck(stamp);
-
-                               Range b = (Range)MemberwiseClone();
-
-                               b.forwards = !forwards;
-                               return b;
-                       }
-
-
-                       [Tested]
-                       IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
-
-
-                       [Tested]
-                       public EnumerationDirection Direction
-                       {
-                               [Tested]
-                               get
-                               { return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards; }
-                       }
-               }
-
-
-               #endregion
-
-               #region IList<T> Members
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> if this list is empty.
-               /// </summary>
-               /// <value>The first item in this list.</value>
-               [Tested]
-               public virtual T First
-               {
-                       [Tested]
-                       get
-                       {
-                               modifycheck();
-                               if (size == 0)
-                                       throw new InvalidOperationException("List is empty");
-
-                               return startsentinel.next.item;
-                       }
-               }
-
-
-               /// <summary>
-               /// <exception cref="InvalidOperationException"/> if this list is empty.
-               /// </summary>
-               /// <value>The last item in this list.</value>
-               [Tested]
-               public virtual T Last
-               {
-                       [Tested]
-                       get
-                       {
-                               modifycheck();
-                               if (size == 0)
-                                       throw new InvalidOperationException("List is empty");
-
-                               return endsentinel.prev.item;
-                       }
-               }
-
-
-               /// <summary>
-               /// Since <code>Add(T item)</code> always add at the end of the list,
-               /// this describes if list has FIFO or LIFO semantics.
-               /// </summary>
-               /// <value>True if the <code>Remove()</code> operation removes from the
-               /// start of the list, false if it removes from the end.</value>
-               [Tested]
-               public bool FIFO
-               {
-                       [Tested]
-                       get { modifycheck(); return fIFO; }
-                       [Tested]
-                       set { updatecheck(); fIFO = value; }
-               }
-
-
-               /// <summary>
-               /// On this list, this indexer is read/write.
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
-               /// &gt;= the size of the collection.
-               /// </summary>
-               /// <value>The i'th item of this list.</value>
-               /// <param name="index">The index of the item to fetch or store.</param>
-               [Tested]
-               public virtual T this[int index]
-               {
-                       [Tested]
-                       get { modifycheck(); return get(index).item; }
-                       [Tested]
-                       set { updatecheck(); get(index).item = value; }
-               }
-
-
-               /// <summary>
-               /// Return the node at position n
-               /// </summary>
-               /// <param name="n"></param>
-               /// <returns></returns>
-               protected Node get(int n)
-               {
-                       if (n < 0 || n >= size)
-                               throw new IndexOutOfRangeException();
-                       else if (n < size / 2)
-                       {              // Closer to front
-                               Node node = startsentinel;
-
-                               for (int i = 0; i <= n; i++)
-                                       node = node.next;
-
-                               return node;
-                       }
-                       else
-                       {                            // Closer to end
-                               Node node = endsentinel;
-
-                               for (int i = size; i > n; i--)
-                                       node = node.prev;
-
-                               return node;
-                       }
-               }
-
-
-               /// <summary>
-               /// Insert an item at a specific index location in this list. 
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
-               /// &gt; the size of the collection.</summary>
-               /// <param name="i">The index at which to insert.</param>
-               /// <param name="item">The item to insert.</param>
-               [Tested]
-               public virtual void Insert(int i, T item)
-               {
-                       updatecheck();
-                       insert(i == size ? endsentinel : get(i), item);
-               }
-
-
-               /// <summary>
-               /// Insert into this list all items from an enumerable collection starting 
-               /// at a particular index.
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
-               /// &gt; the size of the collection.
-               /// </summary>
-               /// <param name="i">Index to start inserting at</param>
-               /// <param name="items">Items to insert</param>
-               [Tested]
-               public virtual void InsertAll(int i, MSG.IEnumerable<T> items)
-               {
-                       updatecheck();
-
-                       Node succ, node;
-                       int count = 0;
-
-                       succ = i == size ? endsentinel : get(i);
-                       node = succ.prev;
-#if LISTORDER
-                       //TODO: replace with Debug.Assert(!maintaintags)
-                       int taglimit = i == size ? int.MaxValue : succ.tag - 1, thetag = node.tag;
-#elif EXTLISTORDER
-                       TagGroup taggroup = null;
-                       int taglimit = 0, thetag = 0;
-
-                       if (maintaintags)
-                               taggroup = gettaggroup(node, succ, out thetag, out taglimit);
-#endif
-                       foreach (T item in items)
-                       {
-                               Node tmp = new Node(item, node, null);
-#if LISTORDER
-                               //TODO: remove
-                               if (maintaintags)
-                                       tmp.tag = thetag < taglimit ? ++thetag : thetag;
-#elif EXTLISTORDER
-                               if (maintaintags)
-                               {
-                                       tmp.tag = thetag < taglimit ? ++thetag : thetag;
-                                       tmp.taggroup = taggroup;
-                               }
-#endif
-                               node.next = tmp;
-                               count++;
-                               node = tmp;
-                       }
-#if EXTLISTORDER
-                       if (maintaintags)
-                       {
-                               taggroup.count += count;
-                               taggroup.first = succ.prev;
-                               taggroup.last = node;
-                       }
-#endif 
-                       succ.prev = node;
-                       node.next = succ;
-                       size += count;
-                       if (underlying != null)
-                               underlying.size += count;
-#if LISTORDER
-                       //TODO: remove 
-                       if (maintaintags && node.tag == node.prev.tag)
-                               settag(node);
-#elif EXTLISTORDER
-                       if (maintaintags)
-                       {
-                               if (node.tag == node.prev.tag)
-                                       splittaggroup(taggroup);
-                       }
-#endif
-               }
-
-
-               /// <summary>
-               /// Insert an item right before the first occurrence of some target item.
-               /// <exception cref="ArgumentException"/> if target     is not found
-               /// </summary>
-               /// <param name="item">The item to insert.</param>
-               /// <param name="target">The target before which to insert.</param>
-               [Tested]
-               public virtual void InsertBefore(T item, T target)
-               {
-                       updatecheck();
-
-                       Node node = startsentinel.next;
-                       int i = 0;
-
-                       if (!find(target, ref node, ref i))
-                               throw new ArgumentException("Target item not found");
-
-                       insert(node, item);
-               }
-
-
-               /// <summary>
-               /// Insert an item right after the last(???) occurrence of some target item.
-               /// <exception cref="ArgumentException"/> if target     is not found
-               /// </summary>
-               /// <param name="item">The item to insert.</param>
-               /// <param name="target">The target after which to insert.</param>
-               [Tested]
-               public virtual void InsertAfter(T item, T target)
-               {
-                       updatecheck();
-
-                       Node node = endsentinel.prev;
-                       int i = size - 1;
-
-                       if (!dnif(target, ref node, ref i))
-                               throw new ArgumentException("Target item not found");
-
-                       insert(node.next, item);
-               }
-
-
-               /// <summary>
-               /// Insert an item at the front of this list.
-               /// </summary>
-               /// <param name="item">The item to insert.</param>
-               [Tested]
-               public virtual void InsertFirst(T item)
-               {
-                       updatecheck();
-                       insert(startsentinel.next, item);
-               }
-
-               /// <summary>
-               /// Insert an item at the back of this list.
-               /// </summary>
-               /// <param name="item">The item to insert.</param>
-               [Tested]
-               public virtual void InsertLast(T item)
-               {
-                       updatecheck();
-                       insert(endsentinel, item);
-               }
-
-
-               /// <summary>
-               /// Create a new list consisting of the results of mapping all items of this
-               /// list.
-               /// </summary>
-               /// <param name="mapper">The delegate definging the map.</param>
-               /// <returns>The new list.</returns>
-               [Tested]
-        public IList<V> Map<V>(Mapper<T, V> mapper)
-        {
-            modifycheck();
-
-            LinkedList<V> retval = new LinkedList<V>();
-            return map<V>(mapper, retval);
-        }
-
-        /// <summary>
-        /// Create a new list consisting of the results of mapping all items of this
-        /// list. The new list will use a specified hasher for the item type.
-        /// </summary>
-        /// <typeparam name="V">The type of items of the new list</typeparam>
-        /// <param name="mapper">The delegate defining the map.</param>
-        /// <param name="hasher">The hasher to use for the new list</param>
-        /// <returns>The new list.</returns>
-        public IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher)
-        {
-            modifycheck();
-
-            LinkedList<V> retval = new LinkedList<V>(hasher);
-            return map<V>(mapper, retval);
-        }
-
-        private IList<V> map<V>(Mapper<T, V> mapper, LinkedList<V> retval)
-        {
-            Node cursor = startsentinel.next;
-            LinkedList<V>.Node mcursor = retval.startsentinel;
-
-#if LISTORDER
-                       //TODO: replace with Debug.Assert(!retval.maintaintags)
-                       double tagdelta = int.MaxValue / (size + 1.0);
-                       int count = 1;
-#elif EXTLISTORDER
-            double tagdelta = int.MaxValue / (size + 1.0);
-            int count = 1;
-            LinkedList<V>.TagGroup taggroup = null;
-
-            if (retval.maintaintags)
-            {
-                taggroup = new LinkedList<V>.TagGroup();
-                retval.taggroups = 1;
-                taggroup.count = size;
-            }
-#endif
-            while (cursor != endsentinel)
-            {
-                mcursor.next = new LinkedList<V>.Node(mapper(cursor.item), mcursor, null);
-                cursor = cursor.next;
-                mcursor = mcursor.next;
-#if LISTORDER
-                               //TODO: remove
-                               if (retval.maintaintags) mcursor.tag = (int)(tagdelta * count++);
-#elif EXTLISTORDER
-                if (retval.maintaintags)
-                {
-                    mcursor.taggroup = taggroup;
-                    mcursor.tag = (int)(tagdelta * count++);
-                }
-#endif
-            }
-
-            retval.endsentinel.prev = mcursor;
-            mcursor.next = retval.endsentinel;
-            retval.size = size; return retval;
-        }
-
-
-        /// <summary>
-               /// Remove one item from the list: from the front if <code>FIFO</code>
-               /// is true, else from the back.
-               /// <exception cref="InvalidOperationException"/> if this list is empty.
-               /// </summary>
-               /// <returns>The removed item.</returns>
-               [Tested]
-               public virtual T Remove()
-               {
-                       return fIFO ? RemoveFirst() : RemoveLast();
-               }
-
-
-               /// <summary>
-               /// Remove one item from the front of the list.
-               /// <exception cref="InvalidOperationException"/> if this list is empty.
-               /// </summary>
-               /// <returns>The removed item.</returns>
-               [Tested]
-               public virtual T RemoveFirst()
-               {
-                       updatecheck();
-                       if (size == 0)
-                throw new InvalidOperationException("List is empty");
-
-            T item = startsentinel.next.item;
-
-                       if (size == 1)
-                               clear();
-                       else
-                               remove(startsentinel.next);
-
-                       return item;
-               }
-
-
-               /// <summary>
-               /// Remove one item from the back of the list.
-               /// <exception cref="InvalidOperationException"/> if this list is empty.
-               /// </summary>
-               /// <returns>The removed item.</returns>
-               [Tested]
-               public virtual T RemoveLast()
-               {
-                       updatecheck();
-                       if (size == 0)
-                throw new InvalidOperationException("List is empty");
-
-            Node toremove = endsentinel.prev;
-                       T item = toremove.item;
-
-                       if (size == 1)
-                               clear();
-                       else
-                               remove(toremove);
-
-                       return item;
-               }
-
-
-               /// <summary>
-               /// Create a list view on this list. 
-        /// <exception cref="ArgumentOutOfRangeException"/> if the start or count is negative
-        /// <exception cref="ArgumentException"/> if the range does not fit within list.
-        /// </summary>
-        /// <param name="start">The index in this list of the start of the view.</param>
-               /// <param name="count">The size of the view.</param>
-               /// <returns>The new list view.</returns>
-               [Tested]
-               public virtual IList<T> View(int start, int count)
-               {
-                       modifycheck();
-                       checkRange(start, count);
-
-                       LinkedList<T> retval = (LinkedList<T>)MemberwiseClone();
-
-                       retval.underlying = underlying != null ? underlying : this;
-                       retval.offset = offset + start;
-                       retval.size = count;
-                       retval.startsentinel = start == 0 ? startsentinel : get(start - 1);
-                       retval.endsentinel = start + count == size ? endsentinel : get(start + count);
-#if DEBUG
-                       Check();
-#endif
-                       return retval;
-               }
-
-
-               /// <summary>
-               /// Null if this list is not a view.
-               /// </summary>
-        /// <value>Underlying list for view.</value>
-        [Tested]
-        public IList<T> Underlying { [Tested]get { modifycheck(); return underlying; } }
-
-
-        /// <summary>
-               /// </summary>
-               /// <value>Offset for this list view or 0 for a underlying list.</value>
-               [Tested]
-               public int Offset { [Tested]get { modifycheck(); return offset; } }
-
-
-               /// <summary>
-               /// Slide this list view along the underlying list.
-               /// <exception cref="InvalidOperationException"/> if this list is not a view.
-               /// <exception cref="ArgumentOutOfRangeException"/> if the operation
-               /// would bring either end of the view outside the underlying list.
-               /// </summary>
-               /// <param name="offset">The signed amount to slide: positive to slide
-               /// towards the end.</param>
-               [Tested]
-               public void Slide(int offset)
-               {
-                       modifycheck();
-                       if (underlying == null)
-                               throw new InvalidOperationException("List not a view");
-
-                       if (offset + this.offset < 0 || offset + this.offset + size > underlying.size)
-                               throw new ArgumentOutOfRangeException();
-
-                       if (offset == 0) return;
-
-                       if (offset > 0)
-                               for (int i = 0; i < offset; i++)
-                               {
-                                       endsentinel = endsentinel.next;
-                                       startsentinel = startsentinel.next;
-                               }
-                       else
-                               for (int i = 0; i < -offset; i++)
-                               {
-                                       endsentinel = endsentinel.prev;
-                                       startsentinel = startsentinel.prev;
-                               }
-
-                       this.offset += offset;
-               }
-
-
-               /// <summary>
-               /// Slide this list view along the underlying list, changing its size.
-               /// <exception cref="InvalidOperationException"/> if this list is not a view.
-               /// <exception cref="ArgumentOutOfRangeException"/> if the operation
-               /// would bring either end of the view outside the underlying list.
-               /// </summary>
-               /// <param name="offset">The signed amount to slide: positive to slide
-               /// towards the end.</param>
-               /// <param name="size">The new size of the view.</param>
-               [Tested]
-               public void Slide(int offset, int size)
-               {
-                       modifycheck();
-                       if (underlying == null)
-                               throw new InvalidOperationException("List not a view");
-
-                       if (offset + this.offset < 0 || offset + this.offset + size > underlying.size)
-                               throw new ArgumentOutOfRangeException();
-
-                       Node node = startsentinel;
-
-                       if (offset > 0)
-                               for (int i = 0; i < offset; i++)
-                                       node = node.next;
-                       else
-                               for (int i = 0; i < -offset; i++)
-                                       node = node.prev;
-
-                       startsentinel = node;
-
-                       int enddelta = offset + size - this.size;
-
-                       node = endsentinel;
-                       if (enddelta > 0)
-                               for (int i = 0; i < enddelta; i++)
-                                       node = node.next;
-                       else
-                               for (int i = 0; i < -enddelta; i++)
-                                       node = node.prev;
-
-                       endsentinel = node;
-                       this.size = size;
-                       this.offset += offset;
-               }
-
-
-               /// <summary>
-               /// Reverse the list so the items are in the opposite sequence order.
-               /// </summary>
-               [Tested]
-               public void Reverse() { Reverse(0, size); }
-
-
-               //Question: should we swap items or move nodes around?
-               //The first seems much more efficient unless the items are value types 
-               //with a large memory footprint.
-               //(Swapping will do count*3/2 T assignments, linking around will do 
-               // 4*count ref assignments; note that ref assignments are more expensive 
-               //than copying non-ref bits)
-               /// <summary>
-               /// Reverst part of the list so the items are in the opposite sequence order.
-               /// <exception cref="ArgumentException"/> if the count is negative.
-               /// <exception cref="ArgumentOutOfRangeException"/> if the part does not fit
-               /// into the list.
-               /// </summary>
-               /// <param name="start">The index of the start of the part to reverse.</param>
-               /// <param name="count">The size of the part to reverse.</param>
-               [Tested]
-               public virtual void Reverse(int start, int count)
-               {
-                       updatecheck();
-                       checkRange(start, count);
-                       if (count == 0)
-                               return;
-
-                       Node a = get(start), b = get(start + count - 1);
-
-                       for (int i = 0; i < count / 2; i++)
-                       {
-                               T swap = a.item;a.item = b.item;b.item = swap;
-#if LISTORDER
-                               //Do nothing!
-#elif EXTLISTORDER
-                               //Neither
-#endif
-                               a = a.next;b = b.prev;
-                       }
-               }
-
-
-               /// <summary>
-               /// Check if this list is sorted according to a specific sorting order.
-               /// </summary>
-               /// <param name="c">The comparer defining the sorting order.</param>
-               /// <returns>True if the list is sorted, else false.</returns>
-               [Tested]
-               public bool IsSorted(IComparer<T> c)
-               {
-                       modifycheck();
-                       if (size <= 1)
-                               return true;
-
-                       Node node = startsentinel.next;
-                       T prevItem = node.item;
-
-                       node = node.next;
-                       while (node != endsentinel)
-                       {
-                               if (c.Compare(prevItem, node.item) > 0)
-                                       return false;
-                               else
-                               {
-                                       prevItem = node.item;
-                                       node = node.next;
-                               }
-                       }
-
-                       return true;
-               }
-
-
-               // Sort the linked list using mergesort
-               /// <summary>
-               /// Sort the items of the list according to a specific sorting order.
-               /// The sorting is stable.
-               /// </summary>
-               /// <param name="c">The comparer defining the sorting order.</param>
-               [Tested]
-               public void Sort(IComparer<T> c)
-               {
-                       updatecheck();
-
-                       // Build a linked list of non-empty runs.
-                       // The prev field in first node of a run points to next run's first node
-                       if (size == 0)
-                               return;
-
-#if EXTLISTORDER
-                       if (maintaintags && underlying != null)
-                       {
-                               Node cursor = startsentinel.next;
-
-                               while (cursor != endsentinel)
-                               {
-                                       cursor.taggroup.count--;
-                                       cursor = cursor.next;
-                               }
-                       }
-#endif
-                       Node runTail = startsentinel.next;
-                       Node prevNode = startsentinel.next;
-
-                       endsentinel.prev.next = null;
-                       while (prevNode != null)
-                       {
-                               Node node = prevNode.next;
-
-                               while (node != null && c.Compare(prevNode.item, node.item) <= 0)
-                               {
-                                       prevNode = node;
-                                       node = prevNode.next;
-                               }
-
-                               // Completed a run; prevNode is the last node of that run
-                               prevNode.next = null;   // Finish the run
-                               runTail.prev = node;    // Link it into the chain of runs
-                               runTail = node;
-                               if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0)
-                                       endsentinel.prev = prevNode;    // Update last pointer to point to largest
-
-                               prevNode = node;                // Start a new run
-                       }
-
-                       // Repeatedly merge runs two and two, until only one run remains
-                       while (startsentinel.next.prev != null)
-                       {
-                               Node run = startsentinel.next;
-                               Node newRunTail = null;
-
-                               while (run != null && run.prev != null)
-                               { // At least two runs, merge
-                                       Node nextRun = run.prev.prev;
-                                       Node newrun = mergeRuns(run, run.prev, c);
-
-                                       if (newRunTail != null)
-                                               newRunTail.prev = newrun;
-                                       else
-                                               startsentinel.next = newrun;
-
-                                       newRunTail = newrun;
-                                       run = nextRun;
-                               }
-
-                               if (run != null) // Add the last run, if any
-                                       newRunTail.prev = run;
-                       }
-
-                       endsentinel.prev.next = endsentinel;
-                       startsentinel.next.prev = startsentinel;
-
-                       //assert invariant();
-                       //assert isSorted();
-#if LISTORDER
-                       if (maintaintags)
-                       {
-                               int span = (endsentinel.tag > 0 ? endsentinel.tag - 1 : int.MaxValue) - startsentinel.tag;
-
-                               Debug.Assert(span >= size);
-
-                               double tagdelta = span / (size + 0.0);
-                               int count = 1;
-                               Node cursor = startsentinel.next;
-
-                               while (cursor != endsentinel)
-                               {
-                                       cursor.tag = startsentinel.tag + (int)(tagdelta * count++);
-                                       cursor = cursor.next;
-                               }
-                       }
-#elif EXTLISTORDER
-                       if (maintaintags)
-                       {
-                               Node cursor = startsentinel.next, end = endsentinel;
-                               int tag, taglimit;
-                               TagGroup t = gettaggroup(startsentinel, endsentinel, out tag, out taglimit);
-                               int tagdelta = taglimit / (size + 1) - tag / (size + 1);
-
-                               tagdelta = tagdelta == 0 ? 1 : tagdelta;
-                               if (underlying == null)
-                                       taggroups = 1;
-
-                               while (cursor != end)
-                               {
-                                       tag = tag + tagdelta > taglimit ? taglimit : tag + tagdelta;
-                                       cursor.tag = tag;
-                                       t.count++;
-                                       cursor = cursor.next;
-                               }
-
-                               if (tag == taglimit)
-                                       splittaggroup(t);
-                       }
-#endif
-               }
-
-
-               private static Node mergeRuns(Node run1, Node run2, IComparer<T> c)
-               {
-                       //assert run1 != null && run2 != null;
-                       Node prev;
-                       bool prev1;     // is prev from run1?
-
-                       if (c.Compare(run1.item, run2.item) <= 0)
-                       {
-                               prev = run1;
-                               prev1 = true;
-                               run1 = run1.next;
-                       }
-                       else
-                       {
-                               prev = run2;
-                               prev1 = false;
-                               run2 = run2.next;
-                       }
-
-                       Node start = prev;
-
-                       //assert start != null;
-                       start.prev = null;
-                       while (run1 != null && run2 != null)
-                       {
-                               if (prev1)
-                               {
-                                       //assert prev.next == run1;
-                                       //Comparable run2item = (Comparable)run2.item;
-                                       while (run1 != null && c.Compare(run2.item, run1.item) >= 0)
-                                       {
-                                               prev = run1;
-                                               run1 = prev.next;
-                                       }
-
-                                       if (run1 != null)
-                                       { // prev.item <= run2.item < run1.item; insert run2
-                                               prev.next = run2;
-                                               run2.prev = prev;
-                                               prev = run2;
-                                               run2 = prev.next;
-                                               prev1 = false;
-                                       }
-                               }
-                               else
-                               {
-                                       //assert prev.next == run2;
-                                       //Comparable run1item = (Comparable)run1.item;
-                                       while (run2 != null && c.Compare(run1.item, run2.item) > 0)
-                                       {
-                                               prev = run2;
-                                               run2 = prev.next;
-                                       }
-
-                                       if (run2 != null)
-                                       { // prev.item < run1.item <= run2.item; insert run1
-                                               prev.next = run1;
-                                               run1.prev = prev;
-                                               prev = run1;
-                                               run1 = prev.next;
-                                               prev1 = true;
-                                       }
-                               }
-                       }
-
-                       //assert !(run1 != null && prev1) && !(run2 != null && !prev1);
-                       if (run1 != null)
-                       { // last run2 < all of run1; attach run1 at end
-                               prev.next = run1;
-                               run1.prev = prev;
-                       }
-                       else if (run2 != null)
-                       { // last run1 
-                               prev.next = run2;
-                               run2.prev = prev;
-                       }
-
-                       return start;
-               }
-
-
-               /// <summary>
-               /// Randonmly shuffle the items of this list. 
-               /// </summary>
-               public virtual void Shuffle() { Shuffle(new C5Random()); }
-
-
-               /// <summary>
-               /// Shuffle the items of this list according to a specific random source.
-               /// </summary>
-               /// <param name="rnd">The random source.</param>
-               public virtual void Shuffle(Random rnd)
-               {
-                       updatecheck();
-
-                       ArrayList<T> a = new ArrayList<T>();
-
-                       a.AddAll(this);
-                       a.Shuffle(rnd);
-
-                       Node cursor = startsentinel.next;
-                       int j = 0;
-
-                       while (cursor != endsentinel)
-                       {
-                               cursor.item = a[j++];
-                               cursor = cursor.next;
-                       }
-               }
-
-               #endregion
-
-               #region IIndexed<T> Members
-
-
-               /// <summary>
-               /// <exception cref="IndexOutOfRangeException"/>.
-               /// </summary>
-               /// <value>The directed collection of items in a specific index interval.</value>
-               /// <param name="start">The low index of the interval (inclusive).</param>
-        /// <param name="count">The size of the range.</param>
-        [Tested]
-        public IDirectedCollectionValue<T> this[int start, int count]
-               {
-                       [Tested]
-                       get
-                       {
-                               modifycheck();
-                               checkRange(start, count);
-                               return new Range(this, start, count, true);
-                       }
-               }
-
-
-               /// <summary>
-               /// Searches for an item in the list going forwrds from the start.
-               /// </summary>
-               /// <param name="item">Item to search for.</param>
-               /// <returns>Index of item from start.</returns>
-               [Tested]
-               public virtual int IndexOf(T item)
-               {
-                       modifycheck();
-
-                       Node node = startsentinel.next;
-                       int index = 0;
-
-                       if (find(item, ref node, ref index))
-                               return index;
-                       else
-                               return -1;
-               }
-
-
-               /// <summary>
-               /// Searches for an item in the list going backwords from the end.
-               /// </summary>
-               /// <param name="item">Item to search for.</param>
-               /// <returns>Index of of item from the end.</returns>
-               [Tested]
-               public virtual int LastIndexOf(T item)
-               {
-                       modifycheck();
-
-                       Node node = endsentinel.prev;
-                       int index = size - 1;
-
-                       if (dnif(item, ref node, ref index))
-                               return index;
-                       else
-                               return -1;
-               }
-
-
-               private bool find(T item, ref Node node, ref int index)
-               {
-                       while (node != endsentinel)
-                       {
-                               //if (item.Equals(node.item))
-                               if (itemhasher.Equals(item, node.item))
-                                       return true;
-
-                               index++;
-                               node = node.next;
-                       }
-
-                       return false;
-               }
-
-
-               private bool dnif(T item, ref Node node, ref int index)
-               {
-                       while (node != startsentinel)
-                       {
-                               //if (item.Equals(node.item))
-                               if (itemhasher.Equals(item, node.item))
-                                       return true;
-
-                               index--;
-                               node = node.prev;
-                       }
-
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Remove the item at a specific position of the list.
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or
-               /// &gt;= the size of the collection.
-               /// </summary>
-               /// <param name="i">The index of the item to remove.</param>
-               /// <returns>The removed item.</returns>
-               [Tested]
-               public virtual T RemoveAt(int i)
-               {
-                       updatecheck();
-                       return remove(get(i));
-               }
-
-
-               /// <summary>
-               /// Remove all items in an index interval.
-               /// <exception cref="IndexOutOfRangeException"/>???. 
-               /// </summary>
-               /// <param name="start">The index of the first item to remove.</param>
-               /// <param name="count">The number of items to remove.</param>
-               [Tested]
-               public virtual void RemoveInterval(int start, int count)
-               {
-                       updatecheck();
-                       checkRange(start, count);
-                       if (count == 0)
-                               return;
-
-                       //for small count: optimize
-                       //make an optimal get(int i, int j, ref Node ni, ref Node nj)?
-                       Node a = get(start), b = get(start + count - 1);
-#if EXTLISTORDER
-                       if (maintaintags)
-                       {
-                               Node c = a;
-                               TagGroup t = a.taggroup;
-
-                               while (c.taggroup == t && c != b.next)
-                               {
-                                       removefromtaggroup(c);
-                                       c = c.next;
-                               }
-
-                               if (c != b.next)
-                               {
-                                       Debug.Assert(b.taggroup != t);
-                                       c = b;
-                                       t = b.taggroup;
-                                       while (c.taggroup == t)
-                                       {
-                                               removefromtaggroup(c);
-                                               c = c.prev;
-                                       }
-                               }
-                       }
-#endif
-                       a.prev.next = b.next;
-                       b.next.prev = a.prev;
-                       if (underlying != null)
-                               underlying.size -= count;
-
-                       size -= count;
-               }
-
-               
-               #endregion
-
-               #region ISequenced<T> Members
-
-               [Tested]
-               int ISequenced<T>.GetHashCode() { modifycheck(); return sequencedhashcode(); }
-
-
-               [Tested]
-               bool ISequenced<T>.Equals(ISequenced<T> that)
-               { modifycheck(); return sequencedequals(that); }
-
-               #endregion
-
-               #region IDirectedCollection<T> Members
-
-               /// <summary>
-               /// Create a collection containing the same items as this collection, but
-               /// whose enumerator will enumerate the items backwards. The new collection
-               /// will become invalid if the original is modified. Method typicaly used as in
-               /// <code>foreach (T x in coll.Backwards()) {...}</code>
-               /// </summary>
-               /// <returns>The backwards collection.</returns>
-               [Tested]
-               public IDirectedCollectionValue<T> Backwards()
-               { return this[0, size].Backwards(); }
-
-               #endregion
-
-               #region IDirectedEnumerable<T> Members
-
-               [Tested]
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
-               
-               #endregion
-
-               #region IEditableCollection<T> Members
-
-               /// <summary>
-               /// The value is symbolic indicating the type of asymptotic complexity
-               /// in terms of the size of this collection (worst-case or amortized as
-               /// relevant).
-               /// </summary>
-               /// <value>Speed.Linear</value>
-               [Tested]
-               public virtual Speed ContainsSpeed { [Tested]get { return Speed.Linear; } }
-
-
-               [Tested]
-               int ICollection<T>.GetHashCode()
-               { modifycheck(); return unsequencedhashcode(); }
-
-
-               [Tested]
-               bool ICollection<T>.Equals(ICollection<T> that)
-               { modifycheck(); return unsequencedequals(that); }
-
-
-               /// <summary>
-               /// Check if this collection contains (an item equivalent to according to the
-               /// itemhasher) a particular value.
-               /// </summary>
-               /// <param name="item">The value to check for.</param>
-               /// <returns>True if the items is in this collection.</returns>
-               [Tested]
-               public virtual bool Contains(T item)
-               {
-                       modifycheck();
-
-                       Node node = startsentinel.next;
-
-                       while (node != endsentinel)
-                       {
-                               if (itemhasher.Equals(item, node.item))
-                                       return true;
-
-                               node = node.next;
-                       }
-
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Check if this collection contains an item equivalent according to the
-               /// itemhasher to a particular value. If so, return in the ref argument (a
-               /// binary copy of) the actual value found.
-               /// </summary>
-               /// <param name="item">The value to look for.</param>
-               /// <returns>True if the items is in this collection.</returns>
-               [Tested]
-               public virtual bool Find(ref T item)
-               {
-                       modifycheck();
-
-                       Node node = startsentinel.next;
-
-                       while (node != endsentinel)
-                       {
-                               if (equals(item, node.item))
-                               {
-                                       item = node.item;
-                                       return true;
-                               }
-
-                               node = node.next;
-                       }
-
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Check if this collection contains an item equivalent according to the
-               /// itemhasher to a particular value. If so, update the item in the collection 
-               /// to with a binary copy of the supplied value. Will update a single item.
-               /// </summary>
-               /// <param name="item">Value to update.</param>
-               /// <returns>True if the item was found and hence updated.</returns>
-               [Tested]
-               public virtual bool Update(T item)
-               {
-                       updatecheck();
-
-                       Node node = startsentinel.next;
-
-                       while (node != endsentinel)
-                       {
-                               if (equals(item, node.item))
-                               {
-                                       node.item = item;
-                                       return true;
-                               }
-
-                               node = node.next;
-                       }
-
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Check if this collection contains an item equivalent according to the
-               /// itemhasher to a particular value. If so, return in the ref argument (a
-               /// binary copy of) the actual value found. Else, add the item to the collection.
-               /// </summary>
-               /// <param name="item">The value to look for.</param>
-               /// <returns>True if the item was found (hence not added).</returns>
-               [Tested]
-               public virtual bool FindOrAdd(ref T item)
-               {
-                       updatecheck();
-                       if (Find(ref item))
-                               return true;
-
-                       Add(item);
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Check if this collection contains an item equivalent according to the
-               /// itemhasher to a particular value. If so, update the item in the collection 
-               /// to with a binary copy of the supplied value; else add the value to the collection. 
-               /// </summary>
-               /// <param name="item">Value to add or update.</param>
-               /// <returns>True if the item was updated (hence not added).</returns>
-               [Tested]
-               public virtual bool UpdateOrAdd(T item)
-               {
-                       updatecheck();
-                       if (Update(item))
-                               return true;
-
-                       Add(item);
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Remove a particular item from this collection. Since the collection has bag
-               /// semantics only one copy equivalent to the supplied item is removed. 
-               /// </summary>
-               /// <param name="item">The value to remove.</param>
-               /// <returns>True if the item was found (and removed).</returns>
-               [Tested]
-               public virtual bool Remove(T item)
-               {
-                       updatecheck();
-
-                       Node node = startsentinel.next;
-
-                       while (node != endsentinel)
-                       {
-                               if (itemhasher.Equals(item, node.item))
-                               {
-                                       remove(node);
-                                       return true;
-                               }
-
-                               node = node.next;
-                       }
-
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Remove a particular item from this collection if found (only one copy). 
-               /// If an item was removed, report a binary copy of the actual item removed in 
-               /// the argument.
-               /// </summary>
-               /// <param name="item">The value to remove on input.</param>
-               /// <returns>True if the item was found (and removed).</returns>
-               [Tested]
-               public virtual bool RemoveWithReturn(ref T item)
-               {
-                       updatecheck();
-
-                       Node node = startsentinel.next;
-
-                       while (node != endsentinel)
-                       {
-                               if (itemhasher.Equals(item, node.item))
-                               {
-                                       item = node.item;
-                                       remove(node);
-                                       return true;
-                               }
-
-                               node = node.next;
-                       }
-
-                       return false;
-               }
-
-
-               /// <summary>
-               /// Remove all items in another collection from this one, take multiplicities into account.
-               /// </summary>
-               /// <param name="items">The items to remove.</param>
-               [Tested]
-               public virtual void RemoveAll(MSG.IEnumerable<T> items)
-               {
-                       //Use an auxiliary hashbag should speed from O(n*m) to O(n+m) but use more memory
-                       updatecheck();
-                       if (size == 0)
-                               return;
-
-                       bool[] paired = new bool[size];
-                       int index, toretain = size;
-                       Node node;
-
-                       foreach (T item in items)
-                       {
-                               node = startsentinel.next;
-                               index = 0;
-                               while (node != endsentinel)
-                               {
-                                       if (itemhasher.Equals(item, node.item) && !paired[index])
-                                       {
-                                               if (--toretain == 0)
-                                               {
-                                                       clear();
-                                                       return;
-                                               }
-
-                                               paired[index] = true;
-                                               goto cont;
-                                       }
-
-                                       node = node.next;
-                                       index++;
-                               }
-                       cont :
-
-                               ;
-                       }
-
-                       if (toretain == size)
-                               return;
-
-                       if (underlying != null)
-                               underlying.size -= size - toretain;
-
-                       node = startsentinel.next;
-                       size = toretain;
-                       index = 0;
-                       while (paired[index])
-                       {
-#if EXTLISTORDER
-                               if (maintaintags) removefromtaggroup(node);
-#endif
-                               node = node.next;
-                               index++;
-                       }
-
-                       if (index > 0)
-                       {
-                               startsentinel.next = node;
-                               node.prev = startsentinel;
-                       }
-
-                       while (true)
-                       {
-                               while (--toretain > 0 && !paired[++index])
-                                       node = node.next;
-
-                               Node localend = node;
-
-                               if (toretain == 0)
-                               {
-#if EXTLISTORDER
-                                       node = node.next;
-                                       while (node != endsentinel)
-                                       {
-                                               if (maintaintags) removefromtaggroup(node);
-
-                                               node = node.next;
-                                       }
-#endif
-                                       //fixup at end
-                                       endsentinel.prev = localend;
-                                       localend.next = endsentinel;
-                                       break;
-                               }
-
-                               node = node.next;
-                               while (paired[index])
-                               {
-#if EXTLISTORDER
-                                       if (maintaintags) removefromtaggroup(node);
-#endif
-                                       node = node.next;
-                                       index++;
-                               }
-
-                               localend.next = node;
-                               node.prev = localend;
-                       }
-               }
-
-
-               /// <summary>
-               /// Remove all items from this collection.
-               /// </summary>
-               [Tested]
-               public virtual void Clear()
-               {
-                       updatecheck();
-                       clear();
-               }
-
-
-               void clear()
-               {
-#if EXTLISTORDER
-                       if (maintaintags)
-                       {
-                               if (underlying != null)
-                               {
-                                       Node n = startsentinel.next;
-
-                                       while (n != endsentinel)
-                                       {
-                                               n.next.prev = startsentinel;
-                                               startsentinel.next = n.next;
-                                               removefromtaggroup(n);
-                                               n = n.next;
-                                       }
-                               }
-                               else
-                               {
-                                       taggroups = 0;
-                               }
-                       }
-#endif
-                       endsentinel.prev = startsentinel;
-                       startsentinel.next = endsentinel;
-                       if (underlying != null)
-                               underlying.size -= size;
-
-                       size = 0;
-               }
-
-
-               /// <summary>
-               /// Remove all items not in some other collection from this one, take multiplicities into account.
-               /// </summary>
-               /// <param name="items">The items to retain.</param>
-               [Tested]
-               public virtual void RetainAll(MSG.IEnumerable<T> items)
-               {
-                       updatecheck();
-                       if (size == 0)
-                               return;
-
-                       bool[] paired = new bool[size];
-                       int index, pairs = 0;
-                       Node node;
-
-                       foreach (T item in items)
-                       {
-                               node = startsentinel.next;
-                               index = 0;
-                               while (node != endsentinel)
-                               {
-                                       if (itemhasher.Equals(item, node.item) && !paired[index])
-                                       {
-                                               if (++pairs == size)
-                                                       return;
-
-                                               paired[index] = true;
-                                               goto cont;
-                                       }
-
-                                       node = node.next;
-                                       index++;
-                               }
-                       cont :
-
-                               ;
-                       }
-
-                       if (pairs == 0)
-                       {
-                               clear();
-                               return;
-                       }
-
-                       if (underlying != null)
-                               underlying.size -= size - pairs;
-
-                       node = startsentinel.next;
-                       size = pairs;
-                       index = 0;
-                       while (!paired[index])
-                       {
-#if EXTLISTORDER
-                               if (maintaintags) removefromtaggroup(node);
-#endif
-                               node = node.next;
-                               index++;
-                       }
-
-                       if (index > 0)
-                       {
-                               startsentinel.next = node;
-                               node.prev = startsentinel;
-                       }
-
-                       while (true)
-                       {
-                               while (--pairs > 0 && paired[++index])
-                                       node = node.next;
-
-                               Node localend = node;
-
-                               if (pairs == 0)
-                               {
-#if EXTLISTORDER
-                                       node = node.next;
-                                       while (node != endsentinel)
-                                       {
-                                               if (maintaintags) removefromtaggroup(node);
-
-                                               node = node.next;
-                                       }
-#endif
-                                       endsentinel.prev = localend;
-                                       localend.next = endsentinel;
-                                       break;
-                               }
-
-                               node = node.next;
-                               while (!paired[index])
-                               {
-#if EXTLISTORDER
-                                       if (maintaintags) removefromtaggroup(node);
-#endif
-                                       node = node.next;
-                                       index++;
-                               }
-
-                               localend.next = node;
-                               node.prev = localend;
-                       }
-               }
-
-
-               /// <summary>
-               /// Check if this collection contains all the values in another collection
-               /// with respect to multiplicities.
-               /// </summary>
-               /// <param name="items">The </param>
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>
-               [Tested]
-               public virtual bool ContainsAll(MSG.IEnumerable<T> items)
-               {
-                       modifycheck();
-
-                       bool[] paired = new bool[size];
-
-                       foreach (T item in items)
-                       {
-                               int index = 0;
-                               Node node = startsentinel.next;
-
-                               while (node != endsentinel)
-                               {
-                                       if (itemhasher.Equals(item, node.item) && !paired[index])
-                                       {
-                                               paired[index] = true;
-                                               goto cont;
-                                       }
-
-                                       node = node.next;
-                                       index++;
-                               }
-
-                               return false;
-                       cont :
-                               ;
-                       }
-
-                       return true;
-               }
-
-
-               /// <summary>
-               /// Create a new list consisting of the items of this list satisfying a 
-               /// certain predicate.
-               /// </summary>
-               /// <param name="filter">The filter delegate defining the predicate.</param>
-               /// <returns>The new list.</returns>
-               [Tested]
-               public IList<T> FindAll(Filter<T> filter)
-               {
-                       LinkedList<T> retval = new LinkedList<T>();
-
-                       modifycheck();
-
-                       Node cursor = startsentinel.next;
-                       Node mcursor = retval.startsentinel;
-
-#if LISTORDER
-                       double tagdelta = int.MaxValue / (size + 1.0);
-#elif EXTLISTORDER
-                       double tagdelta = int.MaxValue / (size + 1.0);
-                       int count = 1;
-                       TagGroup taggroup = null;
-
-                       if (retval.maintaintags)
-                       {
-                               taggroup = new TagGroup();
-                               retval.taggroups = 1;
-                       }
-#endif
-                       while (cursor != endsentinel)
-                       {
-                               if (filter(cursor.item))
-                               {
-                                       mcursor.next = new Node(cursor.item, mcursor, null);
-                                       mcursor = mcursor.next;
-                                       retval.size++;
-#if LISTORDER
-                                       if (retval.maintaintags)
-                                               mcursor.tag = (int)(retval.size * tagdelta);
-#elif EXTLISTORDER
-                                       if (retval.maintaintags)
-                                       {
-                                               mcursor.taggroup = taggroup;
-                                               mcursor.tag = (int)(tagdelta * count++);
-                                       }
-#endif
-                               }
-
-                               cursor = cursor.next;
-                       }
-
-#if EXTLISTORDER       
-                       if (retval.maintaintags)
-                               taggroup.count = retval.size;
-#endif
-                       retval.endsentinel.prev = mcursor;
-                       mcursor.next = retval.endsentinel;
-                       return retval;
-               }
-
-
-               /// <summary>
-               /// Count the number of items of the collection equal to a particular value.
-               /// Returns 0 if and only if the value is not in the collection.
-               /// </summary>
-               /// <param name="item">The value to count.</param>
-               /// <returns>The number of copies found.</returns>
-               [Tested]
-               public virtual int ContainsCount(T item)
-               {
-                       int retval = 0;
-
-                       modifycheck();
-
-                       Node node = startsentinel.next;
-
-                       while (node != endsentinel)
-                       {
-                               if (itemhasher.Equals(node.item, item))
-                                       retval++;
-
-                               node = node.next;
-                       }
-
-                       return retval;
-               }
-
-
-               /// <summary>
-               /// Remove all items equivalent to a given value.
-               /// </summary>
-               /// <param name="item">The value to remove.</param>
-               [Tested]
-               public virtual void RemoveAllCopies(T item)
-               {
-                       updatecheck();
-
-                       int removed = 0;
-                       Node node = startsentinel.next;
-
-                       while (node != endsentinel)
-                       {
-                               //Here we could loop to collect more matching adjacent nodes in one 
-                               //splice, but with some overhead for the general case.
-                               //se retailall for an example
-                               //if (node.item.Equals(item))
-                               if (itemhasher.Equals(node.item, item))
-                               {
-                                       removed++;
-                                       node.prev.next = node.next;
-                                       node.next.prev = node.prev;
-#if EXTLISTORDER
-                                       if (maintaintags)
-                                               removefromtaggroup(node);
-#endif
-                               }
-
-                               node = node.next;
-                       }
-
-                       if (removed > 0)
-                       {
-                               size -= removed;
-                               if (underlying != null)
-                                       underlying.size -= removed;
-                       }
-
-                       return;
-               }
-               #endregion
-
-               #region ICollection<T> Members
-
-               /// <summary>
-               /// 
-               /// </summary>
-               /// <value>The number of items in this collection</value>
-               [Tested]
-               public override int Count { [Tested]get { modifycheck(); return size; } }
-
-               #endregion
-
-               #region IEnumerable<T> Members
-               /// <summary>
-               /// Create an enumerator for the collection
-               /// </summary>
-               /// <returns>The enumerator</returns>
-               [Tested]
-               public override MSG.IEnumerator<T> GetEnumerator()
-               {
-                       Node cursor = startsentinel.next;
-                       int startstamp = this.stamp;
-
-                       while (cursor != endsentinel)
-                       {
-                               modifycheck(startstamp);
-                               yield return cursor.item;
-                               cursor = cursor.next;
-                       }
-               }
-
-               #endregion
-
-               #region ISink<T> Members
-               /// <summary>
-               /// Add an item to this collection if possible. 
-               /// </summary>
-               /// <param name="item">The item to add.</param>
-               /// <returns>True.</returns>
-               [Tested]
-               public virtual bool Add(T item)
-               {
-                       updatecheck();
-                       insert(endsentinel, item);
-                       return true;
-               }
-
-
-               /// <summary>
-               /// 
-               /// </summary>
-               /// <value>True since this collection has bag semantics.</value>
-               [Tested]
-               public virtual bool AllowsDuplicates { [Tested]get { return true; } }
-
-
-               /// <summary>
-               /// Add the elements from another collection to this collection. 
-               /// </summary>
-               /// <param name="items">The items to add.</param>
-               [Tested]
-               public virtual void AddAll(MSG.IEnumerable<T> items) { InsertAll(size, items); }
-
-        /// <summary>
-        /// Add the elements from another collection with a more specialized item type 
-        /// to this collection. 
-        /// </summary>
-        /// <typeparam name="U">The type of items to add</typeparam>
-        /// <param name="items">The items to add</param>
-        public virtual void AddAll<U>(MSG.IEnumerable<U> items) where U : T
-        {
-            //TODO: implement
-        }
-
-
-               #endregion
-
-        #region IStack<T> Members
-
-        /// <summary>
-        /// Push an item to the top of the stack.
-        /// </summary>
-        /// <param name="item">The item</param>
-        [Tested]
-        public void Push(T item)
-        {
-            Add(item);
-        }
-
-        /// <summary>
-        /// Pop the item at the top of the stack from the stack.
-        /// </summary>
-        /// <returns>The popped item.</returns>
-        [Tested]
-        public T Pop()
-        {
-            return RemoveLast();
-        }
-
-         #endregion
-
-        #region IQueue<T> Members
-
-        /// <summary>
-        /// Enqueue an item at the back of the queue. 
-        /// </summary>
-        /// <param name="item">The item</param>
-        [Tested]
-        public void EnQueue(T item)
-        {
-            Add(item);
-        }
-
-        /// <summary>
-        /// Dequeue an item from the front of the queue.
-        /// </summary>
-        /// <returns>The item</returns>
-        [Tested]
-        public T DeQueue()
-        {
-            return RemoveFirst();
-        }
-
-         #endregion
-        
-        #region Diagnostic
-
-        /// <summary>
-               /// Check the sanity of this list
-               /// </summary>
-               /// <returns>true if sane</returns>
-               [Tested]
-               public virtual bool Check()
-               {
-                       bool retval = true;
-
-                       if (underlying != null && underlying.stamp != stamp)
-                       {
-                               Console.WriteLine("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp);
-                               retval = false;
-                       }
-
-                       if (startsentinel == null)
-                       {
-                               Console.WriteLine("startsentinel == null");
-                               retval = false;
-                       }
-
-                       if (endsentinel == null)
-                       {
-                               Console.WriteLine("endsentinel == null");
-                               retval = false;
-                       }
-
-                       if (size == 0)
-                       {
-                               if (startsentinel != null && startsentinel.next != endsentinel)
-                               {
-                                       Console.WriteLine("size == 0 but startsentinel.next != endsentinel");
-                                       retval = false;
-                               }
-
-                               if (endsentinel != null && endsentinel.prev != startsentinel)
-                               {
-                                       Console.WriteLine("size == 0 but endsentinel.prev != startsentinel");
-                                       retval = false;
-                               }
-                       }
-
-                       if (startsentinel == null)
-                               return retval;
-
-                       int count = 0;
-                       Node node = startsentinel.next, prev = startsentinel;
-#if EXTLISTORDER
-                       int taggroupsize = 0, oldtaggroupsize = losize + 1, seentaggroups = 0;
-                       TagGroup oldtg = null;
-
-                       if (maintaintags && underlying == null)
-                       {
-                               TagGroup tg = startsentinel.taggroup;
-
-                               if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MinValue)
-                               {
-                                       Console.WriteLine("Bad startsentinel tag group: {0}", tg);
-                                       retval = false;
-                               }
-
-                               tg = endsentinel.taggroup;
-                               if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MaxValue)
-                               {
-                                       Console.WriteLine("Bad endsentinel tag group: {0}", tg);
-                                       retval = false;
-                               }
-                       }
-#endif
-                       while (node != endsentinel)
-                       {
-                               count++;
-                               if (node.prev != prev)
-                               {
-                                       Console.WriteLine("Bad backpointer at node {0}", count);
-                                       retval = false;
-                               }
-#if LISTORDER
-                               if (maintaintags && node.prev.tag >= node.tag)
-                               {
-                                       Console.WriteLine("node.prev.tag ({0}) >= node.tag ({1}) at index={2} item={3} ", node.prev.tag, node.tag, count, node.item);
-                                       retval = false;
-                               }
-#elif EXTLISTORDER
-                               if (maintaintags && underlying == null)
-                               {
-                                       if (!node.prev.precedes(node))
-                                       {
-                                               Console.WriteLine("node.prev.tag ({0}, {1}) >= node.tag ({2}, {3}) at index={4} item={5} ", node.prev.taggroup.tag, node.prev.tag, node.taggroup.tag, node.tag, count, node.item);
-                                               retval = false;
-                                       }
-
-                                       if (node.taggroup != oldtg)
-                                       {
-                                               if (oldtg != null)
-                                               {
-                                                       if (oldtg.count != taggroupsize)
-                                                       {
-                                                               Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
-                                                               retval = false;
-                                                       }
-
-                                                       if (oldtaggroupsize <= losize && taggroupsize <= losize)
-                                                       {
-                                                               Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
-                                                               retval = false;
-                                                       }
-
-                                                       oldtaggroupsize = taggroupsize;
-                                               }
-
-                                               seentaggroups++;
-                                               oldtg = node.taggroup;
-                                               taggroupsize = 1;
-                                       }
-                                       else
-                                       {
-                                               taggroupsize++;
-                                       }
-                               }
-#endif
-                               prev = node;
-                               node = node.next;
-                               if (node == null)
-                               {
-                                       Console.WriteLine("Null next pointer at node {0}", count);
-                                       return false;
-                               }
-                       }
-
-#if EXTLISTORDER
-                       if (maintaintags && underlying == null && size > 0)
-                       {
-                               oldtg = node.prev.taggroup;
-                               if (oldtg != null)
-                               {
-                                       if (oldtg.count != taggroupsize)
-                                       {
-                                               Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
-                                               retval = false;
-                                       }
-
-                                       if (oldtaggroupsize <= losize && taggroupsize <= losize)
-                                       {
-                                               Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
-                                               retval = false;
-                                       }
-                               }
-
-                               if (seentaggroups != taggroups)
-                               {
-                                       Console.WriteLine("seentaggroups ({0}) != taggroups ({1}) (at size {2})", seentaggroups, taggroups, size);
-                                       retval = false;
-                               }
-                       }
-#endif
-                       if (count != size)
-                       {
-                               Console.WriteLine("size={0} but enumeration gives {1} nodes ", size, count);
-                               retval = false;
-                       }
-
-                       return retval;
-               }
-
-               #endregion      
-       }
-}
-#endif
diff --git a/mcs/class/Mono.C5/trees/RedBlackTree.cs b/mcs/class/Mono.C5/trees/RedBlackTree.cs
deleted file mode 100644 (file)
index daca84a..0000000
+++ /dev/null
@@ -1,4329 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-#define MAINTAIN_SIZE\r
-#define MAINTAIN_RANKnot\r
-#define MAINTAIN_HEIGHTnot\r
-#define BAGnot\r
-#define NCP\r
-\r
-#define MAINTAIN_EXTREMAnot\r
-#define TRACE_IDnot\r
-\r
-#if BAG\r
-#if !MAINTAIN_SIZE\r
-#error  BAG defined without MAINTAIN_SIZE!\r
-#endif\r
-#endif\r
-\r
-\r
-using System;\r
-using MSG = System.Collections.Generic;\r
-using SC = System.Collections;\r
-\r
-// NOTE NOTE NOTE NOTE\r
-// This source file is used to produce both TreeSet<T> and TreeBag<T>\r
-// It should be copied to a file called TreeBag.cs in which all code mentions of \r
-// TreeSet is changed to TreeBag and the preprocessor symbol BAG is defined.\r
-// NOTE: there may be problems with documentation comments.\r
-\r
-namespace C5\r
-{\r
-#if BAG\r
-       /// <summary>\r
-       /// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics,\r
-       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. (<see cref="T:C5.TreeSet!1"/> for an \r
-       /// implementation with set semantics).\r
-       /// <br/>\r
-       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
-       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
-       /// be external and supplied by the user in the constructor.\r
-       /// <br/>\r
-       /// Each distinct item is only kept in one place in the tree - together with the number\r
-       /// of times it is a member of the bag. Thus, if two items that are equal according\r
-       /// </summary>\r
-#else\r
-       /// <summary>\r
-       /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics,\r
-       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. <see cref="T:C5.TreeBag!1"/> for a version \r
-       /// with bag semantics. <see cref="T:C5.TreeDictionary!2"/> for a sorted dictionary \r
-       /// based on this tree implementation.\r
-       /// <p>\r
-       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
-       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
-       /// be external and supplied by the user in the constructor.</p>\r
-       ///\r
-       /// <p><i>TODO: describe performance here</i></p>\r
-       /// <p><i>TODO: discuss persistence and its useful usage modes. Warn about the space\r
-       /// leak possible with other usage modes.</i></p>\r
-       /// </summary>\r
-#endif\r
-       public class TreeSet<T>: SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>\r
-       {\r
-               #region Feature\r
-               /// <summary>\r
-               /// A debugging aid for making the selected compilation alternatives \r
-               /// available to the user. (To be removed when selection is finally fixed\r
-               /// for production version).\r
-               /// </summary>\r
-               [Flags]\r
-               public enum Feature: short\r
-               {\r
-                       /// <summary>\r
-                       /// Nothing\r
-                       /// </summary>\r
-                       Dummy = 0,\r
-                       /// <summary>\r
-                       /// Node copy persistence as explained in <a href="litterature.htm#Tarjan1">Tarjan1</a>\r
-                       /// </summary>\r
-                       NodeCopyPersistence = 2,\r
-                       /// <summary>\r
-                       /// Maintain sub tree sizes\r
-                       /// </summary>\r
-                       Sizes = 4,\r
-                       /// <summary>\r
-                       /// Maintain precise node heights\r
-                       /// </summary>\r
-                       Heights = 8,\r
-                       /// <summary>\r
-                       /// Maintain node ranks (~ black height)\r
-                       /// </summary>\r
-                       Ranks = 16,\r
-                       /// <summary>\r
-                       /// Maintain unique ids on tree nodes.\r
-                       /// </summary>\r
-                       Traceid = 32\r
-               }\r
-\r
-\r
-\r
-               static Feature features = Feature.Dummy\r
-#if NCP\r
-               | Feature.NodeCopyPersistence\r
-#endif\r
-#if MAINTAIN_RANK\r
-                       |Feature.Ranks\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                       |Feature.Heights\r
-#endif\r
-#if MAINTAIN_SIZE\r
-               | Feature.Sizes\r
-#endif\r
-#if TRACE_ID\r
-               | Feature.Traceid\r
-#endif\r
-               ;\r
-\r
-\r
-               /// <summary>\r
-               /// A debugging aid for making the selected compilation alternatives \r
-               /// available to the user. (To be removed when selection is finally fixed\r
-               /// for production version).\r
-               /// </summary>\r
-               public static Feature Features { get { return features; } }\r
-\r
-               #endregion\r
-\r
-               #region Fields\r
-\r
-               IComparer<T> comparer;\r
-\r
-               Node root;\r
-\r
-               int blackdepth = 0;\r
-\r
-               //We double these stacks for the iterative add and remove on demand\r
-               private int[] dirs = new int[2];\r
-\r
-               private Node[] path = new Node[2];\r
-#if NCP\r
-               private bool isSnapShot = false;\r
-\r
-               private SnapData snapdata;\r
-\r
-               private int generation;\r
-\r
-               private int maxsnapid = -1;\r
-\r
-#endif\r
-#if MAINTAIN_EXTREMA\r
-               T min, max;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-               private short depth = 0;\r
-#endif\r
-               #endregion\r
-\r
-               #region Util\r
-\r
-               /// <summary>\r
-               /// Fetch the left child of n taking node-copying persistence into\r
-               /// account if relevant. \r
-               /// </summary>\r
-               /// <param name="n"></param>\r
-               /// <returns></returns>\r
-               private Node left(Node n)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                       {\r
-#if SEPARATE_EXTRA\r
-                               Node.Extra e = n.extra;\r
-\r
-                               if (e != null && e.lastgeneration >= treegen && e.leftnode)\r
-                                       return e.oldref;\r
-#else\r
-                               if (n.lastgeneration >= generation && n.leftnode)\r
-                                       return n.oldref;\r
-#endif\r
-                       }\r
-#endif\r
-                       return n.left;\r
-               }\r
-\r
-\r
-               private Node right(Node n)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                       {\r
-#if SEPARATE_EXTRA\r
-                               Node.Extra e = n.extra;\r
-\r
-                               if (e != null && e.lastgeneration >= treegen && !e.leftnode)\r
-                                       return e.oldref;\r
-#else\r
-                               if (n.lastgeneration >= generation && !n.leftnode)\r
-                                       return n.oldref;\r
-#endif\r
-                       }\r
-#endif\r
-                       return n.right;\r
-               }\r
-\r
-\r
-               //This method should be called by methods that use the internal \r
-               //traversal stack, unless certain that there is room enough\r
-               private void stackcheck()\r
-               {\r
-                       while (dirs.Length < 2 * blackdepth)\r
-                       {\r
-                               dirs = new int[2 * dirs.Length];\r
-                               path = new Node[2 * dirs.Length];\r
-                       }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Node nested class\r
-                       \r
-\r
-               /// <summary>\r
-               /// The type of node in a Red-Black binary tree\r
-               /// </summary>\r
-               class Node\r
-               {\r
-                       public bool red = true;\r
-\r
-                       public T item;\r
-\r
-                       public Node left;\r
-\r
-                       public Node right;\r
-\r
-#if MAINTAIN_SIZE\r
-                       public int size = 1;\r
-#endif\r
-\r
-#if BAG\r
-                       public int items = 1;\r
-#endif\r
-\r
-#if MAINTAIN_HEIGHT\r
-                       public short height; \r
-#endif\r
-\r
-#if MAINTAIN_RANK\r
-                       public short rank = 1;\r
-#endif\r
-\r
-#if TRACE_ID\r
-                       public int id = sid++;\r
-                       public static int sid = 0;\r
-#endif\r
-\r
-#if NCP\r
-                       public int generation;\r
-#if SEPARATE_EXTRA\r
-                       internal class Extra\r
-                       {\r
-                               public int lastgeneration;\r
-\r
-                               public Node oldref;\r
-\r
-                               public bool leftnode;\r
-\r
-                               //public Node next;\r
-                       }\r
-\r
-                       public Extra extra;\r
-\r
-#else\r
-                       public int lastgeneration = -1;\r
-\r
-                       public Node oldref;\r
-\r
-                       public bool leftnode;\r
-#endif\r
-\r
-                       /// <summary>\r
-                       /// Update a child pointer\r
-                       /// </summary>\r
-                       /// <param name="cursor"></param>\r
-                       /// <param name="leftnode"></param>\r
-                       /// <param name="child"></param>\r
-                       /// <param name="maxsnapid"></param>\r
-                       /// <param name="generation"></param>\r
-                       /// <returns>True if node was *copied*</returns>\r
-                       internal static bool update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation)\r
-                       {\r
-                               Node oldref = leftnode ? cursor.left : cursor.right;\r
-\r
-                               if (child == oldref)\r
-                                       return false;\r
-\r
-                               bool retval = false;\r
-\r
-                               if (cursor.generation <= maxsnapid)\r
-                               { \r
-#if SEPARATE_EXTRA\r
-                                       if (cursor.extra == null)\r
-                                       {\r
-                                               Extra extra = cursor.extra = new Extra();       \r
-\r
-                                               extra.leftnode = leftnode;\r
-                                               extra.lastgeneration = maxsnapid;\r
-                                               extra.oldref = oldref;\r
-                                       }\r
-                                       else if (cursor.extra.leftnode != leftnode || cursor.extra.lastgeneration < maxsnapid)\r
-#else\r
-                                       if (cursor.lastgeneration == -1)\r
-                                       {\r
-                                               cursor.leftnode = leftnode;\r
-                                               cursor.lastgeneration = maxsnapid;\r
-                                               cursor.oldref = oldref;\r
-                                       }\r
-                                       else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid)\r
-#endif\r
-                                       {\r
-                                               CopyNode(ref cursor, maxsnapid, generation);\r
-                                               retval = true;\r
-                                       }\r
-                               }\r
-\r
-                               if (leftnode)\r
-                                       cursor.left = child;\r
-                               else\r
-                                       cursor.right = child;\r
-\r
-                               return retval;\r
-                       }\r
-\r
-\r
-                       //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will \r
-                       //always be used in the old copy of cursor. Therefore, after \r
-                       //making the clone, we should update the old copy by restoring\r
-                       //the child pointer and setting extra to null.\r
-                       //OTOH then we cannot clean up unused Extra objects unless we link\r
-                       //them together in a doubly linked list.\r
-                       public static bool CopyNode(ref Node cursor, int maxsnapid, int generation)\r
-                       {\r
-                               if (cursor.generation <= maxsnapid)\r
-                               {\r
-                                       cursor = (Node)(cursor.MemberwiseClone());\r
-                                       cursor.generation = generation;\r
-#if SEPARATE_EXTRA\r
-                                       cursor.extra = null;\r
-#else\r
-                                       cursor.lastgeneration = -1;\r
-#endif\r
-#if TRACE_ID\r
-                                       cursor.id = sid++;\r
-#endif\r
-                                       return true;\r
-                               }\r
-                               else\r
-                                       return false;\r
-                       }\r
-\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-                       \r
-               /// <summary>\r
-               /// Create a red-black tree collection with natural comparer and item hasher.\r
-               /// </summary>\r
-               public TreeSet()\r
-               {\r
-                       comparer = ComparerBuilder.FromComparable<T>.Examine();\r
-                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a red-black tree collection with an external comparer (and natural item hasher,\r
-               /// assumed consistent).\r
-               /// </summary>\r
-               /// <param name="c">The external comparer</param>\r
-               public TreeSet(IComparer<T> c)\r
-               {\r
-                       comparer = c;\r
-                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a red-black tree collection with an external comparer aand an external\r
-               /// item hasher, assumed consistent.\r
-               /// </summary>\r
-               /// <param name="c">The external comparer</param>\r
-               /// <param name="h">The external item hasher</param>\r
-               public TreeSet(IComparer<T> c, IHasher<T> h)\r
-               {\r
-                       comparer = c;\r
-                       itemhasher = h;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region TreeSet.Enumerator nested class\r
-\r
-               /// <summary>\r
-               /// An enumerator for a red-black tree collection. Based on an explicit stack\r
-               /// of subtrees waiting to be enumerated. Currently only used for the tree set \r
-               /// enumerators (tree bag enumerators use an iterator block based enumerator).\r
-               /// </summary>\r
-               public class Enumerator: MSG.IEnumerator<T>\r
-               {\r
-                       #region Private Fields\r
-                       TreeSet<T> tree;\r
-\r
-                       bool valid = false;\r
-\r
-                       int stamp;\r
-\r
-                       T current;\r
-\r
-                       Node cursor;\r
-\r
-                       Node[] path; // stack of nodes\r
-\r
-                       int level = 0;\r
-                       #endregion\r
-                       /// <summary>\r
-                       /// Create a tree enumerator\r
-                       /// </summary>\r
-                       /// <param name="tree">The red-black tree to enumerate</param>\r
-                       public Enumerator(TreeSet<T> tree)\r
-                       {\r
-                               this.tree = tree;\r
-                               stamp = tree.stamp;\r
-                               path = new Node[2 * tree.blackdepth];\r
-                               cursor = new Node();\r
-                               cursor.right = tree.root;\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
-                       /// </summary>\r
-                       /// <value>The current item of the enumerator.</value>\r
-                       [Tested]\r
-                       public T Current\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       if (valid)\r
-                                               return current;\r
-                                       else\r
-                                               throw new InvalidOperationException();\r
-                               }\r
-                       }\r
-\r
-\r
-                       //Maintain a stack of nodes that are roots of\r
-                       //subtrees not completely exported yet. Invariant:\r
-                       //The stack nodes together with their right subtrees\r
-                       //consists of exactly the items we have not passed\r
-                       //yet (the top of the stack holds current item).\r
-                       /// <summary>\r
-                       /// Move enumerator to next item in tree, or the first item if\r
-                       /// this is the first call to MoveNext. \r
-                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
-                       /// </summary>\r
-                       /// <returns>True if enumerator is valid now</returns>\r
-                       [Tested]\r
-                       public bool MoveNext()\r
-                       {\r
-                               tree.modifycheck(stamp);\r
-                               if (cursor.right != null)\r
-                               {\r
-                                       path[level] = cursor = cursor.right;\r
-                                       while (cursor.left != null)\r
-                                               path[++level] = cursor = cursor.left;\r
-                               }\r
-                               else if (level == 0)\r
-                                       return valid = false;\r
-                               else\r
-                                       cursor = path[--level];\r
-\r
-                               current = cursor.item;\r
-                               return valid = true;\r
-                       }\r
-\r
-\r
-                       #region IDisposable Members for Enumerator\r
-\r
-                       bool disposed;\r
-\r
-\r
-                       /// <summary>\r
-                       /// Call Dispose(true) and then suppress finalization of this enumerator.\r
-                       /// </summary>\r
-                       [Tested]\r
-                       public void Dispose()\r
-                       {\r
-                               Dispose(true);\r
-                               GC.SuppressFinalize(this);\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Remove the internal data (notably the stack array).\r
-                       /// </summary>\r
-                       /// <param name="disposing">True if called from Dispose(),\r
-                       /// false if called from the finalizer</param>\r
-                       protected virtual void Dispose(bool disposing)\r
-                       {\r
-                               if (!disposed)\r
-                               {\r
-                                       if (disposing)\r
-                                       {\r
-                                       }\r
-\r
-                                       current = default(T);\r
-                                       cursor = null;\r
-                                       path = null;\r
-                                       disposed = true;\r
-                               }\r
-                       }\r
-\r
-                       void SC.IEnumerator.Reset ()\r
-                       {\r
-                               throw new NotImplementedException ();\r
-                       }\r
-\r
-                       object SC.IEnumerator.Current {\r
-                               get {\r
-                                       return Current;\r
-                               }\r
-                       }\r
-\r
-                       /// <summary>\r
-                       /// Finalizer for enumeratir\r
-                       /// </summary>\r
-                       ~Enumerator()\r
-                       {\r
-                               Dispose(false);\r
-                       }\r
-                       #endregion\r
-\r
-               }\r
-#if NCP\r
-               /// <summary>\r
-               /// An enumerator for a snapshot of a node copy persistent red-black tree\r
-               /// collection.\r
-               /// </summary>\r
-               public class SnapEnumerator: MSG.IEnumerator<T>\r
-               {\r
-                       #region Private Fields\r
-                       TreeSet<T> tree;\r
-\r
-                       bool valid = false;\r
-\r
-                       int stamp;\r
-#if BAG\r
-                       int togo;\r
-#endif\r
-\r
-                       T current;\r
-\r
-                       Node cursor;\r
-\r
-                       Node[] path; // stack of nodes\r
-\r
-                       int level;\r
-                       #endregion\r
-\r
-                       /// <summary>\r
-                       /// Creta an enumerator for a snapshot of a node copy persistent red-black tree\r
-                       /// collection\r
-                       /// </summary>\r
-                       /// <param name="tree">The snapshot</param>\r
-                       public SnapEnumerator(TreeSet<T> tree)\r
-                       {\r
-                               this.tree = tree;\r
-                               stamp = tree.stamp;\r
-                               path = new Node[2 * tree.blackdepth];\r
-                               cursor = new Node();\r
-                               cursor.right = tree.root;\r
-                       }\r
-\r
-\r
-                       #region MSG.IEnumerator<T> Members\r
-\r
-                       /// <summary>\r
-                       /// Move enumerator to next item in tree, or the first item if\r
-                       /// this is the first call to MoveNext. \r
-                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
-                       /// </summary>\r
-                       /// <returns>True if enumerator is valid now</returns>\r
-                       [Tested]\r
-                       public bool MoveNext()\r
-                       {\r
-                               tree.modifycheck(stamp);//???\r
-\r
-#if BAG\r
-                               if (--togo>0)\r
-                                       return true;\r
-#endif\r
-                               Node next = tree.right(cursor);\r
-\r
-                               if (next != null)\r
-                               {\r
-                                       path[level] = cursor = next;\r
-                                       next = tree.left(cursor);\r
-                                       while (next != null)\r
-                                       {\r
-                                               path[++level] = cursor = next;\r
-                                               next = tree.left(cursor);\r
-                                       }\r
-                               }\r
-                               else if (level == 0)\r
-                                       return valid = false;\r
-                               else\r
-                                       cursor = path[--level];\r
-\r
-#if BAG\r
-                               togo = cursor.items;\r
-#endif\r
-                               current = cursor.item;\r
-                               return valid = true;\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
-                       /// </summary>\r
-                       /// <value>The current value of the enumerator.</value>\r
-                       [Tested]\r
-                       public T Current\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       if (valid)\r
-                                               return current;\r
-                                       else\r
-                                               throw new InvalidOperationException();\r
-                               }\r
-                       }\r
-\r
-                       #endregion\r
-\r
-                       void SC.IEnumerator.Reset ()\r
-                       {\r
-                               throw new NotImplementedException ();\r
-                       }\r
-\r
-                       object SC.IEnumerator.Current {\r
-                               get {\r
-                                       return Current;\r
-                               }\r
-                       }\r
-\r
-                       #region IDisposable Members\r
-\r
-                       [Tested]\r
-                       void System.IDisposable.Dispose()\r
-                       {\r
-                               tree = null;\r
-                               valid = false;\r
-                               current = default(T);\r
-                               cursor = null;\r
-                               path = null;\r
-                       }\r
-\r
-                       #endregion\r
-               }\r
-#endif\r
-               #endregion\r
-\r
-               #region IEnumerable<T> Members\r
-\r
-               private MSG.IEnumerator<T> getEnumerator(Node node, int origstamp)\r
-               {\r
-                       if (node == null)\r
-                               yield break;\r
-\r
-                       if (node.left != null)\r
-                       {\r
-                               MSG.IEnumerator<T> child = getEnumerator(node.left, origstamp);\r
-\r
-                               while (child.MoveNext())\r
-                               {\r
-                                       modifycheck(origstamp);\r
-                                       yield return child.Current;\r
-                               }\r
-                       }\r
-#if BAG\r
-                       int togo = node.items;\r
-                       while (togo-- > 0)\r
-                       {\r
-                               modifycheck(origstamp);\r
-                               yield return node.item;\r
-                       }\r
-#else\r
-                       modifycheck(origstamp);\r
-                       yield return node.item;\r
-#endif\r
-                       if (node.right != null)\r
-                       {\r
-                               MSG.IEnumerator<T> child = getEnumerator(node.right, origstamp);\r
-\r
-                               while (child.MoveNext())\r
-                               {\r
-                                       modifycheck(origstamp);\r
-                                       yield return child.Current;\r
-                               }\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an enumerator for this tree\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               [Tested]\r
-               public override MSG.IEnumerator<T> GetEnumerator()\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               return new SnapEnumerator(this);\r
-#endif\r
-#if BAG\r
-                       return getEnumerator(root,stamp);\r
-#else\r
-                       return new Enumerator(this);\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-                       \r
-               /// <summary>\r
-               /// Add item to tree. If already there, return the found item in the second argument.\r
-               /// </summary>\r
-               /// <param name="item">Item to add</param>\r
-        /// <param name="founditem">item found</param>\r
-        /// <param name="update">whether item in node should be updated</param>\r
-        /// <param name="wasfound">true if found in bag, false if not found or tre is a set</param>\r
-        /// <returns>True if item was added</returns>\r
-        bool addIterative(T item, ref T founditem, bool update, out bool wasfound)\r
-        {\r
-            wasfound = false;\r
-            if (root == null)\r
-                       {\r
-                               root = new Node();\r
-                               root.red = false;\r
-                               blackdepth = 1;\r
-#if MAINTAIN_EXTREMA\r
-                               root.item = min = max = item;\r
-#else\r
-                               root.item = item;\r
-#endif\r
-#if NCP\r
-                               root.generation = generation;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = 0;\r
-#endif\r
-                               return true;\r
-                       }\r
-\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (true)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp == 0)\r
-                               {\r
-                    founditem = cursor.item;\r
-\r
-#if BAG\r
-                    wasfound = true;\r
-#if NCP\r
-                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                                       cursor.items++;\r
-                                       cursor.size++;\r
-                                       if (update)\r
-                                               cursor.item = item;\r
-\r
-                                       update = true;\r
-\r
-#else\r
-                    if (update)\r
-                    {\r
-#if NCP\r
-                        Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                        cursor.item = item;\r
-                    }\r
-#endif\r
-\r
-                    while (level-- > 0)\r
-                    {\r
-                        if (update)\r
-                                               {\r
-                                                       Node kid = cursor;\r
-\r
-                                                       cursor = path[level];\r
-#if NCP\r
-                                                       Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
-#endif\r
-#if BAG\r
-                                                       cursor.size++;\r
-#endif\r
-                                               }\r
-\r
-                                               path[level] = null;\r
-                                       }\r
-#if BAG\r
-                                       return true;\r
-#else\r
-                                       if (update)\r
-                                               root = cursor;\r
-\r
-                                       return false;\r
-#endif\r
-                               }\r
-\r
-                               //else\r
-                               Node child = comp > 0 ? cursor.left : cursor.right;\r
-\r
-                               if (child == null)\r
-                               {\r
-                                       child = new Node();\r
-                                       child.item = item;\r
-#if NCP\r
-                                       child.generation = generation;\r
-                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
-#else\r
-                                       if (comp > 0) { cursor.left = child; }\r
-                                       else { cursor.right = child; }\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                                       cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                                       dirs[level] = comp;\r
-                                       break;\r
-                               }\r
-                               else\r
-                               {\r
-                                       dirs[level] = comp;\r
-                                       path[level++] = cursor;\r
-                                       cursor = child;\r
-                               }\r
-                       }\r
-\r
-                       //We have just added the red node child to "cursor"\r
-                       while (cursor.red)\r
-                       {\r
-                               //take one step up:\r
-                               Node child = cursor;\r
-\r
-                               cursor = path[--level];\r
-                               path[level] = null;\r
-#if NCP\r
-                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                               cursor.size++;\r
-#endif\r
-                               int comp = dirs[level];\r
-                               Node childsibling = comp > 0 ? cursor.right : cursor.left;\r
-\r
-                               if (childsibling != null && childsibling.red)\r
-                               {\r
-                                       //Promote\r
-#if MAINTAIN_RANK\r
-                                       cursor.rank++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                                       child.red = false;\r
-#if NCP\r
-                                       Node.update(ref cursor, comp < 0, childsibling, maxsnapid, generation);\r
-#endif\r
-                                       childsibling.red = false;\r
-\r
-                                       //color cursor red & take one step up the tree unless at root\r
-                                       if (level == 0)\r
-                                       {\r
-                                               root = cursor;\r
-                                               blackdepth++;\r
-                                               return true;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               cursor.red = true;\r
-#if NCP\r
-                                               child = cursor;\r
-                                               cursor = path[--level];\r
-                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-                                               path[level] = null;\r
-#if MAINTAIN_SIZE\r
-                                               cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       //ROTATE!!!\r
-                                       int childcomp = dirs[level + 1];\r
-\r
-                                       cursor.red = true;\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               if (childcomp > 0)\r
-                                               {//zagzag\r
-#if NCP\r
-                                                       Node.update(ref cursor, true, child.right, maxsnapid, generation);\r
-                                                       Node.update(ref child, false, cursor, maxsnapid, generation);\r
-#else\r
-                                                       cursor.left = child.right;\r
-                                                       child.right = cursor;\r
-#endif\r
-                                                       cursor = child;\r
-                                               }\r
-                                               else\r
-                                               {//zagzig\r
-                                                       Node badgrandchild = child.right;\r
-#if NCP\r
-                                                       Node.update(ref cursor, true, badgrandchild.right, maxsnapid, generation);\r
-                                                       Node.update(ref child, false, badgrandchild.left, maxsnapid, generation);\r
-                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
-#else\r
-                                                       cursor.left = badgrandchild.right;\r
-                                                       child.right = badgrandchild.left;\r
-#endif\r
-                                                       badgrandchild.left = child;\r
-                                                       badgrandchild.right = cursor;\r
-                                                       cursor = badgrandchild;\r
-                                               }\r
-                                       }\r
-                                       else\r
-                                       {//comp < 0\r
-                                               if (childcomp < 0)\r
-                                               {//zigzig\r
-#if NCP\r
-                                                       Node.update(ref cursor, false, child.left, maxsnapid, generation);\r
-                                                       Node.update(ref child, true, cursor, maxsnapid, generation);\r
-#else\r
-                                                       cursor.right = child.left;\r
-                                                       child.left = cursor;\r
-#endif\r
-                                                       cursor = child;\r
-                                               }\r
-                                               else\r
-                                               {//zigzag\r
-                                                       Node badgrandchild = child.left;\r
-#if NCP\r
-                                                       Node.update(ref cursor, false, badgrandchild.left, maxsnapid, generation);\r
-                                                       Node.update(ref child, true, badgrandchild.right, maxsnapid, generation);\r
-                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
-#else\r
-                                                       cursor.right = badgrandchild.left;\r
-                                                       child.left = badgrandchild.right;\r
-#endif\r
-                                                       badgrandchild.right = child;\r
-                                                       badgrandchild.left = cursor;\r
-                                                       cursor = badgrandchild;\r
-                                               }\r
-                                       }\r
-\r
-                                       cursor.red = false;\r
-\r
-#if MAINTAIN_SIZE\r
-                                       Node n;\r
-\r
-#if BAG\r
-                                       n = cursor.right;\r
-                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
-                                       n = cursor.left;\r
-                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
-                                       cursor.size += n.size + cursor.items;\r
-#else\r
-                                       n = cursor.right;\r
-                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
-                                       n = cursor.left;\r
-                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
-                                       cursor.size += n.size + 1;\r
-#endif\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor.right);\r
-                                       fixheight(cursor.left);\r
-                                       fixheight(cursor);\r
-#endif\r
-                                       if (level == 0)\r
-                                       {\r
-                                               root = cursor;\r
-                                               return true;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               child = cursor;\r
-                                               cursor = path[--level];\r
-                                               path[level] = null;\r
-#if NCP\r
-                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#else\r
-                                               if (dirs[level] > 0)\r
-                                                       cursor.left = child;\r
-                                               else\r
-                                                       cursor.right = child;\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                                               cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(cursor);\r
-#endif\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       }\r
-#if NCP\r
-                       bool stillmore = true;\r
-#endif\r
-                       while (level > 0)\r
-                       {\r
-                               Node child = cursor;\r
-\r
-                               cursor = path[--level];\r
-                               path[level] = null;\r
-#if NCP\r
-                               if (stillmore)\r
-                                       stillmore = Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                               cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               fixheight(cursor);\r
-#endif\r
-                       }\r
-\r
-                       root = cursor;\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to this collection if possible. If this collection has set\r
-               /// semantics, the item will be added if not already in the collection. If\r
-               /// bag semantics, the item will always be added.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True if item was added.</returns>\r
-               [Tested]\r
-               public bool Add(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       //Note: blackdepth of the tree is set inside addIterative\r
-                       T j = default(T);\r
-            bool tmp;\r
-\r
-            if (addIterative(item, ref j, false, out tmp))\r
-                       {\r
-                               size++;\r
-#if MAINTAIN_EXTREMA\r
-                               if (Compare(item, min) < 0)\r
-                                       min = item;\r
-                               else if (Compare(item, max) > 0)\r
-                                       max = item;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = root.height;\r
-#endif\r
-                               return true;\r
-                       }\r
-                       else\r
-                               return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add the elements from another collection to this collection. If this\r
-               /// collection has set semantics, only items not already in the collection\r
-               /// will be added.\r
-               /// </summary>\r
-               /// <param name="items">The items to add.</param>\r
-               [Tested]\r
-               public void AddAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       int c = 0;\r
-                       T j = default(T);\r
-            bool tmp;\r
-\r
-            updatecheck();\r
-                       foreach (T i in items)\r
-                               if (addIterative(i, ref j, false, out tmp)) c++;\r
-\r
-                       size += c;\r
-               }\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. If this\r
-        /// collection has set semantics, only items not already in the collection\r
-        /// will be added.\r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
-        {\r
-            int c = 0;\r
-            T j = default(T);\r
-            bool tmp;\r
-\r
-            updatecheck();\r
-            foreach (T i in items)\r
-                if (addIterative(i, ref j, false, out tmp)) c++;\r
-\r
-            size += c;\r
-        }\r
-\r
-\r
-        /// <summary>\r
-               /// Add all the items from another collection with an enumeration order that \r
-               /// is increasing in the items. <para>The idea is that the implementation may use\r
-               /// a faster algorithm to merge the two collections.</para>\r
-               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
-               /// not to be in increasing order.\r
-               /// </summary>\r
-               /// <param name="items">The collection to add.</param>\r
-               [Tested]\r
-               public void AddSorted(MSG.IEnumerable<T> items)\r
-               {\r
-                       if (size > 0)\r
-                               AddAll(items);\r
-                       else\r
-                       {\r
-                               updatecheck();\r
-                               addSorted(items, true);\r
-                       }\r
-               }\r
-\r
-               #region add-sorted helpers\r
-               \r
-               //Create a RB tree from x+2^h-1  (x < 2^h, h>=1) nodes taken from a\r
-               //singly linked list of red nodes using only the right child refs.\r
-               //The x nodes at depth h+1 will be red, the rest black.\r
-               //(h is the blackdepth of the resulting tree)\r
-               static Node maketreer(ref Node rest, int blackheight, int maxred, int red)\r
-               {\r
-                       if (blackheight == 1)\r
-                       {\r
-                               Node top = rest;\r
-\r
-                               rest = rest.right;\r
-                               if (red > 0)\r
-                               {\r
-                                       top.right = null;\r
-                                       rest.left = top;\r
-                                       top = rest;\r
-#if BAG\r
-                                       top.size += top.left.size;\r
-#elif MAINTAIN_SIZE\r
-                                       top.size = 1 + red;\r
-#endif\r
-                                       rest = rest.right;\r
-                                       red--;\r
-                               }\r
-\r
-                               if (red > 0)\r
-                               {\r
-#if BAG\r
-                                       top.size += rest.size;\r
-#endif\r
-                                       top.right = rest;\r
-                                       rest = rest.right;\r
-                                       top.right.right = null;\r
-                               }\r
-                               else\r
-                                       top.right = null;\r
-\r
-                               top.red = false;\r
-                               return top;\r
-                       }\r
-                       else\r
-                       {\r
-                               maxred >>=1;\r
-\r
-                               int lred = red > maxred ? maxred : red;\r
-                               Node left = maketreer(ref rest, blackheight - 1, maxred, lred);\r
-                               Node top = rest;\r
-\r
-                               rest = rest.right;\r
-                               top.left = left;\r
-                               top.red = false;\r
-#if MAINTAIN_RANK\r
-                               top.rank = (short)blackheight;\r
-#endif\r
-                               top.right = maketreer(ref rest, blackheight - 1, maxred, red - lred);\r
-#if BAG\r
-                               top.size = top.items + top.left.size + top.right.size;\r
-#elif MAINTAIN_SIZE\r
-                               top.size = (maxred << 1) - 1 + red;\r
-#endif\r
-                               return top;\r
-                       }\r
-               }\r
-\r
-\r
-               void addSorted(MSG.IEnumerable<T> items, bool safe)\r
-               {\r
-                       MSG.IEnumerator<T> e = items.GetEnumerator();;\r
-                       if (size > 0)\r
-                               throw new ApplicationException("This can't happen");\r
-\r
-                       if (!e.MoveNext())\r
-                               return;\r
-\r
-                       //To count theCollect \r
-                       Node head = new Node(), tail = head;\r
-                       int z = 1;\r
-                       T lastitem = tail.item = e.Current;\r
-#if BAG\r
-                       int ec=0;\r
-#endif\r
-\r
-                       while (e.MoveNext())\r
-                       {\r
-#if BAG\r
-                               T thisitem = e.Current;\r
-                               int comp = comparer.Compare(lastitem, thisitem);\r
-                               if (comp>0)\r
-                                       throw new ArgumentException("Argument not sorted");\r
-                               if (comp == 0)\r
-                               {\r
-                                       tail.items++;\r
-                                       ec++;\r
-                               }\r
-                               else\r
-                               {\r
-                                       tail.size = tail.items;\r
-                                       z++;\r
-                                       tail.right = new Node();\r
-                                       tail = tail.right;\r
-                                       lastitem = tail.item = thisitem;\r
-#if NCP\r
-                                       tail.generation = generation;\r
-#endif\r
-                               }\r
-#else\r
-                               z++;\r
-                               tail.right = new Node();\r
-                               tail = tail.right;\r
-                               tail.item = e.Current;\r
-                               if (safe)\r
-                               {\r
-                                       if (comparer.Compare(lastitem, tail.item) >= 0)\r
-                                               throw new ArgumentException("Argument not sorted");\r
-\r
-                                       lastitem = tail.item;\r
-                               }\r
-#if NCP\r
-                               tail.generation = generation;\r
-#endif\r
-#endif\r
-                       }\r
-#if BAG\r
-                       tail.size = tail.items;\r
-#endif                         \r
-                       int blackheight = 0, red = z, maxred = 1;\r
-\r
-                       while (maxred <= red)\r
-                       {\r
-                               red -= maxred;\r
-                               maxred <<= 1;\r
-                               blackheight++;\r
-                       }\r
-\r
-                       root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);\r
-                       blackdepth = blackheight;\r
-                       size = z;\r
-#if BAG\r
-                       size += ec;\r
-#endif                         \r
-                       return;\r
-               }\r
-\r
-               #endregion\r
-\r
-#if BAG\r
-               /// <summary></summary>\r
-               /// <value>True since this collection has bag semantics.</value>\r
-               [Tested]\r
-               public bool AllowsDuplicates { [Tested]get { return true; } }\r
-#else\r
-               /// <summary></summary>\r
-               /// <value>False since this tree has set semantics.</value>\r
-               [Tested]\r
-               public bool AllowsDuplicates { [Tested]get { return false; } }\r
-#endif\r
-\r
-               #endregion\r
-\r
-               #region IEditableCollection<T> Members\r
-                       \r
-\r
-               /// <summary>\r
-               /// The value is symbolic indicating the type of asymptotic complexity\r
-               /// in terms of the size of this collection (worst-case or amortized as\r
-               /// relevant).\r
-               /// </summary>\r
-               /// <value>Speed.Log</value>\r
-               [Tested]\r
-               public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }\r
-\r
-\r
-               [Tested]\r
-               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
-\r
-\r
-               [Tested]\r
-               bool ICollection<T>.Equals(ICollection<T> that)\r
-               { return unsequencedequals(that); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains (an item equivalent to according to the\r
-               /// itemhasher) a particular value.\r
-               /// </summary>\r
-               /// <param name="item">The value to check for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public bool Contains(T item)\r
-               {\r
-                       Node next; int comp = 0;\r
-\r
-                       next = root;\r
-                       while (next != null)\r
-                       {\r
-                comp = comparer.Compare(next.item, item);\r
-                if (comp == 0)\r
-                                       return true;\r
-\r
-                               next = comp < 0 ? right(next) : left(next);\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               //Variant for dictionary use\r
-               //Will return the actual matching item in the ref argument.\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public bool Find(ref T item)\r
-               {\r
-                       Node next; int comp = 0;\r
-\r
-                       next = root;\r
-                       while (next != null)\r
-                       {\r
-                comp = comparer.Compare(next.item, item);\r
-                if (comp == 0)\r
-                               {\r
-                                       item = next.item;\r
-                                       return true;\r
-                               }\r
-\r
-                               next = comp < 0 ? right(next) : left(next);\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find or add the item to the tree. If the tree does not contain\r
-               /// an item equivalent to this item add it, else return the exisiting\r
-               /// one in the ref argument. \r
-               ///\r
-               /// </summary>\r
-               /// <param name="item"></param>\r
-               /// <returns>True if item was found</returns>\r
-               [Tested]\r
-               public bool FindOrAdd(ref T item)\r
-               {\r
-                       updatecheck();\r
-            bool wasfound;\r
-\r
-            //Note: blackdepth of the tree is set inside addIterative\r
-                       if (addIterative(item, ref item, false, out wasfound))\r
-                       {\r
-                               size++;\r
-#if MAINTAIN_EXTREMA\r
-                               if (Compare(item, min) < 0)\r
-                                       min = item;\r
-                               else if (Compare(item, max) > 0)\r
-                                       max = item;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = root.height;\r
-#endif\r
-                               return wasfound;\r
-                       }\r
-                       else\r
-                               return true;\r
-\r
-               }\r
-\r
-\r
-               //For dictionary use. \r
-               //If found, the matching entry will be updated with the new item.\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
-               /// this updates all equivalent copies in\r
-               /// the collection.\r
-               /// </summary>\r
-               /// <param name="item">Value to update.</param>\r
-               /// <returns>True if the item was found and hence updated.</returns>\r
-               [Tested]\r
-               public bool Update(T item)\r
-               {\r
-                       updatecheck();\r
-#if NCP\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-#endif\r
-                       Node cursor = root;\r
-                       int comp = 0;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                comp = comparer.Compare(cursor.item, item);\r
-                if (comp == 0)\r
-                               {\r
-#if NCP\r
-                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                                       cursor.item = item;\r
-#if NCP\r
-                                       while (level > 0)\r
-                                       {\r
-                                               Node child = cursor;\r
-\r
-                                               cursor = path[--level];\r
-                                               path[level] = null;\r
-#if NCP\r
-                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#else\r
-                                               if (Node.CopyNode(maxsnapid, ref cursor, generation))\r
-                                               {\r
-                                                       if (dirs[level] > 0)\r
-                                                               cursor.left = child;\r
-                                                       else\r
-                                                               cursor.right = child;\r
-                                               }\r
-#endif\r
-                                       }\r
-\r
-                                       root = cursor;\r
-#endif\r
-                                       return true;\r
-                               }\r
-#if NCP\r
-                               dirs[level] = comp;\r
-                               path[level++] = cursor;\r
-#endif\r
-                               cursor = comp < 0 ? cursor.right : cursor.left;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value; else add the value to the collection. \r
-               ///\r
-               /// <p>NOTE: the bag implementation is currently wrong!</p>\r
-               /// </summary>\r
-               /// <param name="item">Value to add or update.</param>\r
-               /// <returns>True if the item was found and updated (hence not added).</returns>\r
-               [Tested]\r
-               public bool UpdateOrAdd(T item)\r
-               {\r
-                       updatecheck();\r
-            bool wasfound;\r
-\r
-            //Note: blackdepth of the tree is set inside addIterative\r
-                       if (addIterative(item, ref item, true, out wasfound))\r
-                       {\r
-                               size++;\r
-#if MAINTAIN_EXTREMA\r
-                               if (Compare(item, min) < 0)\r
-                                       min = item;\r
-                               else if (Compare(item, max) > 0)\r
-                                       max = item;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = root.height;\r
-#endif\r
-                               return wasfound;\r
-                       }\r
-                       else\r
-                               return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection. If the collection has bag\r
-               /// semantics only one copy equivalent to the supplied item is removed. \r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public bool Remove(T item)\r
-               {\r
-                       updatecheck();\r
-                       if (root == null)\r
-                               return false;\r
-\r
-                       return removeIterative(ref item, false);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection if found. If the collection\r
-               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
-               /// which one is implementation dependent. \r
-               /// If an item was removed, report a binary copy of the actual item removed in \r
-               /// the argument.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove on input.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public bool RemoveWithReturn(ref T item)\r
-               {\r
-                       updatecheck();\r
-                       if (root == null)\r
-                               return false;\r
-\r
-                       return removeIterative(ref item, false);\r
-               }\r
-\r
-\r
-               private bool removeIterative(ref T item, bool all)\r
-               {\r
-                       //Stage 1: find item\r
-                       stackcheck();\r
-\r
-                       int level = 0, comp;\r
-                       Node cursor = root;\r
-\r
-                       while (true)\r
-                       {\r
-                comp = comparer.Compare(cursor.item, item);\r
-                if (comp == 0)\r
-                               {\r
-                                       item = cursor.item;\r
-#if BAG\r
-                                       if (!all && cursor.items > 1)\r
-                                       {\r
-#if NCP\r
-                                               Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                                               cursor.items--;\r
-                                               cursor.size--;\r
-                                               while (level-- > 0)\r
-                                               {\r
-                                                       Node kid = cursor;\r
-\r
-                                                       cursor = path[level];\r
-#if NCP\r
-                                                       Node.update(ref cursor, dirs[level] > 0,  kid,maxsnapid,generation);\r
-#endif\r
-                                                       cursor.size--;\r
-                                                       path[level] = null;\r
-                                               }\r
-                                               size--;\r
-                                               return true;\r
-                                       }\r
-#endif\r
-                                       break;\r
-                               }\r
-\r
-                               Node child = comp > 0 ? cursor.left : cursor.right;\r
-\r
-                               if (child == null)\r
-                                       return false;\r
-\r
-                               dirs[level] = comp;\r
-                               path[level++] = cursor;\r
-                               cursor = child;\r
-                       }\r
-\r
-                       return removeIterativePhase2(cursor, level);\r
-               }\r
-\r
-\r
-               private bool removeIterativePhase2(Node cursor, int level)\r
-               {\r
-                       if (size == 1)\r
-                       {\r
-                               clear();\r
-                               return true;\r
-                       }\r
-\r
-#if MAINTAIN_EXTREMA\r
-                       if (Compare(cursor.item, min) == 0)\r
-                               min = cursor.right != null ? cursor.right.item : path[level - 1].item;\r
-                       else if (Compare(cursor.item, max) == 0)\r
-                               max = cursor.left != null ? cursor.left.item : path[level - 1].item;\r
-#endif\r
-#if BAG\r
-                       int removedcount = cursor.items;\r
-                       size -= removedcount;\r
-#else\r
-                       //We are certain to remove one node:\r
-                       size--;\r
-#endif\r
-                       //Stage 2: if item's node has no null child, find predecessor\r
-                       int level_of_item = level;\r
-\r
-                       if (cursor.left != null && cursor.right != null)\r
-                       {\r
-                               dirs[level] = 1;\r
-                               path[level++] = cursor;\r
-                               cursor = cursor.left;\r
-                               while (cursor.right != null)\r
-                               {\r
-                                       dirs[level] = -1;\r
-                                       path[level++] = cursor;\r
-                                       cursor = cursor.right;\r
-                               }\r
-#if NCP\r
-                               Node.CopyNode(ref path[level_of_item], maxsnapid, generation);\r
-#endif\r
-                               path[level_of_item].item = cursor.item;\r
-#if BAG\r
-                               path[level_of_item].items = cursor.items;\r
-#endif\r
-                       }\r
-\r
-                       //Stage 3: splice out node to be removed\r
-                       Node newchild = cursor.right == null ? cursor.left : cursor.right;\r
-                       bool demote_or_rotate = newchild == null && !cursor.red;\r
-\r
-                       //assert newchild.red \r
-                       if (newchild != null)\r
-                       {\r
-                               newchild.red = false;\r
-                       }\r
-\r
-                       if (level == 0)\r
-                       {\r
-                               root = newchild;\r
-#if MAINTAIN_HEIGHT\r
-                               depth = 0;\r
-#endif\r
-                               return true;\r
-                       }\r
-\r
-                       level--;\r
-                       cursor = path[level];\r
-                       path[level] = null;\r
-\r
-                       int comp = dirs[level];\r
-                       Node childsibling;\r
-#if NCP\r
-                       Node.update(ref cursor, comp > 0, newchild, maxsnapid, generation);\r
-#else\r
-                       if (comp > 0)\r
-                               cursor.left = newchild;\r
-                       else\r
-                               cursor.right = newchild;\r
-#endif\r
-                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
-#if BAG\r
-                       cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                       cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                       fixheight(cursor);\r
-#endif\r
-\r
-                       //Stage 4: demote till we must rotate\r
-                       Node farnephew = null, nearnephew = null;\r
-\r
-                       while (demote_or_rotate)\r
-                       {\r
-                               if (childsibling.red)\r
-                                       break; //rotate 2+?\r
-\r
-                               farnephew = comp > 0 ? childsibling.right : childsibling.left;\r
-                               if (farnephew != null && farnephew.red)\r
-                                       break; //rotate 1b\r
-\r
-                               nearnephew = comp > 0 ? childsibling.left : childsibling.right;\r
-                               if (nearnephew != null && nearnephew.red)\r
-                                       break; //rotate 1c\r
-\r
-                               //demote cursor\r
-                               childsibling.red = true;\r
-#if MAINTAIN_RANK\r
-                               cursor.rank--;\r
-#endif\r
-                               if (level == 0)\r
-                               {\r
-                                       cursor.red = false;\r
-                                       blackdepth--;\r
-#if MAINTAIN_HEIGHT\r
-                                       depth = root.height;\r
-#endif\r
-#if NCP\r
-                                       root = cursor;\r
-#endif\r
-                                       return true;\r
-                               }\r
-                               else if (cursor.red)\r
-                               {\r
-                                       cursor.red = false;\r
-                                       demote_or_rotate = false;\r
-                                       break; //No rotation\r
-                               }\r
-                               else\r
-                               {\r
-                                       Node child = cursor;\r
-\r
-                                       cursor = path[--level];\r
-                                       path[level] = null;\r
-                                       comp = dirs[level];\r
-                                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
-#if NCP\r
-                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
-#endif\r
-#if BAG\r
-                                       cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                       }\r
-\r
-                       //Stage 5: rotate \r
-                       if (demote_or_rotate)\r
-                       {\r
-                               //At start:\r
-                               //parent = cursor (temporary for swapping nodes)\r
-                               //childsibling is the sibling of the updated child (x)\r
-                               //cursor is always the top of the subtree\r
-                               Node parent = cursor;\r
-\r
-                               if (childsibling.red)\r
-                               {//Case 2 and perhaps more. \r
-                                       //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null \r
-                                       //(and black). The grandnephews are children of nearnephew\r
-                                       Node neargrandnephew, fargrandnephew;\r
-\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               nearnephew = childsibling.left;\r
-                                               farnephew = childsibling.right;\r
-                                               neargrandnephew = nearnephew.left;\r
-                                               fargrandnephew = nearnephew.right;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               nearnephew = childsibling.right;\r
-                                               farnephew = childsibling.left;\r
-                                               neargrandnephew = nearnephew.right;\r
-                                               fargrandnephew = nearnephew.left;\r
-                                       }\r
-\r
-                                       if (fargrandnephew != null && fargrandnephew.red)\r
-                                       {//Case 2+1b\r
-#if NCP\r
-                                               Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
-\r
-                                               //The end result of this will always be e copy of parent\r
-                                               Node.update(ref parent, comp < 0, neargrandnephew, maxsnapid, generation);\r
-                                               Node.update(ref childsibling, comp > 0, nearnephew, maxsnapid, generation);\r
-#endif\r
-                                               if (comp > 0)\r
-                                               {\r
-                                                       nearnephew.left = parent;\r
-                                                       parent.right = neargrandnephew;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       nearnephew.right = parent;\r
-                                                       parent.left = neargrandnephew;\r
-                                               }\r
-\r
-                                               cursor = childsibling;\r
-                                               childsibling.red = false;\r
-                                               nearnephew.red = true;\r
-                                               fargrandnephew.red = false;\r
-#if MAINTAIN_RANK\r
-                                               nearnephew.rank++;\r
-                                               parent.rank--;\r
-#endif\r
-#if BAG\r
-                                               cursor.size = parent.size;\r
-                                               nearnephew.size = cursor.size - cursor.items - farnephew.size;\r
-                                               parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size;\r
-#elif MAINTAIN_SIZE\r
-                                               cursor.size = parent.size;\r
-                                               nearnephew.size = cursor.size - 1 - farnephew.size;\r
-                                               parent.size = nearnephew.size - 1 - fargrandnephew.size;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(parent);\r
-                                               fixheight(nearnephew);\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                                       else if (neargrandnephew != null && neargrandnephew.red)\r
-                                       {//Case 2+1c\r
-#if NCP\r
-                                               Node.CopyNode(ref neargrandnephew, maxsnapid, generation);\r
-#endif\r
-                                               if (comp > 0)\r
-                                               {\r
-#if NCP\r
-                                                       Node.update(ref childsibling, true, neargrandnephew, maxsnapid, generation);\r
-                                                       Node.update(ref nearnephew, true, neargrandnephew.right, maxsnapid, generation);\r
-                                                       Node.update(ref parent, false, neargrandnephew.left, maxsnapid, generation);\r
-#else\r
-                                                       childsibling.left = neargrandnephew;\r
-                                                       nearnephew.left = neargrandnephew.right;\r
-                                                       parent.right = neargrandnephew.left;\r
-#endif\r
-                                                       neargrandnephew.left = parent;\r
-                                                       neargrandnephew.right = nearnephew;\r
-                                               }\r
-                                               else\r
-                                               {\r
-#if NCP\r
-                                                       Node.update(ref childsibling, false, neargrandnephew, maxsnapid, generation);\r
-                                                       Node.update(ref nearnephew, false, neargrandnephew.left, maxsnapid, generation);\r
-                                                       Node.update(ref parent, true, neargrandnephew.right, maxsnapid, generation);\r
-#else\r
-                                                       childsibling.right = neargrandnephew;\r
-                                                       nearnephew.right = neargrandnephew.left;\r
-                                                       parent.left = neargrandnephew.right;\r
-#endif\r
-                                                       neargrandnephew.right = parent;\r
-                                                       neargrandnephew.left = nearnephew;\r
-                                               }\r
-\r
-                                               cursor = childsibling;\r
-                                               childsibling.red = false;\r
-#if MAINTAIN_RANK\r
-                                               neargrandnephew.rank++;\r
-                                               parent.rank--;\r
-#endif\r
-#if BAG\r
-                                               cursor.size = parent.size;\r
-                                               parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                               nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
-                                               neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size;\r
-#elif MAINTAIN_SIZE\r
-                                               cursor.size = parent.size;\r
-                                               parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                               nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
-                                               neargrandnephew.size = 1 + parent.size + nearnephew.size;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(parent);\r
-                                               fixheight(nearnephew);\r
-                                               fixheight(neargrandnephew);\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                                       else\r
-                                       {//Case 2 only\r
-#if NCP\r
-                                               Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
-                                               Node.update(ref childsibling, comp > 0, parent, maxsnapid, generation);\r
-#else\r
-                                               if (comp > 0)\r
-                                               {\r
-                                                       childsibling.left = parent;\r
-                                                       parent.right = nearnephew;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       childsibling.right = parent;\r
-                                                       parent.left = nearnephew;\r
-                                               }\r
-#endif\r
-                                               cursor = childsibling;\r
-                                               childsibling.red = false;\r
-                                               nearnephew.red = true;\r
-#if MAINTAIN_RANK\r
-                                               parent.rank--;\r
-#endif\r
-#if BAG\r
-                                               cursor.size = parent.size;\r
-                                               parent.size -= farnephew.size + cursor.items;\r
-#elif MAINTAIN_SIZE\r
-                                               cursor.size = parent.size;\r
-                                               parent.size -= farnephew.size + 1;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(parent);\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                               }\r
-                               else if (farnephew != null && farnephew.red)\r
-                               {//Case 1b\r
-                                       nearnephew = comp > 0 ? childsibling.left : childsibling.right;         \r
-#if NCP\r
-                                       Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
-                                       Node.CopyNode(ref childsibling, maxsnapid, generation);\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               childsibling.left = parent;\r
-                                               childsibling.right = farnephew;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               childsibling.right = parent;\r
-                                               childsibling.left = farnephew;\r
-                                       }\r
-#else\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               childsibling.left = parent;\r
-                                               parent.right = nearnephew;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               childsibling.right = parent;\r
-                                               parent.left = nearnephew;\r
-                                       }\r
-#endif\r
-                                       cursor = childsibling;\r
-                                       cursor.red = parent.red;\r
-                                       parent.red = false;\r
-                                       farnephew.red = false;\r
-\r
-#if MAINTAIN_RANK\r
-                                       childsibling.rank++;\r
-                                       parent.rank--;\r
-#endif\r
-#if BAG\r
-                                       cursor.size = parent.size;\r
-                                       parent.size -= farnephew.size + cursor.items;\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size = parent.size;\r
-                                       parent.size -= farnephew.size + 1;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(parent);\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                               else if (nearnephew != null && nearnephew.red)\r
-                               {//Case 1c\r
-#if NCP\r
-                                       Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
-#endif\r
-                                       if (comp > 0)\r
-                                       {\r
-#if NCP\r
-                                               Node.update(ref childsibling, true, nearnephew.right, maxsnapid, generation);\r
-                                               Node.update(ref parent, false, nearnephew.left, maxsnapid, generation);\r
-#else\r
-                                               childsibling.left = nearnephew.right;\r
-                                               parent.right = nearnephew.left;\r
-#endif\r
-                                               nearnephew.left = parent;\r
-                                               nearnephew.right = childsibling;\r
-                                       }\r
-                                       else\r
-                                       {\r
-#if NCP\r
-                                               Node.update(ref childsibling, false, nearnephew.left, maxsnapid, generation);\r
-                                               Node.update(ref parent, true, nearnephew.right, maxsnapid, generation);\r
-#else\r
-                                               childsibling.right = nearnephew.left;\r
-                                               parent.left = nearnephew.right;\r
-#endif\r
-                                               nearnephew.right = parent;\r
-                                               nearnephew.left = childsibling;\r
-                                       }\r
-\r
-                                       cursor = nearnephew;\r
-                                       cursor.red = parent.red;\r
-                                       parent.red = false;\r
-#if MAINTAIN_RANK\r
-                                       nearnephew.rank++;\r
-                                       parent.rank--;\r
-#endif\r
-#if BAG\r
-                                       cursor.size = parent.size;\r
-                                       parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                       childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size = parent.size;\r
-                                       parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                       childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(parent);\r
-                                       fixheight(childsibling);\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                               else\r
-                               {//Case 1a can't happen\r
-                                       throw new Exception("Case 1a can't happen here");\r
-                               }\r
-\r
-                               //Resplice cursor:\r
-                               if (level == 0)\r
-                               {\r
-                                       root = cursor;\r
-                               }\r
-                               else\r
-                               {\r
-                                       Node swap = cursor;\r
-\r
-                                       cursor = path[--level];\r
-                                       path[level] = null;\r
-#if NCP\r
-                                       Node.update(ref cursor, dirs[level] > 0, swap, maxsnapid, generation);\r
-#else\r
-                               \r
-                                       if (dirs[level] > 0)\r
-                                               cursor.left = swap;\r
-                                       else\r
-                                               cursor.right = swap;\r
-#endif\r
-#if BAG\r
-                                       cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                       }\r
-\r
-                       //Stage 6: fixup to the root\r
-                       while (level > 0)\r
-                       {\r
-                               Node child = cursor;\r
-\r
-                               cursor = path[--level];\r
-                               path[level] = null;\r
-#if NCP\r
-                               if (child != (dirs[level] > 0 ? cursor.left : cursor.right))\r
-                                       Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-#if BAG\r
-                               cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                               cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               fixheight(cursor);\r
-#endif\r
-                       }\r
-\r
-#if MAINTAIN_HEIGHT\r
-                       depth = root.height;\r
-#endif\r
-#if NCP\r
-                       root = cursor;\r
-#endif\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from this collection.\r
-               /// </summary>\r
-               [Tested]\r
-               public void Clear()\r
-               {\r
-                       updatecheck();\r
-                       clear();\r
-               }\r
-\r
-\r
-               private void clear()\r
-               {\r
-                       size = 0;\r
-                       root = null;\r
-                       blackdepth = 0;\r
-#if MAINTAIN_HEIGHT\r
-                       depth = 0;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in another collection from this one. If this collection\r
-               /// has bag semantics, take multiplicities into account.\r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       T jtem;\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               if (root == null)\r
-                                       break;\r
-\r
-                               jtem = item;\r
-                               removeIterative(ref jtem, false);\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items not in some other collection from this one. If this collection\r
-               /// has bag semantics, take multiplicities into account.\r
-               /// </summary>\r
-               /// <param name="items">The items to retain.</param>\r
-               [Tested]\r
-               public void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       //A much more efficient version is possible if items is sorted like this.\r
-                       //Well, it is unclear how efficient it would be.\r
-                       //We could use a marking method!?\r
-                       TreeSet<T> t = (TreeSet<T>)MemberwiseClone();\r
-\r
-                       t.Clear();\r
-                       foreach (T item in items)\r
-                               if (ContainsCount(item) > t.ContainsCount(item))\r
-                                       t.Add(item);\r
-\r
-                       root = t.root;\r
-                       size = t.size;\r
-                       blackdepth = t.blackdepth;\r
-#if MAINTAIN_HEIGHT\r
-                       depth = t.depth;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains all the values in another collection.\r
-               /// If this collection has bag semantics (<code>NoDuplicates==false</code>)\r
-               /// the check is made with respect to multiplicities, else multiplicities\r
-               /// are not taken into account.\r
-               /// </summary>\r
-               /// <param name="items">The </param>\r
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
-               [Tested]\r
-               public bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       //This is worst-case O(m*logn)\r
-                       foreach (T item in items)\r
-                               if (!Contains(item)) return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               //Higher order:\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the items of this\r
-               /// indexed sorted collection satisfying a certain predicate.\r
-               /// </summary>\r
-               /// <param name="filter">The filter delegate defining the predicate.</param>\r
-               /// <returns>The new indexed sorted collection.</returns>\r
-               [Tested]\r
-               public IIndexedSorted<T> FindAll(Filter<T> filter)\r
-               {\r
-                       TreeSet<T> res = new TreeSet<T>(comparer);\r
-                       MSG.IEnumerator<T> e = GetEnumerator();\r
-                       Node head = null, tail = null;\r
-                       int z = 0;\r
-#if BAG\r
-                       int ec = 0;\r
-#endif\r
-                       while (e.MoveNext())\r
-                       {\r
-                               T thisitem = e.Current;\r
-#if BAG\r
-                               //We could document that filter will only be called \r
-                               //once on each unique item. That might even be good for the user!\r
-                               if (tail!=null && comparer.Compare(thisitem, tail.item) == 0)\r
-                               {\r
-                                       tail.items++;\r
-                                       ec++;\r
-                                       continue;\r
-                               }\r
-#endif\r
-                               if (filter(thisitem))\r
-                               {\r
-                                       if (head == null)\r
-                                       {\r
-                                               head = tail = new Node();\r
-                                       }\r
-                                       else\r
-                                       {\r
-#if BAG\r
-                                               tail.size = tail.items;\r
-#endif\r
-                                               tail.right = new Node();\r
-                                               tail = tail.right;\r
-                                       }\r
-\r
-                                       tail.item = thisitem;\r
-                                       z++;\r
-                               }\r
-                       }\r
-#if BAG\r
-                       if (tail!=null)\r
-                               tail.size = tail.items;\r
-#endif\r
-\r
-                       if (z == 0)\r
-                               return res;\r
-\r
-                       int blackheight = 0, red = z, maxred = 1;\r
-\r
-                       while (maxred <= red)\r
-                       {\r
-                               red -= maxred;\r
-                               maxred <<= 1;\r
-                               blackheight++;\r
-                       }\r
-\r
-                       res.root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);\r
-                       res.blackdepth = blackheight;\r
-                       res.size = z;\r
-#if BAG\r
-                       res.size += ec;\r
-#endif\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the results of\r
-               /// mapping all items of this list.\r
-               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
-               /// the items of this collection (with respect to the two given comparison \r
-               /// relations).\r
-               /// </summary>\r
-               /// <param name="mapper">The delegate definging the map.</param>\r
-               /// <param name="c">The comparion relation to use for the result.</param>\r
-               /// <returns>The new sorted collection.</returns>\r
-               [Tested]\r
-               public IIndexedSorted<V> Map<V>(Mapper<T,V> mapper, IComparer<V> c)\r
-               {\r
-                       TreeSet<V> res = new TreeSet<V>(c);\r
-\r
-                       if (size == 0)\r
-                               return res;\r
-\r
-                       MSG.IEnumerator<T> e = GetEnumerator();\r
-                       TreeSet<V>.Node head = null, tail = null;\r
-                       V oldv = default(V);\r
-                       int z = 0;\r
-#if BAG\r
-                       T lastitem = default(T);\r
-#endif\r
-                       while (e.MoveNext())\r
-                       {\r
-                               T thisitem = e.Current;\r
-#if BAG\r
-                               //We could document that mapper will only be called \r
-                               //once on each unique item. That might even be good for the user!\r
-                               if (tail != null && comparer.Compare(thisitem, lastitem) == 0)\r
-                               {\r
-                                       tail.items++;\r
-                                       continue;\r
-                               }\r
-#endif\r
-                               V newv = mapper(thisitem);\r
-\r
-                               if (head == null)\r
-                               {\r
-                                       head = tail = new TreeSet<V>.Node();\r
-                                       z++;\r
-                               }\r
-                               else\r
-                               {\r
-                                       int comp = c.Compare(oldv, newv);\r
-#if BAG\r
-                                       if (comp == 0)\r
-                                       {\r
-                                               tail.items++;\r
-                                               continue;\r
-                                       }\r
-                                       if (comp > 0)\r
-#else\r
-                                       if (comp >= 0)\r
-#endif\r
-                                               throw new ArgumentException("mapper not monotonic");\r
-#if BAG\r
-                                       tail.size = tail.items;\r
-#endif\r
-                                       tail.right = new TreeSet<V>.Node();\r
-                                       tail = tail.right;\r
-                                       z++;\r
-                               }\r
-#if BAG\r
-                               lastitem = thisitem;\r
-#endif\r
-                               tail.item = oldv = newv;\r
-                       }\r
-\r
-#if BAG\r
-                       tail.size = tail.items;\r
-#endif\r
-\r
-                       int blackheight = 0, red = z, maxred = 1;\r
-\r
-                       while (maxred <= red)\r
-                       {\r
-                               red -= maxred;\r
-                               maxred <<= 1;\r
-                               blackheight++;\r
-                       }\r
-\r
-                       res.root = TreeSet<V>.maketreer(ref head, blackheight, maxred, red);\r
-                       res.blackdepth = blackheight;\r
-                       res.size = size;\r
-                       return res;\r
-               }\r
-\r
-\r
-               //below is the bag utility stuff\r
-               /// <summary>\r
-               /// Count the number of items of the collection equal to a particular value.\r
-               /// Returns 0 if and only if the value is not in the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to count.</param>\r
-               /// <returns>The number of copies found.</returns>\r
-               [Tested]\r
-               public int ContainsCount(T item)\r
-               {\r
-#if BAG\r
-                       Node next; int comp = 0;\r
-\r
-                       next = root;\r
-                       while (next != null)\r
-                       {\r
-                               comp = comparer.Compare(next.item, item);\r
-                               if (comp == 0)\r
-                                       return next.items;\r
-\r
-                               next = comp < 0 ? right(next) : left(next);\r
-                       }\r
-\r
-                       return 0;\r
-#else\r
-                       //Since we are strictly NoDuplicates we just do\r
-                       return Contains(item) ? 1 : 0;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items equivalent to a given value.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               [Tested]\r
-               public void RemoveAllCopies(T item)\r
-               {\r
-#if BAG\r
-                       updatecheck();\r
-                       removeIterative(ref item, true);\r
-#else\r
-                       \r
-                       Remove(item);\r
-#endif\r
-               }\r
-\r
-\r
-               #endregion\r
-\r
-               #region IIndexed<T> Members\r
-                       \r
-               private Node findNode(int i)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                       Node next = root;\r
-\r
-                       if (i >= 0 && i < size)\r
-                               while (true)\r
-                               {\r
-                                       int j = next.left == null ? 0 : next.left.size;\r
-\r
-                                       if (i > j)\r
-                                       {\r
-#if BAG\r
-                                               i -= j + next.items;                                    \r
-                                               if (i<0)\r
-                                                       return next;\r
-#else\r
-                                               i -= j + 1;\r
-#endif\r
-                                               next = next.right;\r
-                                       }\r
-                                       else if (i == j)\r
-                                               return next;\r
-                                       else\r
-                                               next = next.left;\r
-                               }\r
-\r
-                       throw new IndexOutOfRangeException();\r
-#else\r
-                       throw new NotSupportedException();\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <value>The i'th item of this list.</value>\r
-               /// <param name="i">the index to lookup</param>\r
-               [Tested]\r
-               public T this[int i] { [Tested] get { return findNode(i).item; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going forwrds from the start.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of item from start.</returns>\r
-               [Tested]\r
-               public int IndexOf(T item)\r
-               {\r
-                       int upper;\r
-\r
-                       return indexOf(item, out upper);\r
-               }\r
-\r
-\r
-               private int indexOf(T item, out int upper)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                       int ind = 0; Node next = root;\r
-\r
-                       while (next != null)\r
-                       {\r
-                int comp = comparer.Compare(item, next.item);\r
-\r
-                if (comp < 0)\r
-                                       next = next.left;\r
-                               else\r
-                               {\r
-                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
-\r
-                                       if (comp == 0)\r
-                                       {\r
-#if BAG\r
-                                               upper = ind + leftcnt + next.items - 1;\r
-                                               return ind + leftcnt;\r
-#else\r
-                                               return upper = ind + leftcnt;\r
-#endif\r
-                                       }\r
-                                       else\r
-                                       {\r
-#if BAG\r
-                                               ind = ind + next.items + leftcnt;\r
-#else\r
-                                               ind = ind + 1 + leftcnt;\r
-#endif\r
-                                               next = next.right;\r
-                                       }\r
-                               }\r
-                       }\r
-#endif\r
-                       upper = -1;\r
-                       return -1;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going backwords from the end.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of of item from the end.</returns>\r
-               [Tested]\r
-               public int LastIndexOf(T item)\r
-               {\r
-#if BAG\r
-                       int res;\r
-                       indexOf(item, out res);\r
-                       return res;\r
-#else\r
-                       //We have NoDuplicates==true for the set\r
-                       return IndexOf(item);\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the item at a specific position of the list.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <param name="i">The index of the item to remove.</param>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T RemoveAt(int i)\r
-               {\r
-                       updatecheck();\r
-#if MAINTAIN_SIZE\r
-                       if (i < 0 || i >= size)\r
-                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
-\r
-                       //We must follow the pattern of removeIterative()\r
-                       while (dirs.Length < 2 * blackdepth)\r
-                       {\r
-                               dirs = new int[2 * dirs.Length];\r
-                               path = new Node[2 * dirs.Length];\r
-                       }\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (true)\r
-                       {\r
-                               int j = cursor.left == null ? 0 : cursor.left.size;\r
-\r
-                               if (i > j)\r
-                               {\r
-#if BAG\r
-                                       i -= j + cursor.items;\r
-                                       if (i<0)\r
-                                               break;\r
-#else\r
-                                       i -= j + 1;\r
-#endif\r
-                                       dirs[level] = -1;\r
-                                       path[level++] = cursor;\r
-                                       cursor = cursor.right;\r
-                               }\r
-                               else if (i == j)\r
-                                       break;\r
-                               else\r
-                               {\r
-                                       dirs[level] = 1;\r
-                                       path[level++] = cursor;\r
-                                       cursor = cursor.left;\r
-                               }\r
-                       }\r
-\r
-                       T retval = cursor.item;\r
-\r
-#if BAG\r
-                       if (cursor.items>1)\r
-                       {\r
-                               resplicebag(level, cursor);\r
-                               size--;\r
-                               return retval;\r
-                       }\r
-#endif\r
-                       removeIterativePhase2(cursor, level);\r
-                       return retval;\r
-#else\r
-                       throw new NotSupportedException();\r
-#endif\r
-               }\r
-\r
-#if BAG\r
-               private void resplicebag(int level, Node cursor)\r
-               {\r
-#if NCP\r
-                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                       cursor.items--;\r
-                       cursor.size--;\r
-                       while (level-- > 0)\r
-                       {\r
-                               Node kid = cursor;\r
-\r
-                               cursor = path[level];\r
-#if NCP\r
-                               Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
-#endif\r
-                               cursor.size--;\r
-                               path[level] = null;\r
-                       }\r
-               }\r
-#endif\r
-               /// <summary>\r
-               /// Remove all items in an index interval.\r
-               /// <exception cref="IndexOutOfRangeException"/>???. \r
-               /// </summary>\r
-               /// <param name="start">The index of the first item to remove.</param>\r
-               /// <param name="count">The number of items to remove.</param>\r
-               [Tested]\r
-               public void RemoveInterval(int start, int count)\r
-               {\r
-                       if (start < 0 || count < 0)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       if (start + count > this.size)\r
-                               throw new ArgumentException();\r
-\r
-                       updatecheck();\r
-\r
-                       //This is terrible for large count. We should split the tree at \r
-                       //the endpoints of the range and fuse the parts!\r
-                       //We really need good internal destructive split and catenate functions!\r
-                       for (int i = 0; i < count; i++)\r
-                               RemoveAt(start);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/>.\r
-               /// </summary>\r
-               /// <value>The directed collection of items in a specific index interval.</value>\r
-               /// <param name="start">The low index of the interval (inclusive).</param>\r
-               /// <param name="end">The high index of the interval (exclusive).</param>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> this[int start, int end]\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-                               checkRange(start, end - start);\r
-                               return new Interval(this, start, end - start, true);\r
-                       }\r
-               }\r
-\r
-               #region Interval nested class\r
-               class Interval: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
-               {\r
-                       int start, length, stamp;\r
-\r
-                       bool forwards;\r
-\r
-                       TreeSet<T> tree;\r
-\r
-\r
-                       internal Interval(TreeSet<T> tree, int start, int count, bool forwards)\r
-                       {\r
-#if NCP\r
-                               if (tree.isSnapShot)\r
-                                       throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-                               this.start = start; this.length = count;this.forwards = forwards;\r
-                               this.tree = tree; this.stamp = tree.stamp;\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-            public override int Count { [Tested]get { return length; } }\r
-\r
-\r
-            public override Speed CountSpeed { get { return Speed.Constant; } }\r
-            \r
-            [Tested]\r
-            public override MSG.IEnumerator<T> GetEnumerator()\r
-                       {\r
-#if MAINTAIN_SIZE\r
-                               tree.modifycheck(stamp);\r
-#if BAG\r
-                               int togo;\r
-#endif\r
-                               Node cursor = tree.root;\r
-                               Node[] path = new Node[2 * tree.blackdepth];\r
-                               int level = 0, totaltogo = length;\r
-\r
-                               if (totaltogo == 0)\r
-                                       yield break;\r
-\r
-                               if (forwards)\r
-                               {\r
-                                       int i = start;\r
-\r
-                                       while (true)\r
-                                       {\r
-                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
-\r
-                                               if (i > j)\r
-                                               {\r
-#if BAG\r
-                                                       i -= j + cursor.items;\r
-                                                       if (i < 0)\r
-                                                       {\r
-                                                               togo = cursor.items + i;\r
-                                                               break;\r
-                                                       }\r
-#else\r
-                                                       i -= j + 1;\r
-#endif\r
-                                                       cursor = cursor.right;\r
-                                               }\r
-                                               else if (i == j)\r
-                                               {\r
-#if BAG\r
-                                                       togo = cursor.items;\r
-#endif\r
-                                                       break;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       path[level++] = cursor;\r
-                                                       cursor = cursor.left;\r
-                                               }\r
-                                       }\r
-\r
-                                       T current = cursor.item;\r
-\r
-                                       while (totaltogo-- > 0)\r
-                                       {\r
-                                               yield return current;\r
-                                               tree.modifycheck(stamp);\r
-#if BAG\r
-                                               if (--togo > 0)\r
-                                                       continue;\r
-#endif\r
-                                               if (cursor.right != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.right;\r
-                                                       while (cursor.left != null)\r
-                                                               path[++level] = cursor = cursor.left;\r
-                                               }\r
-                                               else if (level == 0)\r
-                                                       yield break;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       int i = start + length - 1;\r
-\r
-                                       while (true)\r
-                                       {\r
-                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
-\r
-                                               if (i > j)\r
-                                               {\r
-#if BAG\r
-                                                       if (i - j < cursor.items)\r
-                                                       {\r
-                                                               togo = i - j + 1;\r
-                                                               break;\r
-                                                       }\r
-                                                       i -= j + cursor.items;\r
-#else\r
-                                                       i -= j + 1;\r
-#endif\r
-                                                       path[level++] = cursor;\r
-                                                       cursor = cursor.right;\r
-                                               }\r
-                                               else if (i == j)\r
-                                               {\r
-#if BAG\r
-                                                       togo = 1;\r
-#endif\r
-                                                       break;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       cursor = cursor.left;\r
-                                               }\r
-                                       }\r
-\r
-                                       T current = cursor.item;\r
-\r
-                                       while (totaltogo-- > 0)\r
-                                       {\r
-                                               yield return current;\r
-                                               tree.modifycheck(stamp);\r
-#if BAG\r
-                                               if (--togo > 0)\r
-                                                       continue;\r
-#endif\r
-                                               if (cursor.left != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.left;\r
-                                                       while (cursor.right != null)\r
-                                                               path[++level] = cursor = cursor.right;\r
-                                               }\r
-                                               else if (level == 0)\r
-                                                       yield break;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                       }\r
-                               }\r
-\r
-#else\r
-                       throw new NotSupportedException();\r
-#endif\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       public IDirectedCollectionValue<T> Backwards()\r
-                       { return new Interval(tree, start, length, !forwards); }\r
-\r
-\r
-                       [Tested]\r
-                       IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()\r
-                       { return Backwards(); }\r
-\r
-\r
-                       [Tested]\r
-                       public EnumerationDirection Direction\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;\r
-                               }\r
-                       }\r
-               }\r
-               #endregion\r
-\r
-               /// <summary>\r
-               /// Create a collection containing the same items as this collection, but\r
-               /// whose enumerator will enumerate the items backwards. The new collection\r
-               /// will become invalid if the original is modified. Method typicaly used as in\r
-               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
-               /// </summary>\r
-               /// <returns>The backwards collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
-\r
-               #endregion\r
-\r
-               #region ISequenced Members\r
-               [Tested]\r
-               int ISequenced<T>.GetHashCode() { return sequencedhashcode(); }\r
-\r
-\r
-               [Tested]\r
-               bool ISequenced<T>.Equals(ISequenced<T> that) { return sequencedequals(that); }\r
-               #endregion\r
-\r
-               #region PriorityQueue Members\r
-\r
-        /// <summary>\r
-        /// The comparer object supplied at creation time for this collection\r
-        /// </summary>\r
-        /// <value>The comparer</value>\r
-        public IComparer<T> Comparer { get { return comparer; } }\r
-\r
-\r
-        /// <summary>\r
-               /// Find the current least item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The least item.</returns>\r
-               [Tested]\r
-               public T FindMin()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-#if MAINTAIN_EXTREMA\r
-                       return min;\r
-#else\r
-                       Node cursor = root, next = left(cursor);\r
-\r
-                       while (next != null)\r
-                       {\r
-                               cursor = next;\r
-                               next = left(cursor);\r
-                       }\r
-\r
-                       return cursor.item;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the least item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMin()\r
-               {\r
-                       updatecheck();\r
-\r
-                       //persistence guard?\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       //We must follow the pattern of removeIterative()\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (cursor.left != null)\r
-                       {\r
-                               dirs[level] = 1;\r
-                               path[level++] = cursor;\r
-                               cursor = cursor.left;\r
-                       }\r
-\r
-                       T retval = cursor.item;\r
-\r
-#if BAG\r
-                       if (cursor.items > 1)\r
-                       {\r
-                               resplicebag(level, cursor);\r
-                               size--;\r
-                               return retval;\r
-                       }\r
-#endif\r
-                       removeIterativePhase2(cursor, level);\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the current largest item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The largest item.</returns>\r
-               [Tested]\r
-               public T FindMax()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-#if MAINTAIN_EXTREMA\r
-                       return max;\r
-#else\r
-                       Node cursor = root, next = right(cursor);\r
-\r
-                       while (next != null)\r
-                       {\r
-                               cursor = next;\r
-                               next = right(cursor);\r
-                       }\r
-\r
-                       return cursor.item;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the largest item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMax()\r
-               {\r
-                       //persistence guard?\r
-                       updatecheck();\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       //We must follow the pattern of removeIterative()\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (cursor.right != null)\r
-                       {\r
-                               dirs[level] = -1;\r
-                               path[level++] = cursor;\r
-                               cursor = cursor.right;\r
-                       }\r
-\r
-                       T retval = cursor.item;\r
-\r
-#if BAG\r
-                       if (cursor.items > 1)\r
-                       {\r
-                               resplicebag(level, cursor);\r
-                               size--;\r
-                               return retval;\r
-                       }\r
-#endif\r
-                       removeIterativePhase2(cursor, level);\r
-                       return retval;\r
-               }\r
-               #endregion\r
-\r
-               #region IPredecesorStructure<T> Members\r
-\r
-               /// <summary>\r
-               /// Find the strict predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than or equal to the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the predecessor for.</param>\r
-               /// <returns>The predecessor.</returns>\r
-               [Tested]\r
-               public T Predecessor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp < 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = right(cursor);\r
-                               }\r
-                               else if (comp == 0)\r
-                               {\r
-                                       cursor = left(cursor);\r
-                                       while (cursor != null)\r
-                                       {\r
-                                               bestsofar = cursor;\r
-                                               cursor = right(cursor);\r
-                                       }\r
-                               }\r
-                               else\r
-                                       cursor = left(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak predecessor for.</param>\r
-               /// <returns>The weak predecessor.</returns>\r
-               [Tested]\r
-               public T WeakPredecessor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp < 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = right(cursor);\r
-                               }\r
-                               else if (comp == 0)\r
-                                       return cursor.item;\r
-                               else\r
-                                       cursor = left(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the strict successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than or equal to the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the successor for.</param>\r
-               /// <returns>The successor.</returns>\r
-               [Tested]\r
-               public T Successor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp > 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = left(cursor);\r
-                               }\r
-                               else if (comp == 0)\r
-                               {\r
-                                       cursor = right(cursor);\r
-                                       while (cursor != null)\r
-                                       {\r
-                                               bestsofar = cursor;\r
-                                               cursor = left(cursor);\r
-                                       }\r
-                               }\r
-                               else\r
-                                       cursor = right(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak successor for.</param>\r
-               /// <returns>The weak successor.</returns>\r
-               [Tested]\r
-               public T WeakSuccessor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp == 0)\r
-                                       return cursor.item;\r
-                               else if (comp > 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = left(cursor);\r
-                               }\r
-                               else\r
-                                       cursor = right(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
-               }\r
-\r
-               #endregion\r
-               \r
-               #region ISorted<T> Members\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items greater than or equal to a supplied value.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeFrom(T bot)\r
-               { return new Range(this, true, bot, false, default(T), EnumerationDirection.Forwards); }\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items between two supplied values.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)\r
-               { return new Range(this, true, bot, true, top, EnumerationDirection.Forwards); }\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items less than a supplied value.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeTo(T top)\r
-               { return new Range(this, false, default(T), true, top, EnumerationDirection.Forwards); }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a directed collection with the same items as this collection.\r
-               /// </summary>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeAll()\r
-               { return new Range(this, false, default(T), false, default(T), EnumerationDirection.Forwards); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot) { return RangeFrom(bot); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> ISorted<T>.RangeTo(T top) { return RangeTo(top); }\r
-\r
-\r
-               //Utility for CountXxxx. Actually always called with strict = true.\r
-               private int countTo(T item, bool strict)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                       int ind = 0, comp = 0; Node next = root;\r
-\r
-                       while (next != null)\r
-                       {\r
-                comp = comparer.Compare(item, next.item);\r
-                if (comp < 0)\r
-                                       next = next.left;\r
-                               else\r
-                               {\r
-                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
-#if BAG\r
-                                       if (comp == 0)\r
-                                               return strict ? ind + leftcnt : ind + leftcnt + next.items;\r
-                                       else\r
-                                       {\r
-                                               ind = ind + next.items + leftcnt;\r
-                                               next = next.right;\r
-                                       }\r
-#else\r
-                                       if (comp == 0)\r
-                                               return strict ? ind + leftcnt : ind + leftcnt + 1;\r
-                                       else\r
-                                       {\r
-                                               ind = ind + 1 + leftcnt;\r
-                                               next = next.right;\r
-                                       }\r
-#endif\r
-                               }\r
-                       }\r
-\r
-                       //if we get here, we are at the same side of the whole collection:\r
-                       return ind;\r
-#else\r
-                       throw new NotSupportedException("Code compiled w/o size!");\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Perform a search in the sorted collection for the ranges in which a\r
-               /// non-decreasing function from the item type to <code>int</code> is\r
-               /// negative, zero respectively positive. If the supplied cut function is\r
-               /// not non-decreasing, the result of this call is undefined.\r
-               /// </summary>\r
-               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
-               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
-               /// the <code>c.CompareTo(T that)</code> method.</param>\r
-               /// <param name="low">Returns the largest item in the collection, where the\r
-               /// cut function is negative (if any).</param>\r
-               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
-               /// on this collection.</param>\r
-               /// <param name="high">Returns the least item in the collection, where the\r
-               /// cut function is positive (if any).</param>\r
-               /// <param name="highIsValid">True if the cut function is positive somewhere\r
-               /// on this collection.</param>\r
-               /// <returns></returns>\r
-               [Tested]\r
-               public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)\r
-               {\r
-                       Node cursor = root, lbest = null, rbest = null;\r
-                       bool res = false;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                               int comp = c.CompareTo(cursor.item);\r
-\r
-                               if (comp > 0)\r
-                               {\r
-                                       lbest = cursor;\r
-                                       cursor = right(cursor);\r
-                               }\r
-                               else if (comp < 0)\r
-                               {\r
-                                       rbest = cursor;\r
-                                       cursor = left(cursor);\r
-                               }\r
-                               else\r
-                               {\r
-                                       res = true;\r
-\r
-                                       Node tmp = left(cursor);\r
-\r
-                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
-                                               tmp = left(tmp);\r
-\r
-                                       if (tmp != null)\r
-                                       {\r
-                                               lbest = tmp;\r
-                                               tmp = right(tmp);\r
-                                               while (tmp != null)\r
-                                               {\r
-                                                       if (c.CompareTo(tmp.item) > 0)\r
-                                                       {\r
-                                                               lbest = tmp;\r
-                                                               tmp = right(tmp);\r
-                                                       }\r
-                                                       else\r
-                                                               tmp = left(tmp);\r
-                                               }\r
-                                       }\r
-\r
-                                       tmp = right(cursor);\r
-                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
-                                               tmp = right(tmp);\r
-\r
-                                       if (tmp != null)\r
-                                       {\r
-                                               rbest = tmp;\r
-                                               tmp = left(tmp);\r
-                                               while (tmp != null)\r
-                                               {\r
-                                                       if (c.CompareTo(tmp.item) < 0)\r
-                                                       {\r
-                                                               rbest = tmp;\r
-                                                               tmp = left(tmp);\r
-                                                       }\r
-                                                       else\r
-                                                               tmp = right(tmp);\r
-                                               }\r
-                                       }\r
-\r
-                                       break;\r
-                               }\r
-                       }\r
-\r
-                       if (highIsValid = (rbest != null))\r
-                               high = rbest.item;\r
-                       else\r
-                               high = default(T);\r
-\r
-                       if (lowIsValid = (lbest != null))\r
-                               low = lbest.item;\r
-                       else\r
-                               low = default(T);\r
-\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items at or above a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountFrom(T bot) { return size - countTo(bot, true); }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountFromTo(T bot, T top)\r
-               {\r
-            if (comparer.Compare(bot, top) >= 0)\r
-                return 0;\r
-\r
-                       return countTo(top, true) - countTo(bot, true);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountTo(T top) { return countTo(top, true); }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection above or at a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeFrom(T low)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int count = CountFrom(low);\r
-\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       for (int i = 0; i < count; i++)\r
-                               DeleteMax();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeFromTo(T low, T hi)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int count = CountFromTo(low, hi);\r
-\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       for (int i = 0; i < count; i++)\r
-                               Remove(Predecessor(hi));\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeTo(T hi)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int count = CountTo(hi);\r
-\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       for (int i = 0; i < count; i++)\r
-                               DeleteMin();\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IPersistent<T> Members\r
-\r
-               private bool disposed;\r
-\r
-\r
-\r
-               /// <summary>\r
-               /// If this tree is a snapshot, remove registration in base tree\r
-               /// </summary>\r
-               [Tested]\r
-               public void Dispose()\r
-               {\r
-                       Dispose(true);\r
-                       GC.SuppressFinalize(this);\r
-               }\r
-\r
-\r
-               private void Dispose(bool disposing)\r
-               {\r
-                       if (!disposed)\r
-                       {\r
-                               if (disposing) { }\r
-#if NCP\r
-                               if (isSnapShot)\r
-                               {\r
-                                       snapdata.Remove(generation, disposing);\r
-                                       snapdata = null;\r
-                                       root = null;\r
-                                       dirs = null;\r
-                                       path = null;\r
-                                       comparer = null;\r
-                                       disposed = true;\r
-                               }\r
-                               else { }\r
-#endif\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// If this tree is a snapshot, remove registration in base tree\r
-               /// </summary>\r
-               ~TreeSet()\r
-               {\r
-                       Dispose(false);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Make a (read-only) snap shot of this collection.\r
-               /// </summary>\r
-               /// <returns>The snap shot.</returns>\r
-               [Tested]\r
-               public ISorted<T> Snapshot()\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new InvalidOperationException("Cannot snapshot a snapshot");\r
-\r
-                       if (snapdata == null)\r
-                       {\r
-                               snapdata = new SnapData(this);\r
-                       }\r
-\r
-                       snapdata.Add(generation, this);\r
-\r
-                       TreeSet<T> res = (TreeSet<T>)MemberwiseClone();\r
-\r
-                       res.isReadOnly = true; res.isSnapShot = true;\r
-                       maxsnapid = generation++;\r
-                       return res;\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Snapdata nested class\r
-               //In a class by itself: the tree itself and snapshots must have a ref to \r
-               //the snapids, but we do not want snapshots to have a (strong) ref to the full\r
-               //updatable tree, which should be garbagecollectable even if there are still \r
-               //live snapshots!\r
-               //\r
-               //Access to SnapData should be thread safe since we expect finalisers \r
-               //of snapshots to remove a snapid that is garbagecollected without \r
-               //having been explicitly Disposed. Therefore we access SnapData through \r
-               //synchronized method/properties.\r
-\r
-#if NCP\r
-               class SnapData\r
-               {\r
-                       TreeSet<int> snapids = new TreeSet<int>(new IC());\r
-\r
-                       WeakReference master;\r
-\r
-\r
-                       internal SnapData(TreeSet<T> tree)\r
-                       {\r
-                               master = new WeakReference(tree);\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       public bool Add(int i, TreeSet<T> tree)\r
-                       {\r
-                               lock (this)\r
-                               {\r
-                                       bool res = snapids.Add(i);\r
-\r
-                                       //assert the following will be i:\r
-                                       tree.maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
-                                       return res;\r
-                               }\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       public bool Remove(int i, bool updmaxsnapid)\r
-                       {\r
-                               lock (this)\r
-                               {\r
-                                       bool res = snapids.Remove(i);\r
-\r
-                                       if (updmaxsnapid)\r
-                                       {\r
-                                               //Is this safe or/and overkill?\r
-                                               object t = master.Target;\r
-\r
-                                               if (t != null && master.IsAlive)\r
-                                               {\r
-                                                       ((TreeSet<T>)t).maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
-                                               }\r
-                                       }\r
-\r
-                                       return res;\r
-                               }\r
-                       }\r
-               }\r
-\r
-#endif\r
-               #endregion\r
-\r
-               #region TreeSet.Range nested class\r
-                       \r
-               internal class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
-               {\r
-                       //We actually need exclusive upper and lower bounds, and flags to \r
-                       //indicate whether the bound is present (we canot rely on default(T))\r
-                       private int stamp;\r
-\r
-                       private TreeSet<T> basis;\r
-\r
-                       private T lowend, highend;\r
-\r
-                       private bool haslowend, hashighend;\r
-\r
-                       EnumerationDirection direction;\r
-\r
-\r
-                       [Tested]\r
-                       public Range(TreeSet<T> basis, bool haslowend, T lowend, bool hashighend, T highend, EnumerationDirection direction)\r
-                       {\r
-                               this.basis = basis;\r
-                               stamp = basis.stamp;\r
-\r
-                               //lowind will be const; should we cache highind?\r
-                               this.lowend = lowend; //Inclusive\r
-                               this.highend = highend;//Exclusive\r
-                               this.haslowend = haslowend;\r
-                               this.hashighend = hashighend;\r
-                               this.direction = direction;\r
-                       }\r
-                       #region IEnumerable<T> Members\r
-\r
-\r
-                       #region TreeSet.Range.Enumerator nested class\r
-                       \r
-                       public class Enumerator: MSG.IEnumerator<T>\r
-                       {\r
-                               #region Private Fields\r
-                               private bool valid = false, ready = true;\r
-\r
-                               private IComparer<T> comparer;\r
-\r
-                               private T current;\r
-#if BAG\r
-                               int togo;\r
-#endif\r
-\r
-                               private Node cursor;\r
-\r
-                               private Node[] path; // stack of nodes\r
-\r
-                               private int level = 0;\r
-\r
-                               private Range range;\r
-\r
-                               private bool forwards;\r
-\r
-                               #endregion\r
-                               [Tested]\r
-                               public Enumerator(Range range)\r
-                               {\r
-                                       comparer = range.basis.comparer;\r
-                                       path = new Node[2 * range.basis.blackdepth];\r
-                                       this.range = range;\r
-                                       forwards = range.direction == EnumerationDirection.Forwards;\r
-                                       cursor = new Node();\r
-                                       if (forwards)\r
-                                               cursor.right = range.basis.root;\r
-                                       else\r
-                                               cursor.left = range.basis.root;\r
-                                       range.basis.modifycheck(range.stamp);\r
-                               }\r
-\r
-\r
-                               int compare(T i1, T i2) { return comparer.Compare(i1, i2); }\r
-\r
-\r
-                               /// <summary>\r
-                               /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
-                               /// </summary>\r
-                               /// <value>The current value of the enumerator.</value>\r
-                               [Tested]\r
-                               public T Current\r
-                               {\r
-                                       [Tested]\r
-                                       get\r
-                                       {\r
-                                               if (valid)\r
-                                                       return current;\r
-                                               else\r
-                                                       throw new InvalidOperationException();\r
-                                       }\r
-                               }\r
-\r
-\r
-                               //Maintain a stack of nodes that are roots of\r
-                               //subtrees not completely exported yet. Invariant:\r
-                               //The stack nodes together with their right subtrees\r
-                               //consists of exactly the items we have not passed\r
-                               //yet (the top of the stack holds current item).\r
-                               /// <summary>\r
-                               /// Move enumerator to next item in tree, or the first item if\r
-                               /// this is the first call to MoveNext. \r
-                               /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
-                               /// </summary>\r
-                               /// <returns>True if enumerator is valid now</returns>\r
-                               [Tested]\r
-                               public bool MoveNext()\r
-                               {\r
-                                       range.basis.modifycheck(range.stamp);\r
-                                       if (!ready)\r
-                                               return false;\r
-#if BAG\r
-                                       if (--togo> 0)\r
-                                               return true;\r
-#endif\r
-                                       if (forwards)\r
-                                       {\r
-                                               if (!valid && range.haslowend)\r
-                                               {\r
-                                                       cursor = cursor.right;\r
-                                                       while (cursor != null)\r
-                                                       {\r
-                                                               int comp = compare(cursor.item, range.lowend);\r
-\r
-                                                               if (comp > 0)\r
-                                                               {\r
-                                                                       path[level++] = cursor;\r
-#if NCP\r
-                                                                       cursor = range.basis.left(cursor);\r
-#else\r
-                                                                       cursor = cursor.left;\r
-#endif\r
-                                                               }\r
-                                                               else if (comp < 0)\r
-                                                               {\r
-#if NCP\r
-                                                                       cursor = range.basis.right(cursor);\r
-#else\r
-                                                                       cursor = cursor.right;\r
-#endif\r
-                                                               }\r
-                                                               else\r
-                                                               {\r
-                                                                       path[level] = cursor;\r
-                                                                       break;\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       if (cursor == null)\r
-                                                       {\r
-                                                               if (level == 0)\r
-                                                                       return valid = ready = false;\r
-                                                               else\r
-                                                                       cursor = path[--level];\r
-                                                       }\r
-                                               }\r
-#if NCP\r
-                                               else if (range.basis.right(cursor) != null)\r
-                                               {\r
-                                                       path[level] = cursor = range.basis.right(cursor);\r
-\r
-                                                       Node next = range.basis.left(cursor);\r
-\r
-                                                       while (next != null)\r
-                                                       {\r
-                                                               path[++level] = cursor = next;\r
-                                                               next = range.basis.left(cursor);\r
-                                                       }\r
-                                               }\r
-#else\r
-                                               else if (cursor.right != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.right;\r
-                                                       while (cursor.left != null)\r
-                                                               path[++level] = cursor = cursor.left;\r
-                                               }\r
-#endif\r
-                                               else if (level == 0)\r
-                                                       return valid = ready = false;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-                                               if (range.hashighend && compare(current, range.highend) >= 0)\r
-                                                       return valid = ready = false;\r
-\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                               return valid = true;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               if (!valid && range.hashighend)\r
-                                               {\r
-                                                       cursor = cursor.left;\r
-                                                       while (cursor != null)\r
-                                                       {\r
-                                                               int comp = compare(cursor.item, range.highend);\r
-\r
-                                                               if (comp < 0)\r
-                                                               {\r
-                                                                       path[level++] = cursor;\r
-#if NCP\r
-                                                                       cursor = range.basis.right(cursor);\r
-#else\r
-                                                                       cursor = cursor.right;\r
-#endif\r
-                                                               }\r
-                                                               else\r
-                                                               {\r
-#if NCP\r
-                                                                       cursor = range.basis.left(cursor);\r
-#else\r
-                                                                       cursor = cursor.left;\r
-#endif\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       if (cursor == null)\r
-                                                       {\r
-                                                               if (level == 0)\r
-                                                                       return valid = ready = false;\r
-                                                               else\r
-                                                                       cursor = path[--level];\r
-                                                       }\r
-                                               }\r
-#if NCP\r
-                                               else if (range.basis.left(cursor) != null)\r
-                                               {\r
-                                                       path[level] = cursor = range.basis.left(cursor);\r
-\r
-                                                       Node next = range.basis.right(cursor);\r
-\r
-                                                       while (next != null)\r
-                                                       {\r
-                                                               path[++level] = cursor = next;\r
-                                                               next = range.basis.right(cursor);\r
-                                                       }\r
-                                               }\r
-#else\r
-                                               else if (cursor.left != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.left;\r
-                                                       while (cursor.right != null)\r
-                                                               path[++level] = cursor = cursor.right;\r
-                                               }\r
-#endif\r
-                                               else if (level == 0)\r
-                                                       return valid = ready = false;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-                                               if (range.haslowend && compare(current, range.lowend) < 0)\r
-                                                       return valid = ready = false;\r
-\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                               return valid = true;\r
-                                       }\r
-                               }\r
-\r
-                               void SC.IEnumerator.Reset ()\r
-                               {\r
-                                       throw new NotImplementedException ();\r
-                               }\r
-\r
-                               object SC.IEnumerator.Current {\r
-                                       get {\r
-                                               return Current;\r
-                                       }\r
-                               }\r
-\r
-                               [Tested]\r
-                               public void Dispose()\r
-                               {\r
-                                       comparer = null;\r
-                                       current = default(T);\r
-                                       cursor = null;\r
-                                       path = null;\r
-                                       range = null;\r
-                               }\r
-                       }\r
-\r
-                       #endregion\r
-\r
-                       [Tested]\r
-                       public override MSG.IEnumerator<T> GetEnumerator() { return new Enumerator(this); }\r
-\r
-\r
-                       [Tested]\r
-                       public EnumerationDirection Direction { [Tested]get { return direction; } }\r
-\r
-\r
-                       #endregion\r
-\r
-                       #region Utility\r
-                       \r
-                       bool inside(T item)\r
-                       {\r
-                return (!haslowend || basis.comparer.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer.Compare(item, highend) < 0);\r
-            }\r
-\r
-\r
-                       void checkstamp()\r
-                       {\r
-                               if (stamp < basis.stamp)\r
-                                       throw new InvalidOperationException("Base collection was modified behind my back!");\r
-                       }\r
-\r
-\r
-                       void syncstamp() { stamp = basis.stamp; }\r
-                       \r
-                       #endregion\r
-\r
-                       [Tested]\r
-                       public IDirectedCollectionValue<T> Backwards()\r
-                       {\r
-                               Range b = (Range)MemberwiseClone();\r
-\r
-                               b.direction = direction == EnumerationDirection.Forwards ? EnumerationDirection.Backwards : EnumerationDirection.Forwards;\r
-                               return b;\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
-\r
-\r
-                       [Tested]\r
-                       public override int Count\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       return haslowend ? (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : (hashighend ? basis.CountTo(highend) : basis.Count);\r
-                               }\r
-                       }\r
-\r
-            //TODO: check that this is correct\r
-            public override Speed CountSpeed { get { return Speed.Log; } }\r
-\r
-        }\r
-\r
-               #endregion\r
-\r
-               #region fixheight utility\r
-\r
-#if MAINTAIN_HEIGHT\r
-               public void fixheight(Node n)\r
-               {\r
-                       int lh = n.left == null ? 0 : n.left.height + 1;\r
-                       int rh = n.right == null ? 0 : n.right.height + 1;\r
-\r
-                       n.height = (short)(lh > rh ? lh : rh);\r
-               }\r
-#endif\r
-\r
-               #endregion\r
-\r
-               #region Diagnostics\r
-               /// <summary>\r
-               /// Display this node on the console, and recursively its subnodes.\r
-               /// </summary>\r
-               /// <param name="n">Node to display</param>\r
-               /// <param name="space">Indentation</param>\r
-               private void minidump(Node n, string space)\r
-               {\r
-                       if (n == null)\r
-                       {\r
-                               //      System.Console.WriteLine(space + "null");\r
-                       }\r
-                       else\r
-                       {\r
-                               minidump(n.right, space + "  ");\r
-                               Console.WriteLine(String.Format("{0} {4} (rank={5}, size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, \r
-#if MAINTAIN_SIZE\r
-                               n.size, \r
-#else\r
-                               0,\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               n.height, \r
-#else\r
-                               0,\r
-#endif\r
-#if NCP\r
-                               n.generation, \r
-#endif\r
-                               n.red ? "RED" : "BLACK", \r
-#if MAINTAIN_RANK\r
-                               n.rank, \r
-#else\r
-                               0,\r
-#endif\r
-#if TRACE_ID\r
-                                       n.id,\r
-#else\r
-                               0,\r
-#endif\r
-#if NCP\r
-#if SEPARATE_EXTRA\r
-                               n.extra == null ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.extra.lastgeneration, n.extra.leftnode ? "L" : "R", n.extra.oldref == null ? "()" : "" + n.extra.oldref.item),\r
-#else\r
-                               n.lastgeneration == -1 ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item),\r
-#endif\r
-#else\r
-                               "",\r
-#endif\r
-#if BAG\r
-                               n.items\r
-#else\r
-                               1\r
-#endif\r
-                               ));\r
-                               minidump(n.left, space + "  ");\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Print the tree structure to the console stdout.\r
-               /// </summary>\r
-               [Tested(via = "Sawtooth")]\r
-               public void dump() { dump(""); }\r
-\r
-\r
-               /// <summary>\r
-               /// Print the tree structure to the console stdout.\r
-               /// </summary>\r
-               [Tested(via = "Sawtooth")]\r
-               public void dump(string msg)\r
-               {\r
-                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
-#if MAINTAIN_HEIGHT\r
-                       depth\r
-#else\r
-                       0\r
-#endif\r
-                       , \r
-#if NCP\r
-                       generation\r
-#endif\r
-                       ));\r
-                       minidump(root, "");\r
-                       check("", Console.Out); Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Display this tree on the console.\r
-               /// </summary>\r
-               /// <param name="msg">Identifying string of this call to dump</param>\r
-               /// <param name="err">Extra (error)message to include</param>\r
-               void dump(string msg, string err)\r
-               {\r
-                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
-#if MAINTAIN_HEIGHT\r
-                       depth\r
-#else\r
-                       0\r
-#endif\r
-                       ,  \r
-#if NCP\r
-                       generation                              \r
-#endif\r
-                       ));\r
-                       minidump(root, ""); Console.Write(err);\r
-                       Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Print warning m on o if b is false.\r
-               /// </summary>\r
-               /// <param name="b">Condition that should hold</param>\r
-               /// <param name="n">Place (used for id display)</param>\r
-               /// <param name="m">Message</param>\r
-               /// <param name="o">Output stream</param>\r
-               /// <returns>b</returns>\r
-               bool massert(bool b, Node n, string m, System.IO.TextWriter o)\r
-               {\r
-                       if (!b) o.WriteLine("*** Node (item={0}, id={1}): {2}", n.item, \r
-#if TRACE_ID\r
-                               n.id\r
-#else\r
-                               0\r
-#endif\r
-                               , m);\r
-\r
-                       return b;\r
-               }\r
-\r
-\r
-               bool rbminicheck(Node n, bool redp, int prank, System.IO.TextWriter o, out T min, out T max, out int blackheight, int maxgen)\r
-               {//Red-Black invariant\r
-                       bool res = true;\r
-\r
-                       res = massert(!(n.red && redp), n, "RED parent of RED node", o) && res;\r
-                       res = massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty", o) && res;\r
-                       res = massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty", o) && res;\r
-#if MAINTAIN_RANK\r
-                       res = massert(n.red == (n.rank == prank), n, "Bad color", o) && res;\r
-                       res = massert(prank <= n.rank + 1, n, "Parentrank-rank >= 2", o) && res;\r
-                       res = massert((n.left != null && n.right != null) || n.rank == 1, n, "Rank>1 but empty child", o) && res;\r
-#endif\r
-#if BAG\r
-                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
-\r
-                       res = massert(sb, n, "Bad size", o) && res;\r
-#elif MAINTAIN_SIZE\r
-                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
-\r
-                       res = massert(sb, n, "Bad size", o) && res;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                       int lh = n.left == null ? 0 : n.left.height + 1;\r
-                       int rh = n.right == null ? 0 : n.right.height + 1;\r
-\r
-                       res = massert(n.height == (lh < rh ? rh : lh), n, "Bad height", o) && res;\r
-#endif\r
-                       int therank =\r
-#if MAINTAIN_RANK\r
-                       n.rank;\r
-#else\r
-                       0;\r
-#endif\r
-                       min = max = n.item;\r
-\r
-                       T otherext;\r
-                       int lbh = 0, rbh = 0;\r
-\r
-                       if (n.left != null)\r
-                       {\r
-                               res = rbminicheck(n.left, n.red, therank, o, out min, out otherext, out lbh, generation) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
-            }\r
-\r
-                       if (n.right != null)\r
-                       {\r
-                               res = rbminicheck(n.right, n.red, therank, o, out otherext, out max, out rbh, generation) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
-            }\r
-\r
-                       res = massert(rbh == lbh, n, "Different blackheights of children", o) && res;\r
-                       blackheight = n.red ? rbh : rbh + 1;\r
-#if MAINTAIN_RANK\r
-                       //The rank is the number of black nodes from this one to\r
-                       //the leaves, not counting this one, but counting 1 for the empty\r
-                       //virtual leaf nodes.\r
-                       res = massert(n.rank == rbh + 1, n, "rank!=blackheight " + blackheight, o) && res;\r
-#endif\r
-                       return res;\r
-               }\r
-\r
-\r
-\r
-\r
-#if NCP\r
-\r
-               bool rbminisnapcheck(Node n, System.IO.TextWriter o, out int size, out T min, out T max)\r
-               {\r
-                       bool res = true;\r
-\r
-                       min = max = n.item;\r
-\r
-                       int lsz = 0, rsz = 0;\r
-                       T otherext;\r
-#if SEPARATE_EXTRA\r
-                       Node.Extra extra = n.extra;\r
-                       Node child = (extra != null && extra.lastgeneration >= treegen && extra.leftnode) ? extra.oldref : n.left;\r
-#else\r
-                       Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left;\r
-#endif\r
-                       if (child != null)\r
-                       {\r
-                               res = rbminisnapcheck(child, o, out lsz, out min, out otherext) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
-            }\r
-\r
-#if SEPARATE_EXTRA\r
-                       child = (extra != null && extra.lastgeneration >= treegen && !extra.leftnode) ? extra.oldref : n.right;\r
-#else\r
-                       child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right;\r
-#endif\r
-                       if (child != null)\r
-                       {\r
-                               res = rbminisnapcheck(child, o, out rsz, out otherext, out max) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
-            }\r
-#if BAG\r
-                       size = n.items + lsz + rsz;\r
-#else\r
-                       size = 1 + lsz + rsz;\r
-#endif\r
-                       return res;\r
-               }\r
-#endif\r
-\r
-               /// <summary>\r
-               /// Checks red-black invariant. Dumps tree to console if bad\r
-               /// </summary>\r
-               /// <param name="name">Title of dump</param>\r
-               /// <returns>false if invariant violation</returns>\r
-               [Tested(via = "Sawtooth")]\r
-               public bool Check(string name)\r
-               {\r
-                       System.Text.StringBuilder e = new System.Text.StringBuilder();\r
-                       System.IO.TextWriter o = new System.IO.StringWriter(e);\r
-\r
-                       if (!check(name, o))\r
-                               return true;\r
-                       else\r
-                       {\r
-                               dump(name, e.ToString());\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Checks red-black invariant. Dumps tree to console if bad\r
-               /// </summary>\r
-               /// <returns>false if invariant violation</returns>\r
-               [Tested]\r
-               public bool Check()\r
-               {\r
-                       //return check("", System.IO.TextWriter.Null);\r
-                       //Console.WriteLine("bamse");\r
-                       return Check("-");\r
-               }\r
-\r
-\r
-               bool check(string msg, System.IO.TextWriter o)\r
-               {\r
-                       if (root != null)\r
-                       {\r
-                               T max, min;\r
-                               int blackheight;\r
-#if NCP\r
-                               if (isSnapShot)\r
-                               {\r
-                                       //Console.WriteLine("Im'a snapshot");\r
-                                       int thesize;\r
-                                       bool rv = rbminisnapcheck(root, o, out thesize, out min, out max);\r
-\r
-                                       rv = massert(size == thesize, root, "bad snapshot size", o) && rv;\r
-                                       return !rv;\r
-                               }\r
-#endif\r
-#if MAINTAIN_RANK\r
-                               bool res = rbminicheck(root, false, root.rank + 1, o, out min, out max, out blackheight, generation);\r
-\r
-                               res = massert(root.rank == blackdepth, root, "blackdepth!=root.rank", o) && res;\r
-#else\r
-                               bool res = rbminicheck(root, false, 0, o, out min, out max, out blackheight, generation);\r
-#endif\r
-                               res = massert(blackheight == blackdepth, root, "bad blackh/d", o) && res;\r
-                               res = massert(!root.red, root, "root is red", o) && res;\r
-#if MAINTAIN_SIZE\r
-                               res = massert(root.size == size, root, "count!=root.size", o) && res;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               res = massert(root.height == depth, root, "depth!=root.height", o) && res;\r
-#endif\r
-                               return !res;\r
-                       }\r
-                       else\r
-                               return false;\r
-               }\r
-               #endregion                      \r
-       }\r
-}\r
-\r
-#endif\r
diff --git a/mcs/class/Mono.C5/trees/RedBlackTreeBag.cs b/mcs/class/Mono.C5/trees/RedBlackTreeBag.cs
deleted file mode 100644 (file)
index 21050b9..0000000
+++ /dev/null
@@ -1,4329 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-#define MAINTAIN_SIZE\r
-#define MAINTAIN_RANKnot\r
-#define MAINTAIN_HEIGHTnot\r
-#define BAG\r
-#define NCP\r
-\r
-#define MAINTAIN_EXTREMAnot\r
-#define TRACE_IDnot\r
-\r
-#if BAG\r
-#if !MAINTAIN_SIZE\r
-#error  BAG defined without MAINTAIN_SIZE!\r
-#endif\r
-#endif\r
-\r
-\r
-using System;\r
-using MSG = System.Collections.Generic;\r
-using SC = System.Collections;\r
-\r
-// NOTE NOTE NOTE NOTE\r
-// This source file is used to produce both TreeBag<T> and TreeBag<T>\r
-// It should be copied to a file called TreeBag.cs in which all code mentions of \r
-// TreeBag is changed to TreeBag and the preprocessor symbol BAG is defined.\r
-// NOTE: there may be problems with documentation comments.\r
-\r
-namespace C5\r
-{\r
-#if BAG\r
-       /// <summary>\r
-       /// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics,\r
-       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. (<see cref="T:C5.TreeBag!1"/> for an \r
-       /// implementation with set semantics).\r
-       /// <br/>\r
-       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
-       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
-       /// be external and supplied by the user in the constructor.\r
-       /// <br/>\r
-       /// Each distinct item is only kept in one place in the tree - together with the number\r
-       /// of times it is a member of the bag. Thus, if two items that are equal according\r
-       /// </summary>\r
-#else\r
-       /// <summary>\r
-       /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics,\r
-       /// cf. <a href="litterature.htm#CLRS">CLRS</a>. <see cref="T:C5.TreeBag!1"/> for a version \r
-       /// with bag semantics. <see cref="T:C5.TreeDictionary!2"/> for a sorted dictionary \r
-       /// based on this tree implementation.\r
-       /// <p>\r
-       /// The comparer (sorting order) may be either natural, because the item type is comparable \r
-       /// (generic: <see cref="T:C5.IComparable!1"/> or non-generic: System.IComparable) or it can\r
-       /// be external and supplied by the user in the constructor.</p>\r
-       ///\r
-       /// <p><i>TODO: describe performance here</i></p>\r
-       /// <p><i>TODO: discuss persistence and its useful usage modes. Warn about the space\r
-       /// leak possible with other usage modes.</i></p>\r
-       /// </summary>\r
-#endif\r
-       public class TreeBag<T>: SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>\r
-       {\r
-               #region Feature\r
-               /// <summary>\r
-               /// A debugging aid for making the selected compilation alternatives \r
-               /// available to the user. (To be removed when selection is finally fixed\r
-               /// for production version).\r
-               /// </summary>\r
-               [Flags]\r
-               public enum Feature: short\r
-               {\r
-                       /// <summary>\r
-                       /// Nothing\r
-                       /// </summary>\r
-                       Dummy = 0,\r
-                       /// <summary>\r
-                       /// Node copy persistence as explained in <a href="litterature.htm#Tarjan1">Tarjan1</a>\r
-                       /// </summary>\r
-                       NodeCopyPersistence = 2,\r
-                       /// <summary>\r
-                       /// Maintain sub tree sizes\r
-                       /// </summary>\r
-                       Sizes = 4,\r
-                       /// <summary>\r
-                       /// Maintain precise node heights\r
-                       /// </summary>\r
-                       Heights = 8,\r
-                       /// <summary>\r
-                       /// Maintain node ranks (~ black height)\r
-                       /// </summary>\r
-                       Ranks = 16,\r
-                       /// <summary>\r
-                       /// Maintain unique ids on tree nodes.\r
-                       /// </summary>\r
-                       Traceid = 32\r
-               }\r
-\r
-\r
-\r
-               static Feature features = Feature.Dummy\r
-#if NCP\r
-               | Feature.NodeCopyPersistence\r
-#endif\r
-#if MAINTAIN_RANK\r
-                       |Feature.Ranks\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                       |Feature.Heights\r
-#endif\r
-#if MAINTAIN_SIZE\r
-               | Feature.Sizes\r
-#endif\r
-#if TRACE_ID\r
-               | Feature.Traceid\r
-#endif\r
-               ;\r
-\r
-\r
-               /// <summary>\r
-               /// A debugging aid for making the selected compilation alternatives \r
-               /// available to the user. (To be removed when selection is finally fixed\r
-               /// for production version).\r
-               /// </summary>\r
-               public static Feature Features { get { return features; } }\r
-\r
-               #endregion\r
-\r
-               #region Fields\r
-\r
-               IComparer<T> comparer;\r
-\r
-               Node root;\r
-\r
-               int blackdepth = 0;\r
-\r
-               //We double these stacks for the iterative add and remove on demand\r
-               private int[] dirs = new int[2];\r
-\r
-               private Node[] path = new Node[2];\r
-#if NCP\r
-               private bool isSnapShot = false;\r
-\r
-               private SnapData snapdata;\r
-\r
-               private int generation;\r
-\r
-               private int maxsnapid = -1;\r
-\r
-#endif\r
-#if MAINTAIN_EXTREMA\r
-               T min, max;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-               private short depth = 0;\r
-#endif\r
-               #endregion\r
-\r
-               #region Util\r
-\r
-               /// <summary>\r
-               /// Fetch the left child of n taking node-copying persistence into\r
-               /// account if relevant. \r
-               /// </summary>\r
-               /// <param name="n"></param>\r
-               /// <returns></returns>\r
-               private Node left(Node n)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                       {\r
-#if SEPARATE_EXTRA\r
-                               Node.Extra e = n.extra;\r
-\r
-                               if (e != null && e.lastgeneration >= treegen && e.leftnode)\r
-                                       return e.oldref;\r
-#else\r
-                               if (n.lastgeneration >= generation && n.leftnode)\r
-                                       return n.oldref;\r
-#endif\r
-                       }\r
-#endif\r
-                       return n.left;\r
-               }\r
-\r
-\r
-               private Node right(Node n)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                       {\r
-#if SEPARATE_EXTRA\r
-                               Node.Extra e = n.extra;\r
-\r
-                               if (e != null && e.lastgeneration >= treegen && !e.leftnode)\r
-                                       return e.oldref;\r
-#else\r
-                               if (n.lastgeneration >= generation && !n.leftnode)\r
-                                       return n.oldref;\r
-#endif\r
-                       }\r
-#endif\r
-                       return n.right;\r
-               }\r
-\r
-\r
-               //This method should be called by methods that use the internal \r
-               //traversal stack, unless certain that there is room enough\r
-               private void stackcheck()\r
-               {\r
-                       while (dirs.Length < 2 * blackdepth)\r
-                       {\r
-                               dirs = new int[2 * dirs.Length];\r
-                               path = new Node[2 * dirs.Length];\r
-                       }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Node nested class\r
-                       \r
-\r
-               /// <summary>\r
-               /// The type of node in a Red-Black binary tree\r
-               /// </summary>\r
-               class Node\r
-               {\r
-                       public bool red = true;\r
-\r
-                       public T item;\r
-\r
-                       public Node left;\r
-\r
-                       public Node right;\r
-\r
-#if MAINTAIN_SIZE\r
-                       public int size = 1;\r
-#endif\r
-\r
-#if BAG\r
-                       public int items = 1;\r
-#endif\r
-\r
-#if MAINTAIN_HEIGHT\r
-                       public short height; \r
-#endif\r
-\r
-#if MAINTAIN_RANK\r
-                       public short rank = 1;\r
-#endif\r
-\r
-#if TRACE_ID\r
-                       public int id = sid++;\r
-                       public static int sid = 0;\r
-#endif\r
-\r
-#if NCP\r
-                       public int generation;\r
-#if SEPARATE_EXTRA\r
-                       internal class Extra\r
-                       {\r
-                               public int lastgeneration;\r
-\r
-                               public Node oldref;\r
-\r
-                               public bool leftnode;\r
-\r
-                               //public Node next;\r
-                       }\r
-\r
-                       public Extra extra;\r
-\r
-#else\r
-                       public int lastgeneration = -1;\r
-\r
-                       public Node oldref;\r
-\r
-                       public bool leftnode;\r
-#endif\r
-\r
-                       /// <summary>\r
-                       /// Update a child pointer\r
-                       /// </summary>\r
-                       /// <param name="cursor"></param>\r
-                       /// <param name="leftnode"></param>\r
-                       /// <param name="child"></param>\r
-                       /// <param name="maxsnapid"></param>\r
-                       /// <param name="generation"></param>\r
-                       /// <returns>True if node was *copied*</returns>\r
-                       internal static bool update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation)\r
-                       {\r
-                               Node oldref = leftnode ? cursor.left : cursor.right;\r
-\r
-                               if (child == oldref)\r
-                                       return false;\r
-\r
-                               bool retval = false;\r
-\r
-                               if (cursor.generation <= maxsnapid)\r
-                               { \r
-#if SEPARATE_EXTRA\r
-                                       if (cursor.extra == null)\r
-                                       {\r
-                                               Extra extra = cursor.extra = new Extra();       \r
-\r
-                                               extra.leftnode = leftnode;\r
-                                               extra.lastgeneration = maxsnapid;\r
-                                               extra.oldref = oldref;\r
-                                       }\r
-                                       else if (cursor.extra.leftnode != leftnode || cursor.extra.lastgeneration < maxsnapid)\r
-#else\r
-                                       if (cursor.lastgeneration == -1)\r
-                                       {\r
-                                               cursor.leftnode = leftnode;\r
-                                               cursor.lastgeneration = maxsnapid;\r
-                                               cursor.oldref = oldref;\r
-                                       }\r
-                                       else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid)\r
-#endif\r
-                                       {\r
-                                               CopyNode(ref cursor, maxsnapid, generation);\r
-                                               retval = true;\r
-                                       }\r
-                               }\r
-\r
-                               if (leftnode)\r
-                                       cursor.left = child;\r
-                               else\r
-                                       cursor.right = child;\r
-\r
-                               return retval;\r
-                       }\r
-\r
-\r
-                       //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will \r
-                       //always be used in the old copy of cursor. Therefore, after \r
-                       //making the clone, we should update the old copy by restoring\r
-                       //the child pointer and setting extra to null.\r
-                       //OTOH then we cannot clean up unused Extra objects unless we link\r
-                       //them together in a doubly linked list.\r
-                       public static bool CopyNode(ref Node cursor, int maxsnapid, int generation)\r
-                       {\r
-                               if (cursor.generation <= maxsnapid)\r
-                               {\r
-                                       cursor = (Node)(cursor.MemberwiseClone());\r
-                                       cursor.generation = generation;\r
-#if SEPARATE_EXTRA\r
-                                       cursor.extra = null;\r
-#else\r
-                                       cursor.lastgeneration = -1;\r
-#endif\r
-#if TRACE_ID\r
-                                       cursor.id = sid++;\r
-#endif\r
-                                       return true;\r
-                               }\r
-                               else\r
-                                       return false;\r
-                       }\r
-\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-                       \r
-               /// <summary>\r
-               /// Create a red-black tree collection with natural comparer and item hasher.\r
-               /// </summary>\r
-               public TreeBag()\r
-               {\r
-                       comparer = ComparerBuilder.FromComparable<T>.Examine();\r
-                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a red-black tree collection with an external comparer (and natural item hasher,\r
-               /// assumed consistent).\r
-               /// </summary>\r
-               /// <param name="c">The external comparer</param>\r
-               public TreeBag(IComparer<T> c)\r
-               {\r
-                       comparer = c;\r
-                       itemhasher = HasherBuilder.ByPrototype<T>.Examine();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a red-black tree collection with an external comparer aand an external\r
-               /// item hasher, assumed consistent.\r
-               /// </summary>\r
-               /// <param name="c">The external comparer</param>\r
-               /// <param name="h">The external item hasher</param>\r
-               public TreeBag(IComparer<T> c, IHasher<T> h)\r
-               {\r
-                       comparer = c;\r
-                       itemhasher = h;\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region TreeBag.Enumerator nested class\r
-\r
-               /// <summary>\r
-               /// An enumerator for a red-black tree collection. Based on an explicit stack\r
-               /// of subtrees waiting to be enumerated. Currently only used for the tree set \r
-               /// enumerators (tree bag enumerators use an iterator block based enumerator).\r
-               /// </summary>\r
-               public class Enumerator: MSG.IEnumerator<T>\r
-               {\r
-                       #region Private Fields\r
-                       TreeBag<T> tree;\r
-\r
-                       bool valid = false;\r
-\r
-                       int stamp;\r
-\r
-                       T current;\r
-\r
-                       Node cursor;\r
-\r
-                       Node[] path; // stack of nodes\r
-\r
-                       int level = 0;\r
-                       #endregion\r
-                       /// <summary>\r
-                       /// Create a tree enumerator\r
-                       /// </summary>\r
-                       /// <param name="tree">The red-black tree to enumerate</param>\r
-                       public Enumerator(TreeBag<T> tree)\r
-                       {\r
-                               this.tree = tree;\r
-                               stamp = tree.stamp;\r
-                               path = new Node[2 * tree.blackdepth];\r
-                               cursor = new Node();\r
-                               cursor.right = tree.root;\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
-                       /// </summary>\r
-                       /// <value>The current item of the enumerator.</value>\r
-                       [Tested]\r
-                       public T Current\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       if (valid)\r
-                                               return current;\r
-                                       else\r
-                                               throw new InvalidOperationException();\r
-                               }\r
-                       }\r
-\r
-\r
-                       //Maintain a stack of nodes that are roots of\r
-                       //subtrees not completely exported yet. Invariant:\r
-                       //The stack nodes together with their right subtrees\r
-                       //consists of exactly the items we have not passed\r
-                       //yet (the top of the stack holds current item).\r
-                       /// <summary>\r
-                       /// Move enumerator to next item in tree, or the first item if\r
-                       /// this is the first call to MoveNext. \r
-                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
-                       /// </summary>\r
-                       /// <returns>True if enumerator is valid now</returns>\r
-                       [Tested]\r
-                       public bool MoveNext()\r
-                       {\r
-                               tree.modifycheck(stamp);\r
-                               if (cursor.right != null)\r
-                               {\r
-                                       path[level] = cursor = cursor.right;\r
-                                       while (cursor.left != null)\r
-                                               path[++level] = cursor = cursor.left;\r
-                               }\r
-                               else if (level == 0)\r
-                                       return valid = false;\r
-                               else\r
-                                       cursor = path[--level];\r
-\r
-                               current = cursor.item;\r
-                               return valid = true;\r
-                       }\r
-\r
-                       void SC.IEnumerator.Reset ()\r
-                       {\r
-                               throw new NotImplementedException ();\r
-                       }\r
-\r
-                       object SC.IEnumerator.Current {\r
-                               get {\r
-                                       return Current;\r
-                               }\r
-                       }\r
-\r
-                       #region IDisposable Members for Enumerator\r
-\r
-                       bool disposed;\r
-\r
-\r
-                       /// <summary>\r
-                       /// Call Dispose(true) and then suppress finalization of this enumerator.\r
-                       /// </summary>\r
-                       [Tested]\r
-                       public void Dispose()\r
-                       {\r
-                               Dispose(true);\r
-                               GC.SuppressFinalize(this);\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Remove the internal data (notably the stack array).\r
-                       /// </summary>\r
-                       /// <param name="disposing">True if called from Dispose(),\r
-                       /// false if called from the finalizer</param>\r
-                       protected virtual void Dispose(bool disposing)\r
-                       {\r
-                               if (!disposed)\r
-                               {\r
-                                       if (disposing)\r
-                                       {\r
-                                       }\r
-\r
-                                       current = default(T);\r
-                                       cursor = null;\r
-                                       path = null;\r
-                                       disposed = true;\r
-                               }\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Finalizer for enumeratir\r
-                       /// </summary>\r
-                       ~Enumerator()\r
-                       {\r
-                               Dispose(false);\r
-                       }\r
-                       #endregion\r
-\r
-               }\r
-#if NCP\r
-               /// <summary>\r
-               /// An enumerator for a snapshot of a node copy persistent red-black tree\r
-               /// collection.\r
-               /// </summary>\r
-               public class SnapEnumerator: MSG.IEnumerator<T>\r
-               {\r
-                       #region Private Fields\r
-                       TreeBag<T> tree;\r
-\r
-                       bool valid = false;\r
-\r
-                       int stamp;\r
-#if BAG\r
-                       int togo;\r
-#endif\r
-\r
-                       T current;\r
-\r
-                       Node cursor;\r
-\r
-                       Node[] path; // stack of nodes\r
-\r
-                       int level;\r
-                       #endregion\r
-\r
-                       /// <summary>\r
-                       /// Creta an enumerator for a snapshot of a node copy persistent red-black tree\r
-                       /// collection\r
-                       /// </summary>\r
-                       /// <param name="tree">The snapshot</param>\r
-                       public SnapEnumerator(TreeBag<T> tree)\r
-                       {\r
-                               this.tree = tree;\r
-                               stamp = tree.stamp;\r
-                               path = new Node[2 * tree.blackdepth];\r
-                               cursor = new Node();\r
-                               cursor.right = tree.root;\r
-                       }\r
-\r
-\r
-                       #region MSG.IEnumerator<T> Members\r
-\r
-                       /// <summary>\r
-                       /// Move enumerator to next item in tree, or the first item if\r
-                       /// this is the first call to MoveNext. \r
-                       /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
-                       /// </summary>\r
-                       /// <returns>True if enumerator is valid now</returns>\r
-                       [Tested]\r
-                       public bool MoveNext()\r
-                       {\r
-                               tree.modifycheck(stamp);//???\r
-\r
-#if BAG\r
-                               if (--togo>0)\r
-                                       return true;\r
-#endif\r
-                               Node next = tree.right(cursor);\r
-\r
-                               if (next != null)\r
-                               {\r
-                                       path[level] = cursor = next;\r
-                                       next = tree.left(cursor);\r
-                                       while (next != null)\r
-                                       {\r
-                                               path[++level] = cursor = next;\r
-                                               next = tree.left(cursor);\r
-                                       }\r
-                               }\r
-                               else if (level == 0)\r
-                                       return valid = false;\r
-                               else\r
-                                       cursor = path[--level];\r
-\r
-#if BAG\r
-                               togo = cursor.items;\r
-#endif\r
-                               current = cursor.item;\r
-                               return valid = true;\r
-                       }\r
-\r
-\r
-                       /// <summary>\r
-                       /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
-                       /// </summary>\r
-                       /// <value>The current value of the enumerator.</value>\r
-                       [Tested]\r
-                       public T Current\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       if (valid)\r
-                                               return current;\r
-                                       else\r
-                                               throw new InvalidOperationException();\r
-                               }\r
-                       }\r
-\r
-                       #endregion\r
-\r
-                       void SC.IEnumerator.Reset ()\r
-                       {\r
-                               throw new NotImplementedException ();\r
-                       }\r
-\r
-                       object SC.IEnumerator.Current {\r
-                               get {\r
-                                       return Current;\r
-                               }\r
-                       }\r
-\r
-                       #region IDisposable Members\r
-\r
-                       [Tested]\r
-                       void System.IDisposable.Dispose()\r
-                       {\r
-                               tree = null;\r
-                               valid = false;\r
-                               current = default(T);\r
-                               cursor = null;\r
-                               path = null;\r
-                       }\r
-\r
-                       #endregion\r
-               }\r
-#endif\r
-               #endregion\r
-\r
-               #region IEnumerable<T> Members\r
-\r
-               private MSG.IEnumerator<T> getEnumerator(Node node, int origstamp)\r
-               {\r
-                       if (node == null)\r
-                               yield break;\r
-\r
-                       if (node.left != null)\r
-                       {\r
-                               MSG.IEnumerator<T> child = getEnumerator(node.left, origstamp);\r
-\r
-                               while (child.MoveNext())\r
-                               {\r
-                                       modifycheck(origstamp);\r
-                                       yield return child.Current;\r
-                               }\r
-                       }\r
-#if BAG\r
-                       int togo = node.items;\r
-                       while (togo-- > 0)\r
-                       {\r
-                               modifycheck(origstamp);\r
-                               yield return node.item;\r
-                       }\r
-#else\r
-                       modifycheck(origstamp);\r
-                       yield return node.item;\r
-#endif\r
-                       if (node.right != null)\r
-                       {\r
-                               MSG.IEnumerator<T> child = getEnumerator(node.right, origstamp);\r
-\r
-                               while (child.MoveNext())\r
-                               {\r
-                                       modifycheck(origstamp);\r
-                                       yield return child.Current;\r
-                               }\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create an enumerator for this tree\r
-               /// </summary>\r
-               /// <returns>The enumerator</returns>\r
-               [Tested]\r
-               public override MSG.IEnumerator<T> GetEnumerator()\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               return new SnapEnumerator(this);\r
-#endif\r
-#if BAG\r
-                       return getEnumerator(root,stamp);\r
-#else\r
-                       return new Enumerator(this);\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISink<T> Members\r
-                       \r
-               /// <summary>\r
-               /// Add item to tree. If already there, return the found item in the second argument.\r
-               /// </summary>\r
-               /// <param name="item">Item to add</param>\r
-        /// <param name="founditem">item found</param>\r
-        /// <param name="update">whether item in node should be updated</param>\r
-        /// <param name="wasfound">true if found in bag, false if not found or tre is a set</param>\r
-        /// <returns>True if item was added</returns>\r
-        bool addIterative(T item, ref T founditem, bool update, out bool wasfound)\r
-        {\r
-            wasfound = false;\r
-            if (root == null)\r
-                       {\r
-                               root = new Node();\r
-                               root.red = false;\r
-                               blackdepth = 1;\r
-#if MAINTAIN_EXTREMA\r
-                               root.item = min = max = item;\r
-#else\r
-                               root.item = item;\r
-#endif\r
-#if NCP\r
-                               root.generation = generation;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = 0;\r
-#endif\r
-                               return true;\r
-                       }\r
-\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (true)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp == 0)\r
-                               {\r
-                    founditem = cursor.item;\r
-\r
-#if BAG\r
-                    wasfound = true;\r
-#if NCP\r
-                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                                       cursor.items++;\r
-                                       cursor.size++;\r
-                                       if (update)\r
-                                               cursor.item = item;\r
-\r
-                                       update = true;\r
-\r
-#else\r
-                    if (update)\r
-                    {\r
-#if NCP\r
-                        Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                        cursor.item = item;\r
-                    }\r
-#endif\r
-\r
-                    while (level-- > 0)\r
-                    {\r
-                        if (update)\r
-                                               {\r
-                                                       Node kid = cursor;\r
-\r
-                                                       cursor = path[level];\r
-#if NCP\r
-                                                       Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
-#endif\r
-#if BAG\r
-                                                       cursor.size++;\r
-#endif\r
-                                               }\r
-\r
-                                               path[level] = null;\r
-                                       }\r
-#if BAG\r
-                                       return true;\r
-#else\r
-                                       if (update)\r
-                                               root = cursor;\r
-\r
-                                       return false;\r
-#endif\r
-                               }\r
-\r
-                               //else\r
-                               Node child = comp > 0 ? cursor.left : cursor.right;\r
-\r
-                               if (child == null)\r
-                               {\r
-                                       child = new Node();\r
-                                       child.item = item;\r
-#if NCP\r
-                                       child.generation = generation;\r
-                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
-#else\r
-                                       if (comp > 0) { cursor.left = child; }\r
-                                       else { cursor.right = child; }\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                                       cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                                       dirs[level] = comp;\r
-                                       break;\r
-                               }\r
-                               else\r
-                               {\r
-                                       dirs[level] = comp;\r
-                                       path[level++] = cursor;\r
-                                       cursor = child;\r
-                               }\r
-                       }\r
-\r
-                       //We have just added the red node child to "cursor"\r
-                       while (cursor.red)\r
-                       {\r
-                               //take one step up:\r
-                               Node child = cursor;\r
-\r
-                               cursor = path[--level];\r
-                               path[level] = null;\r
-#if NCP\r
-                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                               cursor.size++;\r
-#endif\r
-                               int comp = dirs[level];\r
-                               Node childsibling = comp > 0 ? cursor.right : cursor.left;\r
-\r
-                               if (childsibling != null && childsibling.red)\r
-                               {\r
-                                       //Promote\r
-#if MAINTAIN_RANK\r
-                                       cursor.rank++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                                       child.red = false;\r
-#if NCP\r
-                                       Node.update(ref cursor, comp < 0, childsibling, maxsnapid, generation);\r
-#endif\r
-                                       childsibling.red = false;\r
-\r
-                                       //color cursor red & take one step up the tree unless at root\r
-                                       if (level == 0)\r
-                                       {\r
-                                               root = cursor;\r
-                                               blackdepth++;\r
-                                               return true;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               cursor.red = true;\r
-#if NCP\r
-                                               child = cursor;\r
-                                               cursor = path[--level];\r
-                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-                                               path[level] = null;\r
-#if MAINTAIN_SIZE\r
-                                               cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       //ROTATE!!!\r
-                                       int childcomp = dirs[level + 1];\r
-\r
-                                       cursor.red = true;\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               if (childcomp > 0)\r
-                                               {//zagzag\r
-#if NCP\r
-                                                       Node.update(ref cursor, true, child.right, maxsnapid, generation);\r
-                                                       Node.update(ref child, false, cursor, maxsnapid, generation);\r
-#else\r
-                                                       cursor.left = child.right;\r
-                                                       child.right = cursor;\r
-#endif\r
-                                                       cursor = child;\r
-                                               }\r
-                                               else\r
-                                               {//zagzig\r
-                                                       Node badgrandchild = child.right;\r
-#if NCP\r
-                                                       Node.update(ref cursor, true, badgrandchild.right, maxsnapid, generation);\r
-                                                       Node.update(ref child, false, badgrandchild.left, maxsnapid, generation);\r
-                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
-#else\r
-                                                       cursor.left = badgrandchild.right;\r
-                                                       child.right = badgrandchild.left;\r
-#endif\r
-                                                       badgrandchild.left = child;\r
-                                                       badgrandchild.right = cursor;\r
-                                                       cursor = badgrandchild;\r
-                                               }\r
-                                       }\r
-                                       else\r
-                                       {//comp < 0\r
-                                               if (childcomp < 0)\r
-                                               {//zigzig\r
-#if NCP\r
-                                                       Node.update(ref cursor, false, child.left, maxsnapid, generation);\r
-                                                       Node.update(ref child, true, cursor, maxsnapid, generation);\r
-#else\r
-                                                       cursor.right = child.left;\r
-                                                       child.left = cursor;\r
-#endif\r
-                                                       cursor = child;\r
-                                               }\r
-                                               else\r
-                                               {//zigzag\r
-                                                       Node badgrandchild = child.left;\r
-#if NCP\r
-                                                       Node.update(ref cursor, false, badgrandchild.left, maxsnapid, generation);\r
-                                                       Node.update(ref child, true, badgrandchild.right, maxsnapid, generation);\r
-                                                       Node.CopyNode(ref badgrandchild, maxsnapid, generation);\r
-#else\r
-                                                       cursor.right = badgrandchild.left;\r
-                                                       child.left = badgrandchild.right;\r
-#endif\r
-                                                       badgrandchild.right = child;\r
-                                                       badgrandchild.left = cursor;\r
-                                                       cursor = badgrandchild;\r
-                                               }\r
-                                       }\r
-\r
-                                       cursor.red = false;\r
-\r
-#if MAINTAIN_SIZE\r
-                                       Node n;\r
-\r
-#if BAG\r
-                                       n = cursor.right;\r
-                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
-                                       n = cursor.left;\r
-                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
-                                       cursor.size += n.size + cursor.items;\r
-#else\r
-                                       n = cursor.right;\r
-                                       cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
-                                       n = cursor.left;\r
-                                       n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
-                                       cursor.size += n.size + 1;\r
-#endif\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor.right);\r
-                                       fixheight(cursor.left);\r
-                                       fixheight(cursor);\r
-#endif\r
-                                       if (level == 0)\r
-                                       {\r
-                                               root = cursor;\r
-                                               return true;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               child = cursor;\r
-                                               cursor = path[--level];\r
-                                               path[level] = null;\r
-#if NCP\r
-                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#else\r
-                                               if (dirs[level] > 0)\r
-                                                       cursor.left = child;\r
-                                               else\r
-                                                       cursor.right = child;\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                                               cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(cursor);\r
-#endif\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       }\r
-#if NCP\r
-                       bool stillmore = true;\r
-#endif\r
-                       while (level > 0)\r
-                       {\r
-                               Node child = cursor;\r
-\r
-                               cursor = path[--level];\r
-                               path[level] = null;\r
-#if NCP\r
-                               if (stillmore)\r
-                                       stillmore = Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                               cursor.size++;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               fixheight(cursor);\r
-#endif\r
-                       }\r
-\r
-                       root = cursor;\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add an item to this collection if possible. If this collection has set\r
-               /// semantics, the item will be added if not already in the collection. If\r
-               /// bag semantics, the item will always be added.\r
-               /// </summary>\r
-               /// <param name="item">The item to add.</param>\r
-               /// <returns>True if item was added.</returns>\r
-               [Tested]\r
-               public bool Add(T item)\r
-               {\r
-                       updatecheck();\r
-\r
-                       //Note: blackdepth of the tree is set inside addIterative\r
-                       T j = default(T);\r
-            bool tmp;\r
-\r
-            if (addIterative(item, ref j, false, out tmp))\r
-                       {\r
-                               size++;\r
-#if MAINTAIN_EXTREMA\r
-                               if (Compare(item, min) < 0)\r
-                                       min = item;\r
-                               else if (Compare(item, max) > 0)\r
-                                       max = item;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = root.height;\r
-#endif\r
-                               return true;\r
-                       }\r
-                       else\r
-                               return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Add the elements from another collection to this collection. If this\r
-               /// collection has set semantics, only items not already in the collection\r
-               /// will be added.\r
-               /// </summary>\r
-               /// <param name="items">The items to add.</param>\r
-               [Tested]\r
-               public void AddAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       int c = 0;\r
-                       T j = default(T);\r
-            bool tmp;\r
-\r
-            updatecheck();\r
-                       foreach (T i in items)\r
-                               if (addIterative(i, ref j, false, out tmp)) c++;\r
-\r
-                       size += c;\r
-               }\r
-\r
-        /// <summary>\r
-        /// Add the elements from another collection with a more specialized item type \r
-        /// to this collection. If this\r
-        /// collection has set semantics, only items not already in the collection\r
-        /// will be added.\r
-        /// </summary>\r
-        /// <typeparam name="U">The type of items to add</typeparam>\r
-        /// <param name="items">The items to add</param>\r
-        public void AddAll<U>(MSG.IEnumerable<U> items) where U : T\r
-        {\r
-            int c = 0;\r
-            T j = default(T);\r
-            bool tmp;\r
-\r
-            updatecheck();\r
-            foreach (T i in items)\r
-                if (addIterative(i, ref j, false, out tmp)) c++;\r
-\r
-            size += c;\r
-        }\r
-\r
-\r
-        /// <summary>\r
-               /// Add all the items from another collection with an enumeration order that \r
-               /// is increasing in the items. <para>The idea is that the implementation may use\r
-               /// a faster algorithm to merge the two collections.</para>\r
-               /// <exception cref="ArgumentException"/> if the enumerated items turns out\r
-               /// not to be in increasing order.\r
-               /// </summary>\r
-               /// <param name="items">The collection to add.</param>\r
-               [Tested]\r
-               public void AddSorted(MSG.IEnumerable<T> items)\r
-               {\r
-                       if (size > 0)\r
-                               AddAll(items);\r
-                       else\r
-                       {\r
-                               updatecheck();\r
-                               addSorted(items, true);\r
-                       }\r
-               }\r
-\r
-               #region add-sorted helpers\r
-               \r
-               //Create a RB tree from x+2^h-1  (x < 2^h, h>=1) nodes taken from a\r
-               //singly linked list of red nodes using only the right child refs.\r
-               //The x nodes at depth h+1 will be red, the rest black.\r
-               //(h is the blackdepth of the resulting tree)\r
-               static Node maketreer(ref Node rest, int blackheight, int maxred, int red)\r
-               {\r
-                       if (blackheight == 1)\r
-                       {\r
-                               Node top = rest;\r
-\r
-                               rest = rest.right;\r
-                               if (red > 0)\r
-                               {\r
-                                       top.right = null;\r
-                                       rest.left = top;\r
-                                       top = rest;\r
-#if BAG\r
-                                       top.size += top.left.size;\r
-#elif MAINTAIN_SIZE\r
-                                       top.size = 1 + red;\r
-#endif\r
-                                       rest = rest.right;\r
-                                       red--;\r
-                               }\r
-\r
-                               if (red > 0)\r
-                               {\r
-#if BAG\r
-                                       top.size += rest.size;\r
-#endif\r
-                                       top.right = rest;\r
-                                       rest = rest.right;\r
-                                       top.right.right = null;\r
-                               }\r
-                               else\r
-                                       top.right = null;\r
-\r
-                               top.red = false;\r
-                               return top;\r
-                       }\r
-                       else\r
-                       {\r
-                               maxred >>=1;\r
-\r
-                               int lred = red > maxred ? maxred : red;\r
-                               Node left = maketreer(ref rest, blackheight - 1, maxred, lred);\r
-                               Node top = rest;\r
-\r
-                               rest = rest.right;\r
-                               top.left = left;\r
-                               top.red = false;\r
-#if MAINTAIN_RANK\r
-                               top.rank = (short)blackheight;\r
-#endif\r
-                               top.right = maketreer(ref rest, blackheight - 1, maxred, red - lred);\r
-#if BAG\r
-                               top.size = top.items + top.left.size + top.right.size;\r
-#elif MAINTAIN_SIZE\r
-                               top.size = (maxred << 1) - 1 + red;\r
-#endif\r
-                               return top;\r
-                       }\r
-               }\r
-\r
-\r
-               void addSorted(MSG.IEnumerable<T> items, bool safe)\r
-               {\r
-                       MSG.IEnumerator<T> e = items.GetEnumerator();;\r
-                       if (size > 0)\r
-                               throw new ApplicationException("This can't happen");\r
-\r
-                       if (!e.MoveNext())\r
-                               return;\r
-\r
-                       //To count theCollect \r
-                       Node head = new Node(), tail = head;\r
-                       int z = 1;\r
-                       T lastitem = tail.item = e.Current;\r
-#if BAG\r
-                       int ec=0;\r
-#endif\r
-\r
-                       while (e.MoveNext())\r
-                       {\r
-#if BAG\r
-                               T thisitem = e.Current;\r
-                               int comp = comparer.Compare(lastitem, thisitem);\r
-                               if (comp>0)\r
-                                       throw new ArgumentException("Argument not sorted");\r
-                               if (comp == 0)\r
-                               {\r
-                                       tail.items++;\r
-                                       ec++;\r
-                               }\r
-                               else\r
-                               {\r
-                                       tail.size = tail.items;\r
-                                       z++;\r
-                                       tail.right = new Node();\r
-                                       tail = tail.right;\r
-                                       lastitem = tail.item = thisitem;\r
-#if NCP\r
-                                       tail.generation = generation;\r
-#endif\r
-                               }\r
-#else\r
-                               z++;\r
-                               tail.right = new Node();\r
-                               tail = tail.right;\r
-                               tail.item = e.Current;\r
-                               if (safe)\r
-                               {\r
-                                       if (comparer.Compare(lastitem, tail.item) >= 0)\r
-                                               throw new ArgumentException("Argument not sorted");\r
-\r
-                                       lastitem = tail.item;\r
-                               }\r
-#if NCP\r
-                               tail.generation = generation;\r
-#endif\r
-#endif\r
-                       }\r
-#if BAG\r
-                       tail.size = tail.items;\r
-#endif                         \r
-                       int blackheight = 0, red = z, maxred = 1;\r
-\r
-                       while (maxred <= red)\r
-                       {\r
-                               red -= maxred;\r
-                               maxred <<= 1;\r
-                               blackheight++;\r
-                       }\r
-\r
-                       root = TreeBag<T>.maketreer(ref head, blackheight, maxred, red);\r
-                       blackdepth = blackheight;\r
-                       size = z;\r
-#if BAG\r
-                       size += ec;\r
-#endif                         \r
-                       return;\r
-               }\r
-\r
-               #endregion\r
-\r
-#if BAG\r
-               /// <summary></summary>\r
-               /// <value>True since this collection has bag semantics.</value>\r
-               [Tested]\r
-               public bool AllowsDuplicates { [Tested]get { return true; } }\r
-#else\r
-               /// <summary></summary>\r
-               /// <value>False since this tree has set semantics.</value>\r
-               [Tested]\r
-               public bool AllowsDuplicates { [Tested]get { return false; } }\r
-#endif\r
-\r
-               #endregion\r
-\r
-               #region IEditableCollection<T> Members\r
-                       \r
-\r
-               /// <summary>\r
-               /// The value is symbolic indicating the type of asymptotic complexity\r
-               /// in terms of the size of this collection (worst-case or amortized as\r
-               /// relevant).\r
-               /// </summary>\r
-               /// <value>Speed.Log</value>\r
-               [Tested]\r
-               public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }\r
-\r
-\r
-               [Tested]\r
-               int ICollection<T>.GetHashCode() { return unsequencedhashcode(); }\r
-\r
-\r
-               [Tested]\r
-               bool ICollection<T>.Equals(ICollection<T> that)\r
-               { return unsequencedequals(that); }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains (an item equivalent to according to the\r
-               /// itemhasher) a particular value.\r
-               /// </summary>\r
-               /// <param name="item">The value to check for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public bool Contains(T item)\r
-               {\r
-                       Node next; int comp = 0;\r
-\r
-                       next = root;\r
-                       while (next != null)\r
-                       {\r
-                comp = comparer.Compare(next.item, item);\r
-                if (comp == 0)\r
-                                       return true;\r
-\r
-                               next = comp < 0 ? right(next) : left(next);\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               //Variant for dictionary use\r
-               //Will return the actual matching item in the ref argument.\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, return in the ref argument (a\r
-               /// binary copy of) the actual value found.\r
-               /// </summary>\r
-               /// <param name="item">The value to look for.</param>\r
-               /// <returns>True if the items is in this collection.</returns>\r
-               [Tested]\r
-               public bool Find(ref T item)\r
-               {\r
-                       Node next; int comp = 0;\r
-\r
-                       next = root;\r
-                       while (next != null)\r
-                       {\r
-                comp = comparer.Compare(next.item, item);\r
-                if (comp == 0)\r
-                               {\r
-                                       item = next.item;\r
-                                       return true;\r
-                               }\r
-\r
-                               next = comp < 0 ? right(next) : left(next);\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find or add the item to the tree. If the tree does not contain\r
-               /// an item equivalent to this item add it, else return the exisiting\r
-               /// one in the ref argument. \r
-               ///\r
-               /// </summary>\r
-               /// <param name="item"></param>\r
-               /// <returns>True if item was found</returns>\r
-               [Tested]\r
-               public bool FindOrAdd(ref T item)\r
-               {\r
-                       updatecheck();\r
-            bool wasfound;\r
-\r
-            //Note: blackdepth of the tree is set inside addIterative\r
-                       if (addIterative(item, ref item, false, out wasfound))\r
-                       {\r
-                               size++;\r
-#if MAINTAIN_EXTREMA\r
-                               if (Compare(item, min) < 0)\r
-                                       min = item;\r
-                               else if (Compare(item, max) > 0)\r
-                                       max = item;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = root.height;\r
-#endif\r
-                               return wasfound;\r
-                       }\r
-                       else\r
-                               return true;\r
-\r
-               }\r
-\r
-\r
-               //For dictionary use. \r
-               //If found, the matching entry will be updated with the new item.\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value. If the collection has bag semantics,\r
-               /// this updates all equivalent copies in\r
-               /// the collection.\r
-               /// </summary>\r
-               /// <param name="item">Value to update.</param>\r
-               /// <returns>True if the item was found and hence updated.</returns>\r
-               [Tested]\r
-               public bool Update(T item)\r
-               {\r
-                       updatecheck();\r
-#if NCP\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-#endif\r
-                       Node cursor = root;\r
-                       int comp = 0;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                comp = comparer.Compare(cursor.item, item);\r
-                if (comp == 0)\r
-                               {\r
-#if NCP\r
-                                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                                       cursor.item = item;\r
-#if NCP\r
-                                       while (level > 0)\r
-                                       {\r
-                                               Node child = cursor;\r
-\r
-                                               cursor = path[--level];\r
-                                               path[level] = null;\r
-#if NCP\r
-                                               Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#else\r
-                                               if (Node.CopyNode(maxsnapid, ref cursor, generation))\r
-                                               {\r
-                                                       if (dirs[level] > 0)\r
-                                                               cursor.left = child;\r
-                                                       else\r
-                                                               cursor.right = child;\r
-                                               }\r
-#endif\r
-                                       }\r
-\r
-                                       root = cursor;\r
-#endif\r
-                                       return true;\r
-                               }\r
-#if NCP\r
-                               dirs[level] = comp;\r
-                               path[level++] = cursor;\r
-#endif\r
-                               cursor = comp < 0 ? cursor.right : cursor.left;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains an item equivalent according to the\r
-               /// itemhasher to a particular value. If so, update the item in the collection \r
-               /// to with a binary copy of the supplied value; else add the value to the collection. \r
-               ///\r
-               /// <p>NOTE: the bag implementation is currently wrong!</p>\r
-               /// </summary>\r
-               /// <param name="item">Value to add or update.</param>\r
-               /// <returns>True if the item was found and updated (hence not added).</returns>\r
-               [Tested]\r
-               public bool UpdateOrAdd(T item)\r
-               {\r
-                       updatecheck();\r
-            bool wasfound;\r
-\r
-            //Note: blackdepth of the tree is set inside addIterative\r
-                       if (addIterative(item, ref item, true, out wasfound))\r
-                       {\r
-                               size++;\r
-#if MAINTAIN_EXTREMA\r
-                               if (Compare(item, min) < 0)\r
-                                       min = item;\r
-                               else if (Compare(item, max) > 0)\r
-                                       max = item;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               depth = root.height;\r
-#endif\r
-                               return wasfound;\r
-                       }\r
-                       else\r
-                               return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection. If the collection has bag\r
-               /// semantics only one copy equivalent to the supplied item is removed. \r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public bool Remove(T item)\r
-               {\r
-                       updatecheck();\r
-                       if (root == null)\r
-                               return false;\r
-\r
-                       return removeIterative(ref item, false);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Remove a particular item from this collection if found. If the collection\r
-               /// has bag semantics only one copy equivalent to the supplied item is removed,\r
-               /// which one is implementation dependent. \r
-               /// If an item was removed, report a binary copy of the actual item removed in \r
-               /// the argument.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove on input.</param>\r
-               /// <returns>True if the item was found (and removed).</returns>\r
-               [Tested]\r
-               public bool RemoveWithReturn(ref T item)\r
-               {\r
-                       updatecheck();\r
-                       if (root == null)\r
-                               return false;\r
-\r
-                       return removeIterative(ref item, false);\r
-               }\r
-\r
-\r
-               private bool removeIterative(ref T item, bool all)\r
-               {\r
-                       //Stage 1: find item\r
-                       stackcheck();\r
-\r
-                       int level = 0, comp;\r
-                       Node cursor = root;\r
-\r
-                       while (true)\r
-                       {\r
-                comp = comparer.Compare(cursor.item, item);\r
-                if (comp == 0)\r
-                               {\r
-                                       item = cursor.item;\r
-#if BAG\r
-                                       if (!all && cursor.items > 1)\r
-                                       {\r
-#if NCP\r
-                                               Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                                               cursor.items--;\r
-                                               cursor.size--;\r
-                                               while (level-- > 0)\r
-                                               {\r
-                                                       Node kid = cursor;\r
-\r
-                                                       cursor = path[level];\r
-#if NCP\r
-                                                       Node.update(ref cursor, dirs[level] > 0,  kid,maxsnapid,generation);\r
-#endif\r
-                                                       cursor.size--;\r
-                                                       path[level] = null;\r
-                                               }\r
-                                               size--;\r
-                                               return true;\r
-                                       }\r
-#endif\r
-                                       break;\r
-                               }\r
-\r
-                               Node child = comp > 0 ? cursor.left : cursor.right;\r
-\r
-                               if (child == null)\r
-                                       return false;\r
-\r
-                               dirs[level] = comp;\r
-                               path[level++] = cursor;\r
-                               cursor = child;\r
-                       }\r
-\r
-                       return removeIterativePhase2(cursor, level);\r
-               }\r
-\r
-\r
-               private bool removeIterativePhase2(Node cursor, int level)\r
-               {\r
-                       if (size == 1)\r
-                       {\r
-                               clear();\r
-                               return true;\r
-                       }\r
-\r
-#if MAINTAIN_EXTREMA\r
-                       if (Compare(cursor.item, min) == 0)\r
-                               min = cursor.right != null ? cursor.right.item : path[level - 1].item;\r
-                       else if (Compare(cursor.item, max) == 0)\r
-                               max = cursor.left != null ? cursor.left.item : path[level - 1].item;\r
-#endif\r
-#if BAG\r
-                       int removedcount = cursor.items;\r
-                       size -= removedcount;\r
-#else\r
-                       //We are certain to remove one node:\r
-                       size--;\r
-#endif\r
-                       //Stage 2: if item's node has no null child, find predecessor\r
-                       int level_of_item = level;\r
-\r
-                       if (cursor.left != null && cursor.right != null)\r
-                       {\r
-                               dirs[level] = 1;\r
-                               path[level++] = cursor;\r
-                               cursor = cursor.left;\r
-                               while (cursor.right != null)\r
-                               {\r
-                                       dirs[level] = -1;\r
-                                       path[level++] = cursor;\r
-                                       cursor = cursor.right;\r
-                               }\r
-#if NCP\r
-                               Node.CopyNode(ref path[level_of_item], maxsnapid, generation);\r
-#endif\r
-                               path[level_of_item].item = cursor.item;\r
-#if BAG\r
-                               path[level_of_item].items = cursor.items;\r
-#endif\r
-                       }\r
-\r
-                       //Stage 3: splice out node to be removed\r
-                       Node newchild = cursor.right == null ? cursor.left : cursor.right;\r
-                       bool demote_or_rotate = newchild == null && !cursor.red;\r
-\r
-                       //assert newchild.red \r
-                       if (newchild != null)\r
-                       {\r
-                               newchild.red = false;\r
-                       }\r
-\r
-                       if (level == 0)\r
-                       {\r
-                               root = newchild;\r
-#if MAINTAIN_HEIGHT\r
-                               depth = 0;\r
-#endif\r
-                               return true;\r
-                       }\r
-\r
-                       level--;\r
-                       cursor = path[level];\r
-                       path[level] = null;\r
-\r
-                       int comp = dirs[level];\r
-                       Node childsibling;\r
-#if NCP\r
-                       Node.update(ref cursor, comp > 0, newchild, maxsnapid, generation);\r
-#else\r
-                       if (comp > 0)\r
-                               cursor.left = newchild;\r
-                       else\r
-                               cursor.right = newchild;\r
-#endif\r
-                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
-#if BAG\r
-                       cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                       cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                       fixheight(cursor);\r
-#endif\r
-\r
-                       //Stage 4: demote till we must rotate\r
-                       Node farnephew = null, nearnephew = null;\r
-\r
-                       while (demote_or_rotate)\r
-                       {\r
-                               if (childsibling.red)\r
-                                       break; //rotate 2+?\r
-\r
-                               farnephew = comp > 0 ? childsibling.right : childsibling.left;\r
-                               if (farnephew != null && farnephew.red)\r
-                                       break; //rotate 1b\r
-\r
-                               nearnephew = comp > 0 ? childsibling.left : childsibling.right;\r
-                               if (nearnephew != null && nearnephew.red)\r
-                                       break; //rotate 1c\r
-\r
-                               //demote cursor\r
-                               childsibling.red = true;\r
-#if MAINTAIN_RANK\r
-                               cursor.rank--;\r
-#endif\r
-                               if (level == 0)\r
-                               {\r
-                                       cursor.red = false;\r
-                                       blackdepth--;\r
-#if MAINTAIN_HEIGHT\r
-                                       depth = root.height;\r
-#endif\r
-#if NCP\r
-                                       root = cursor;\r
-#endif\r
-                                       return true;\r
-                               }\r
-                               else if (cursor.red)\r
-                               {\r
-                                       cursor.red = false;\r
-                                       demote_or_rotate = false;\r
-                                       break; //No rotation\r
-                               }\r
-                               else\r
-                               {\r
-                                       Node child = cursor;\r
-\r
-                                       cursor = path[--level];\r
-                                       path[level] = null;\r
-                                       comp = dirs[level];\r
-                                       childsibling = comp > 0 ? cursor.right : cursor.left;\r
-#if NCP\r
-                                       Node.update(ref cursor, comp > 0, child, maxsnapid, generation);\r
-#endif\r
-#if BAG\r
-                                       cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                       }\r
-\r
-                       //Stage 5: rotate \r
-                       if (demote_or_rotate)\r
-                       {\r
-                               //At start:\r
-                               //parent = cursor (temporary for swapping nodes)\r
-                               //childsibling is the sibling of the updated child (x)\r
-                               //cursor is always the top of the subtree\r
-                               Node parent = cursor;\r
-\r
-                               if (childsibling.red)\r
-                               {//Case 2 and perhaps more. \r
-                                       //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null \r
-                                       //(and black). The grandnephews are children of nearnephew\r
-                                       Node neargrandnephew, fargrandnephew;\r
-\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               nearnephew = childsibling.left;\r
-                                               farnephew = childsibling.right;\r
-                                               neargrandnephew = nearnephew.left;\r
-                                               fargrandnephew = nearnephew.right;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               nearnephew = childsibling.right;\r
-                                               farnephew = childsibling.left;\r
-                                               neargrandnephew = nearnephew.right;\r
-                                               fargrandnephew = nearnephew.left;\r
-                                       }\r
-\r
-                                       if (fargrandnephew != null && fargrandnephew.red)\r
-                                       {//Case 2+1b\r
-#if NCP\r
-                                               Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
-\r
-                                               //The end result of this will always be e copy of parent\r
-                                               Node.update(ref parent, comp < 0, neargrandnephew, maxsnapid, generation);\r
-                                               Node.update(ref childsibling, comp > 0, nearnephew, maxsnapid, generation);\r
-#endif\r
-                                               if (comp > 0)\r
-                                               {\r
-                                                       nearnephew.left = parent;\r
-                                                       parent.right = neargrandnephew;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       nearnephew.right = parent;\r
-                                                       parent.left = neargrandnephew;\r
-                                               }\r
-\r
-                                               cursor = childsibling;\r
-                                               childsibling.red = false;\r
-                                               nearnephew.red = true;\r
-                                               fargrandnephew.red = false;\r
-#if MAINTAIN_RANK\r
-                                               nearnephew.rank++;\r
-                                               parent.rank--;\r
-#endif\r
-#if BAG\r
-                                               cursor.size = parent.size;\r
-                                               nearnephew.size = cursor.size - cursor.items - farnephew.size;\r
-                                               parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size;\r
-#elif MAINTAIN_SIZE\r
-                                               cursor.size = parent.size;\r
-                                               nearnephew.size = cursor.size - 1 - farnephew.size;\r
-                                               parent.size = nearnephew.size - 1 - fargrandnephew.size;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(parent);\r
-                                               fixheight(nearnephew);\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                                       else if (neargrandnephew != null && neargrandnephew.red)\r
-                                       {//Case 2+1c\r
-#if NCP\r
-                                               Node.CopyNode(ref neargrandnephew, maxsnapid, generation);\r
-#endif\r
-                                               if (comp > 0)\r
-                                               {\r
-#if NCP\r
-                                                       Node.update(ref childsibling, true, neargrandnephew, maxsnapid, generation);\r
-                                                       Node.update(ref nearnephew, true, neargrandnephew.right, maxsnapid, generation);\r
-                                                       Node.update(ref parent, false, neargrandnephew.left, maxsnapid, generation);\r
-#else\r
-                                                       childsibling.left = neargrandnephew;\r
-                                                       nearnephew.left = neargrandnephew.right;\r
-                                                       parent.right = neargrandnephew.left;\r
-#endif\r
-                                                       neargrandnephew.left = parent;\r
-                                                       neargrandnephew.right = nearnephew;\r
-                                               }\r
-                                               else\r
-                                               {\r
-#if NCP\r
-                                                       Node.update(ref childsibling, false, neargrandnephew, maxsnapid, generation);\r
-                                                       Node.update(ref nearnephew, false, neargrandnephew.left, maxsnapid, generation);\r
-                                                       Node.update(ref parent, true, neargrandnephew.right, maxsnapid, generation);\r
-#else\r
-                                                       childsibling.right = neargrandnephew;\r
-                                                       nearnephew.right = neargrandnephew.left;\r
-                                                       parent.left = neargrandnephew.right;\r
-#endif\r
-                                                       neargrandnephew.right = parent;\r
-                                                       neargrandnephew.left = nearnephew;\r
-                                               }\r
-\r
-                                               cursor = childsibling;\r
-                                               childsibling.red = false;\r
-#if MAINTAIN_RANK\r
-                                               neargrandnephew.rank++;\r
-                                               parent.rank--;\r
-#endif\r
-#if BAG\r
-                                               cursor.size = parent.size;\r
-                                               parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                               nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
-                                               neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size;\r
-#elif MAINTAIN_SIZE\r
-                                               cursor.size = parent.size;\r
-                                               parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                               nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);\r
-                                               neargrandnephew.size = 1 + parent.size + nearnephew.size;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(parent);\r
-                                               fixheight(nearnephew);\r
-                                               fixheight(neargrandnephew);\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                                       else\r
-                                       {//Case 2 only\r
-#if NCP\r
-                                               Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
-                                               Node.update(ref childsibling, comp > 0, parent, maxsnapid, generation);\r
-#else\r
-                                               if (comp > 0)\r
-                                               {\r
-                                                       childsibling.left = parent;\r
-                                                       parent.right = nearnephew;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       childsibling.right = parent;\r
-                                                       parent.left = nearnephew;\r
-                                               }\r
-#endif\r
-                                               cursor = childsibling;\r
-                                               childsibling.red = false;\r
-                                               nearnephew.red = true;\r
-#if MAINTAIN_RANK\r
-                                               parent.rank--;\r
-#endif\r
-#if BAG\r
-                                               cursor.size = parent.size;\r
-                                               parent.size -= farnephew.size + cursor.items;\r
-#elif MAINTAIN_SIZE\r
-                                               cursor.size = parent.size;\r
-                                               parent.size -= farnephew.size + 1;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                               fixheight(parent);\r
-                                               fixheight(cursor);\r
-#endif\r
-                                       }\r
-                               }\r
-                               else if (farnephew != null && farnephew.red)\r
-                               {//Case 1b\r
-                                       nearnephew = comp > 0 ? childsibling.left : childsibling.right;         \r
-#if NCP\r
-                                       Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);\r
-                                       Node.CopyNode(ref childsibling, maxsnapid, generation);\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               childsibling.left = parent;\r
-                                               childsibling.right = farnephew;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               childsibling.right = parent;\r
-                                               childsibling.left = farnephew;\r
-                                       }\r
-#else\r
-                                       if (comp > 0)\r
-                                       {\r
-                                               childsibling.left = parent;\r
-                                               parent.right = nearnephew;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               childsibling.right = parent;\r
-                                               parent.left = nearnephew;\r
-                                       }\r
-#endif\r
-                                       cursor = childsibling;\r
-                                       cursor.red = parent.red;\r
-                                       parent.red = false;\r
-                                       farnephew.red = false;\r
-\r
-#if MAINTAIN_RANK\r
-                                       childsibling.rank++;\r
-                                       parent.rank--;\r
-#endif\r
-#if BAG\r
-                                       cursor.size = parent.size;\r
-                                       parent.size -= farnephew.size + cursor.items;\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size = parent.size;\r
-                                       parent.size -= farnephew.size + 1;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(parent);\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                               else if (nearnephew != null && nearnephew.red)\r
-                               {//Case 1c\r
-#if NCP\r
-                                       Node.CopyNode(ref nearnephew, maxsnapid, generation);\r
-#endif\r
-                                       if (comp > 0)\r
-                                       {\r
-#if NCP\r
-                                               Node.update(ref childsibling, true, nearnephew.right, maxsnapid, generation);\r
-                                               Node.update(ref parent, false, nearnephew.left, maxsnapid, generation);\r
-#else\r
-                                               childsibling.left = nearnephew.right;\r
-                                               parent.right = nearnephew.left;\r
-#endif\r
-                                               nearnephew.left = parent;\r
-                                               nearnephew.right = childsibling;\r
-                                       }\r
-                                       else\r
-                                       {\r
-#if NCP\r
-                                               Node.update(ref childsibling, false, nearnephew.left, maxsnapid, generation);\r
-                                               Node.update(ref parent, true, nearnephew.right, maxsnapid, generation);\r
-#else\r
-                                               childsibling.right = nearnephew.left;\r
-                                               parent.left = nearnephew.right;\r
-#endif\r
-                                               nearnephew.right = parent;\r
-                                               nearnephew.left = childsibling;\r
-                                       }\r
-\r
-                                       cursor = nearnephew;\r
-                                       cursor.red = parent.red;\r
-                                       parent.red = false;\r
-#if MAINTAIN_RANK\r
-                                       nearnephew.rank++;\r
-                                       parent.rank--;\r
-#endif\r
-#if BAG\r
-                                       cursor.size = parent.size;\r
-                                       parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                       childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size = parent.size;\r
-                                       parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);\r
-                                       childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(parent);\r
-                                       fixheight(childsibling);\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                               else\r
-                               {//Case 1a can't happen\r
-                                       throw new Exception("Case 1a can't happen here");\r
-                               }\r
-\r
-                               //Resplice cursor:\r
-                               if (level == 0)\r
-                               {\r
-                                       root = cursor;\r
-                               }\r
-                               else\r
-                               {\r
-                                       Node swap = cursor;\r
-\r
-                                       cursor = path[--level];\r
-                                       path[level] = null;\r
-#if NCP\r
-                                       Node.update(ref cursor, dirs[level] > 0, swap, maxsnapid, generation);\r
-#else\r
-                               \r
-                                       if (dirs[level] > 0)\r
-                                               cursor.left = swap;\r
-                                       else\r
-                                               cursor.right = swap;\r
-#endif\r
-#if BAG\r
-                                       cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                                       cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                                       fixheight(cursor);\r
-#endif\r
-                               }\r
-                       }\r
-\r
-                       //Stage 6: fixup to the root\r
-                       while (level > 0)\r
-                       {\r
-                               Node child = cursor;\r
-\r
-                               cursor = path[--level];\r
-                               path[level] = null;\r
-#if NCP\r
-                               if (child != (dirs[level] > 0 ? cursor.left : cursor.right))\r
-                                       Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);\r
-#endif\r
-#if BAG\r
-                               cursor.size -= removedcount;\r
-#elif MAINTAIN_SIZE\r
-                               cursor.size--;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               fixheight(cursor);\r
-#endif\r
-                       }\r
-\r
-#if MAINTAIN_HEIGHT\r
-                       depth = root.height;\r
-#endif\r
-#if NCP\r
-                       root = cursor;\r
-#endif\r
-                       return true;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items from this collection.\r
-               /// </summary>\r
-               [Tested]\r
-               public void Clear()\r
-               {\r
-                       updatecheck();\r
-                       clear();\r
-               }\r
-\r
-\r
-               private void clear()\r
-               {\r
-                       size = 0;\r
-                       root = null;\r
-                       blackdepth = 0;\r
-#if MAINTAIN_HEIGHT\r
-                       depth = 0;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items in another collection from this one. If this collection\r
-               /// has bag semantics, take multiplicities into account.\r
-               /// </summary>\r
-               /// <param name="items">The items to remove.</param>\r
-               [Tested]\r
-               public void RemoveAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       T jtem;\r
-\r
-                       foreach (T item in items)\r
-                       {\r
-                               if (root == null)\r
-                                       break;\r
-\r
-                               jtem = item;\r
-                               removeIterative(ref jtem, false);\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items not in some other collection from this one. If this collection\r
-               /// has bag semantics, take multiplicities into account.\r
-               /// </summary>\r
-               /// <param name="items">The items to retain.</param>\r
-               [Tested]\r
-               public void RetainAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       updatecheck();\r
-\r
-                       //A much more efficient version is possible if items is sorted like this.\r
-                       //Well, it is unclear how efficient it would be.\r
-                       //We could use a marking method!?\r
-                       TreeBag<T> t = (TreeBag<T>)MemberwiseClone();\r
-\r
-                       t.Clear();\r
-                       foreach (T item in items)\r
-                               if (ContainsCount(item) > t.ContainsCount(item))\r
-                                       t.Add(item);\r
-\r
-                       root = t.root;\r
-                       size = t.size;\r
-                       blackdepth = t.blackdepth;\r
-#if MAINTAIN_HEIGHT\r
-                       depth = t.depth;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Check if this collection contains all the values in another collection.\r
-               /// If this collection has bag semantics (<code>NoDuplicates==false</code>)\r
-               /// the check is made with respect to multiplicities, else multiplicities\r
-               /// are not taken into account.\r
-               /// </summary>\r
-               /// <param name="items">The </param>\r
-               /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
-               [Tested]\r
-               public bool ContainsAll(MSG.IEnumerable<T> items)\r
-               {\r
-                       //This is worst-case O(m*logn)\r
-                       foreach (T item in items)\r
-                               if (!Contains(item)) return false;\r
-\r
-                       return true;\r
-               }\r
-\r
-\r
-               //Higher order:\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the items of this\r
-               /// indexed sorted collection satisfying a certain predicate.\r
-               /// </summary>\r
-               /// <param name="filter">The filter delegate defining the predicate.</param>\r
-               /// <returns>The new indexed sorted collection.</returns>\r
-               [Tested]\r
-               public IIndexedSorted<T> FindAll(Filter<T> filter)\r
-               {\r
-                       TreeBag<T> res = new TreeBag<T>(comparer);\r
-                       MSG.IEnumerator<T> e = GetEnumerator();\r
-                       Node head = null, tail = null;\r
-                       int z = 0;\r
-#if BAG\r
-                       int ec = 0;\r
-#endif\r
-                       while (e.MoveNext())\r
-                       {\r
-                               T thisitem = e.Current;\r
-#if BAG\r
-                               //We could document that filter will only be called \r
-                               //once on each unique item. That might even be good for the user!\r
-                               if (tail!=null && comparer.Compare(thisitem, tail.item) == 0)\r
-                               {\r
-                                       tail.items++;\r
-                                       ec++;\r
-                                       continue;\r
-                               }\r
-#endif\r
-                               if (filter(thisitem))\r
-                               {\r
-                                       if (head == null)\r
-                                       {\r
-                                               head = tail = new Node();\r
-                                       }\r
-                                       else\r
-                                       {\r
-#if BAG\r
-                                               tail.size = tail.items;\r
-#endif\r
-                                               tail.right = new Node();\r
-                                               tail = tail.right;\r
-                                       }\r
-\r
-                                       tail.item = thisitem;\r
-                                       z++;\r
-                               }\r
-                       }\r
-#if BAG\r
-                       if (tail!=null)\r
-                               tail.size = tail.items;\r
-#endif\r
-\r
-                       if (z == 0)\r
-                               return res;\r
-\r
-                       int blackheight = 0, red = z, maxred = 1;\r
-\r
-                       while (maxred <= red)\r
-                       {\r
-                               red -= maxred;\r
-                               maxred <<= 1;\r
-                               blackheight++;\r
-                       }\r
-\r
-                       res.root = TreeBag<T>.maketreer(ref head, blackheight, maxred, red);\r
-                       res.blackdepth = blackheight;\r
-                       res.size = z;\r
-#if BAG\r
-                       res.size += ec;\r
-#endif\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a new indexed sorted collection consisting of the results of\r
-               /// mapping all items of this list.\r
-               /// <exception cref="ArgumentException"/> if the map is not increasing over \r
-               /// the items of this collection (with respect to the two given comparison \r
-               /// relations).\r
-               /// </summary>\r
-               /// <param name="mapper">The delegate definging the map.</param>\r
-               /// <param name="c">The comparion relation to use for the result.</param>\r
-               /// <returns>The new sorted collection.</returns>\r
-               [Tested]\r
-               public IIndexedSorted<V> Map<V>(Mapper<T,V> mapper, IComparer<V> c)\r
-               {\r
-                       TreeBag<V> res = new TreeBag<V>(c);\r
-\r
-                       if (size == 0)\r
-                               return res;\r
-\r
-                       MSG.IEnumerator<T> e = GetEnumerator();\r
-                       TreeBag<V>.Node head = null, tail = null;\r
-                       V oldv = default(V);\r
-                       int z = 0;\r
-#if BAG\r
-                       T lastitem = default(T);\r
-#endif\r
-                       while (e.MoveNext())\r
-                       {\r
-                               T thisitem = e.Current;\r
-#if BAG\r
-                               //We could document that mapper will only be called \r
-                               //once on each unique item. That might even be good for the user!\r
-                               if (tail != null && comparer.Compare(thisitem, lastitem) == 0)\r
-                               {\r
-                                       tail.items++;\r
-                                       continue;\r
-                               }\r
-#endif\r
-                               V newv = mapper(thisitem);\r
-\r
-                               if (head == null)\r
-                               {\r
-                                       head = tail = new TreeBag<V>.Node();\r
-                                       z++;\r
-                               }\r
-                               else\r
-                               {\r
-                                       int comp = c.Compare(oldv, newv);\r
-#if BAG\r
-                                       if (comp == 0)\r
-                                       {\r
-                                               tail.items++;\r
-                                               continue;\r
-                                       }\r
-                                       if (comp > 0)\r
-#else\r
-                                       if (comp >= 0)\r
-#endif\r
-                                               throw new ArgumentException("mapper not monotonic");\r
-#if BAG\r
-                                       tail.size = tail.items;\r
-#endif\r
-                                       tail.right = new TreeBag<V>.Node();\r
-                                       tail = tail.right;\r
-                                       z++;\r
-                               }\r
-#if BAG\r
-                               lastitem = thisitem;\r
-#endif\r
-                               tail.item = oldv = newv;\r
-                       }\r
-\r
-#if BAG\r
-                       tail.size = tail.items;\r
-#endif\r
-\r
-                       int blackheight = 0, red = z, maxred = 1;\r
-\r
-                       while (maxred <= red)\r
-                       {\r
-                               red -= maxred;\r
-                               maxred <<= 1;\r
-                               blackheight++;\r
-                       }\r
-\r
-                       res.root = TreeBag<V>.maketreer(ref head, blackheight, maxred, red);\r
-                       res.blackdepth = blackheight;\r
-                       res.size = size;\r
-                       return res;\r
-               }\r
-\r
-\r
-               //below is the bag utility stuff\r
-               /// <summary>\r
-               /// Count the number of items of the collection equal to a particular value.\r
-               /// Returns 0 if and only if the value is not in the collection.\r
-               /// </summary>\r
-               /// <param name="item">The value to count.</param>\r
-               /// <returns>The number of copies found.</returns>\r
-               [Tested]\r
-               public int ContainsCount(T item)\r
-               {\r
-#if BAG\r
-                       Node next; int comp = 0;\r
-\r
-                       next = root;\r
-                       while (next != null)\r
-                       {\r
-                               comp = comparer.Compare(next.item, item);\r
-                               if (comp == 0)\r
-                                       return next.items;\r
-\r
-                               next = comp < 0 ? right(next) : left(next);\r
-                       }\r
-\r
-                       return 0;\r
-#else\r
-                       //Since we are strictly NoDuplicates we just do\r
-                       return Contains(item) ? 1 : 0;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items equivalent to a given value.\r
-               /// </summary>\r
-               /// <param name="item">The value to remove.</param>\r
-               [Tested]\r
-               public void RemoveAllCopies(T item)\r
-               {\r
-#if BAG\r
-                       updatecheck();\r
-                       removeIterative(ref item, true);\r
-#else\r
-                       \r
-                       Remove(item);\r
-#endif\r
-               }\r
-\r
-\r
-               #endregion\r
-\r
-               #region IIndexed<T> Members\r
-                       \r
-               private Node findNode(int i)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                       Node next = root;\r
-\r
-                       if (i >= 0 && i < size)\r
-                               while (true)\r
-                               {\r
-                                       int j = next.left == null ? 0 : next.left.size;\r
-\r
-                                       if (i > j)\r
-                                       {\r
-#if BAG\r
-                                               i -= j + next.items;                                    \r
-                                               if (i<0)\r
-                                                       return next;\r
-#else\r
-                                               i -= j + 1;\r
-#endif\r
-                                               next = next.right;\r
-                                       }\r
-                                       else if (i == j)\r
-                                               return next;\r
-                                       else\r
-                                               next = next.left;\r
-                               }\r
-\r
-                       throw new IndexOutOfRangeException();\r
-#else\r
-                       throw new NotSupportedException();\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <value>The i'th item of this list.</value>\r
-               /// <param name="i">the index to lookup</param>\r
-               [Tested]\r
-               public T this[int i] { [Tested] get { return findNode(i).item; } }\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going forwrds from the start.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of item from start.</returns>\r
-               [Tested]\r
-               public int IndexOf(T item)\r
-               {\r
-                       int upper;\r
-\r
-                       return indexOf(item, out upper);\r
-               }\r
-\r
-\r
-               private int indexOf(T item, out int upper)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                       int ind = 0; Node next = root;\r
-\r
-                       while (next != null)\r
-                       {\r
-                int comp = comparer.Compare(item, next.item);\r
-\r
-                if (comp < 0)\r
-                                       next = next.left;\r
-                               else\r
-                               {\r
-                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
-\r
-                                       if (comp == 0)\r
-                                       {\r
-#if BAG\r
-                                               upper = ind + leftcnt + next.items - 1;\r
-                                               return ind + leftcnt;\r
-#else\r
-                                               return upper = ind + leftcnt;\r
-#endif\r
-                                       }\r
-                                       else\r
-                                       {\r
-#if BAG\r
-                                               ind = ind + next.items + leftcnt;\r
-#else\r
-                                               ind = ind + 1 + leftcnt;\r
-#endif\r
-                                               next = next.right;\r
-                                       }\r
-                               }\r
-                       }\r
-#endif\r
-                       upper = -1;\r
-                       return -1;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Searches for an item in the list going backwords from the end.\r
-               /// </summary>\r
-               /// <param name="item">Item to search for.</param>\r
-               /// <returns>Index of of item from the end.</returns>\r
-               [Tested]\r
-               public int LastIndexOf(T item)\r
-               {\r
-#if BAG\r
-                       int res;\r
-                       indexOf(item, out res);\r
-                       return res;\r
-#else\r
-                       //We have NoDuplicates==true for the set\r
-                       return IndexOf(item);\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the item at a specific position of the list.\r
-               /// <exception cref="IndexOutOfRangeException"/> if i is negative or\r
-               /// &gt;= the size of the collection.\r
-               /// </summary>\r
-               /// <param name="i">The index of the item to remove.</param>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T RemoveAt(int i)\r
-               {\r
-                       updatecheck();\r
-#if MAINTAIN_SIZE\r
-                       if (i < 0 || i >= size)\r
-                               throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
-\r
-                       //We must follow the pattern of removeIterative()\r
-                       while (dirs.Length < 2 * blackdepth)\r
-                       {\r
-                               dirs = new int[2 * dirs.Length];\r
-                               path = new Node[2 * dirs.Length];\r
-                       }\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (true)\r
-                       {\r
-                               int j = cursor.left == null ? 0 : cursor.left.size;\r
-\r
-                               if (i > j)\r
-                               {\r
-#if BAG\r
-                                       i -= j + cursor.items;\r
-                                       if (i<0)\r
-                                               break;\r
-#else\r
-                                       i -= j + 1;\r
-#endif\r
-                                       dirs[level] = -1;\r
-                                       path[level++] = cursor;\r
-                                       cursor = cursor.right;\r
-                               }\r
-                               else if (i == j)\r
-                                       break;\r
-                               else\r
-                               {\r
-                                       dirs[level] = 1;\r
-                                       path[level++] = cursor;\r
-                                       cursor = cursor.left;\r
-                               }\r
-                       }\r
-\r
-                       T retval = cursor.item;\r
-\r
-#if BAG\r
-                       if (cursor.items>1)\r
-                       {\r
-                               resplicebag(level, cursor);\r
-                               size--;\r
-                               return retval;\r
-                       }\r
-#endif\r
-                       removeIterativePhase2(cursor, level);\r
-                       return retval;\r
-#else\r
-                       throw new NotSupportedException();\r
-#endif\r
-               }\r
-\r
-#if BAG\r
-               private void resplicebag(int level, Node cursor)\r
-               {\r
-#if NCP\r
-                       Node.CopyNode(ref cursor, maxsnapid, generation);\r
-#endif\r
-                       cursor.items--;\r
-                       cursor.size--;\r
-                       while (level-- > 0)\r
-                       {\r
-                               Node kid = cursor;\r
-\r
-                               cursor = path[level];\r
-#if NCP\r
-                               Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);\r
-#endif\r
-                               cursor.size--;\r
-                               path[level] = null;\r
-                       }\r
-               }\r
-#endif\r
-               /// <summary>\r
-               /// Remove all items in an index interval.\r
-               /// <exception cref="IndexOutOfRangeException"/>???. \r
-               /// </summary>\r
-               /// <param name="start">The index of the first item to remove.</param>\r
-               /// <param name="count">The number of items to remove.</param>\r
-               [Tested]\r
-               public void RemoveInterval(int start, int count)\r
-               {\r
-                       if (start < 0 || count < 0)\r
-                               throw new ArgumentOutOfRangeException();\r
-\r
-                       if (start + count > this.size)\r
-                               throw new ArgumentException();\r
-\r
-                       updatecheck();\r
-\r
-                       //This is terrible for large count. We should split the tree at \r
-                       //the endpoints of the range and fuse the parts!\r
-                       //We really need good internal destructive split and catenate functions!\r
-                       for (int i = 0; i < count; i++)\r
-                               RemoveAt(start);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// <exception cref="IndexOutOfRangeException"/>.\r
-               /// </summary>\r
-               /// <value>The directed collection of items in a specific index interval.</value>\r
-               /// <param name="start">The low index of the interval (inclusive).</param>\r
-               /// <param name="end">The high index of the interval (exclusive).</param>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> this[int start, int end]\r
-               {\r
-                       [Tested]\r
-                       get\r
-                       {\r
-                               checkRange(start, end - start);\r
-                               return new Interval(this, start, end - start, true);\r
-                       }\r
-               }\r
-\r
-               #region Interval nested class\r
-               class Interval: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
-               {\r
-                       int start, length, stamp;\r
-\r
-                       bool forwards;\r
-\r
-                       TreeBag<T> tree;\r
-\r
-\r
-                       internal Interval(TreeBag<T> tree, int start, int count, bool forwards)\r
-                       {\r
-#if NCP\r
-                               if (tree.isSnapShot)\r
-                                       throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-                               this.start = start; this.length = count;this.forwards = forwards;\r
-                               this.tree = tree; this.stamp = tree.stamp;\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-            public override int Count { [Tested]get { return length; } }\r
-\r
-\r
-            public override Speed CountSpeed { get { return Speed.Constant; } }\r
-            \r
-            [Tested]\r
-            public override MSG.IEnumerator<T> GetEnumerator()\r
-                       {\r
-#if MAINTAIN_SIZE\r
-                               tree.modifycheck(stamp);\r
-#if BAG\r
-                               int togo;\r
-#endif\r
-                               Node cursor = tree.root;\r
-                               Node[] path = new Node[2 * tree.blackdepth];\r
-                               int level = 0, totaltogo = length;\r
-\r
-                               if (totaltogo == 0)\r
-                                       yield break;\r
-\r
-                               if (forwards)\r
-                               {\r
-                                       int i = start;\r
-\r
-                                       while (true)\r
-                                       {\r
-                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
-\r
-                                               if (i > j)\r
-                                               {\r
-#if BAG\r
-                                                       i -= j + cursor.items;\r
-                                                       if (i < 0)\r
-                                                       {\r
-                                                               togo = cursor.items + i;\r
-                                                               break;\r
-                                                       }\r
-#else\r
-                                                       i -= j + 1;\r
-#endif\r
-                                                       cursor = cursor.right;\r
-                                               }\r
-                                               else if (i == j)\r
-                                               {\r
-#if BAG\r
-                                                       togo = cursor.items;\r
-#endif\r
-                                                       break;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       path[level++] = cursor;\r
-                                                       cursor = cursor.left;\r
-                                               }\r
-                                       }\r
-\r
-                                       T current = cursor.item;\r
-\r
-                                       while (totaltogo-- > 0)\r
-                                       {\r
-                                               yield return current;\r
-                                               tree.modifycheck(stamp);\r
-#if BAG\r
-                                               if (--togo > 0)\r
-                                                       continue;\r
-#endif\r
-                                               if (cursor.right != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.right;\r
-                                                       while (cursor.left != null)\r
-                                                               path[++level] = cursor = cursor.left;\r
-                                               }\r
-                                               else if (level == 0)\r
-                                                       yield break;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       int i = start + length - 1;\r
-\r
-                                       while (true)\r
-                                       {\r
-                                               int j = cursor.left == null ? 0 : cursor.left.size;\r
-\r
-                                               if (i > j)\r
-                                               {\r
-#if BAG\r
-                                                       if (i - j < cursor.items)\r
-                                                       {\r
-                                                               togo = i - j + 1;\r
-                                                               break;\r
-                                                       }\r
-                                                       i -= j + cursor.items;\r
-#else\r
-                                                       i -= j + 1;\r
-#endif\r
-                                                       path[level++] = cursor;\r
-                                                       cursor = cursor.right;\r
-                                               }\r
-                                               else if (i == j)\r
-                                               {\r
-#if BAG\r
-                                                       togo = 1;\r
-#endif\r
-                                                       break;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       cursor = cursor.left;\r
-                                               }\r
-                                       }\r
-\r
-                                       T current = cursor.item;\r
-\r
-                                       while (totaltogo-- > 0)\r
-                                       {\r
-                                               yield return current;\r
-                                               tree.modifycheck(stamp);\r
-#if BAG\r
-                                               if (--togo > 0)\r
-                                                       continue;\r
-#endif\r
-                                               if (cursor.left != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.left;\r
-                                                       while (cursor.right != null)\r
-                                                               path[++level] = cursor = cursor.right;\r
-                                               }\r
-                                               else if (level == 0)\r
-                                                       yield break;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                       }\r
-                               }\r
-\r
-#else\r
-                       throw new NotSupportedException();\r
-#endif\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       public IDirectedCollectionValue<T> Backwards()\r
-                       { return new Interval(tree, start, length, !forwards); }\r
-\r
-\r
-                       [Tested]\r
-                       IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()\r
-                       { return Backwards(); }\r
-\r
-\r
-                       [Tested]\r
-                       public EnumerationDirection Direction\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;\r
-                               }\r
-                       }\r
-               }\r
-               #endregion\r
-\r
-               /// <summary>\r
-               /// Create a collection containing the same items as this collection, but\r
-               /// whose enumerator will enumerate the items backwards. The new collection\r
-               /// will become invalid if the original is modified. Method typicaly used as in\r
-               /// <code>foreach (T x in coll.Backwards()) {...}</code>\r
-               /// </summary>\r
-               /// <returns>The backwards collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
-\r
-               #endregion\r
-\r
-               #region ISequenced Members\r
-               [Tested]\r
-               int ISequenced<T>.GetHashCode() { return sequencedhashcode(); }\r
-\r
-\r
-               [Tested]\r
-               bool ISequenced<T>.Equals(ISequenced<T> that) { return sequencedequals(that); }\r
-               #endregion\r
-\r
-               #region PriorityQueue Members\r
-\r
-        /// <summary>\r
-        /// The comparer object supplied at creation time for this collection\r
-        /// </summary>\r
-        /// <value>The comparer</value>\r
-        public IComparer<T> Comparer { get { return comparer; } }\r
-\r
-\r
-        /// <summary>\r
-               /// Find the current least item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The least item.</returns>\r
-               [Tested]\r
-               public T FindMin()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-#if MAINTAIN_EXTREMA\r
-                       return min;\r
-#else\r
-                       Node cursor = root, next = left(cursor);\r
-\r
-                       while (next != null)\r
-                       {\r
-                               cursor = next;\r
-                               next = left(cursor);\r
-                       }\r
-\r
-                       return cursor.item;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the least item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMin()\r
-               {\r
-                       updatecheck();\r
-\r
-                       //persistence guard?\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       //We must follow the pattern of removeIterative()\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (cursor.left != null)\r
-                       {\r
-                               dirs[level] = 1;\r
-                               path[level++] = cursor;\r
-                               cursor = cursor.left;\r
-                       }\r
-\r
-                       T retval = cursor.item;\r
-\r
-#if BAG\r
-                       if (cursor.items > 1)\r
-                       {\r
-                               resplicebag(level, cursor);\r
-                               size--;\r
-                               return retval;\r
-                       }\r
-#endif\r
-                       removeIterativePhase2(cursor, level);\r
-                       return retval;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the current largest item of this priority queue.\r
-               /// </summary>\r
-               /// <returns>The largest item.</returns>\r
-               [Tested]\r
-               public T FindMax()\r
-               {\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-#if MAINTAIN_EXTREMA\r
-                       return max;\r
-#else\r
-                       Node cursor = root, next = right(cursor);\r
-\r
-                       while (next != null)\r
-                       {\r
-                               cursor = next;\r
-                               next = right(cursor);\r
-                       }\r
-\r
-                       return cursor.item;\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove the largest item from this  priority queue.\r
-               /// </summary>\r
-               /// <returns>The removed item.</returns>\r
-               [Tested]\r
-               public T DeleteMax()\r
-               {\r
-                       //persistence guard?\r
-                       updatecheck();\r
-                       if (size == 0)\r
-                               throw new InvalidOperationException("Priority queue is empty");\r
-\r
-                       //We must follow the pattern of removeIterative()\r
-                       stackcheck();\r
-\r
-                       int level = 0;\r
-                       Node cursor = root;\r
-\r
-                       while (cursor.right != null)\r
-                       {\r
-                               dirs[level] = -1;\r
-                               path[level++] = cursor;\r
-                               cursor = cursor.right;\r
-                       }\r
-\r
-                       T retval = cursor.item;\r
-\r
-#if BAG\r
-                       if (cursor.items > 1)\r
-                       {\r
-                               resplicebag(level, cursor);\r
-                               size--;\r
-                               return retval;\r
-                       }\r
-#endif\r
-                       removeIterativePhase2(cursor, level);\r
-                       return retval;\r
-               }\r
-               #endregion\r
-\r
-               #region IPredecesorStructure<T> Members\r
-\r
-               /// <summary>\r
-               /// Find the strict predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than or equal to the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the predecessor for.</param>\r
-               /// <returns>The predecessor.</returns>\r
-               [Tested]\r
-               public T Predecessor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp < 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = right(cursor);\r
-                               }\r
-                               else if (comp == 0)\r
-                               {\r
-                                       cursor = left(cursor);\r
-                                       while (cursor != null)\r
-                                       {\r
-                                               bestsofar = cursor;\r
-                                               cursor = right(cursor);\r
-                                       }\r
-                               }\r
-                               else\r
-                                       cursor = left(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak predecessor in the sorted collection of a particular value,\r
-               /// i.e. the largest item in the collection less than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is less than the minimum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak predecessor for.</param>\r
-               /// <returns>The weak predecessor.</returns>\r
-               [Tested]\r
-               public T WeakPredecessor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp < 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = right(cursor);\r
-                               }\r
-                               else if (comp == 0)\r
-                                       return cursor.item;\r
-                               else\r
-                                       cursor = left(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Below minimum of set");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the strict successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than or equal to the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the successor for.</param>\r
-               /// <returns>The successor.</returns>\r
-               [Tested]\r
-               public T Successor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp > 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = left(cursor);\r
-                               }\r
-                               else if (comp == 0)\r
-                               {\r
-                                       cursor = right(cursor);\r
-                                       while (cursor != null)\r
-                                       {\r
-                                               bestsofar = cursor;\r
-                                               cursor = left(cursor);\r
-                                       }\r
-                               }\r
-                               else\r
-                                       cursor = right(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Find the weak successor in the sorted collection of a particular value,\r
-               /// i.e. the least item in the collection greater than or equal to the supplied value.\r
-               /// <exception cref="InvalidOperationException"/> if no such element exists (the\r
-               /// supplied  value is greater than the maximum of this collection.)\r
-               /// </summary>\r
-               /// <param name="item">The item to find the weak successor for.</param>\r
-               /// <returns>The weak successor.</returns>\r
-               [Tested]\r
-               public T WeakSuccessor(T item)\r
-               {\r
-                       Node cursor = root, bestsofar = null;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                int comp = comparer.Compare(cursor.item, item);\r
-\r
-                if (comp == 0)\r
-                                       return cursor.item;\r
-                               else if (comp > 0)\r
-                               {\r
-                                       bestsofar = cursor;\r
-                                       cursor = left(cursor);\r
-                               }\r
-                               else\r
-                                       cursor = right(cursor);\r
-                       }\r
-\r
-                       if (bestsofar != null)\r
-                               return bestsofar.item;\r
-                       else\r
-                               throw new ArgumentOutOfRangeException("item", item, "Above maximum of set");\r
-               }\r
-\r
-               #endregion\r
-               \r
-               #region ISorted<T> Members\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items greater than or equal to a supplied value.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeFrom(T bot)\r
-               { return new Range(this, true, bot, false, default(T), EnumerationDirection.Forwards); }\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items between two supplied values.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive).</param>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)\r
-               { return new Range(this, true, bot, true, top, EnumerationDirection.Forwards); }\r
-\r
-\r
-               /// <summary>\r
-               /// Query this sorted collection for items less than a supplied value.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive).</param>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeTo(T top)\r
-               { return new Range(this, false, default(T), true, top, EnumerationDirection.Forwards); }\r
-\r
-\r
-               /// <summary>\r
-               /// Create a directed collection with the same items as this collection.\r
-               /// </summary>\r
-               /// <returns>The result directed collection.</returns>\r
-               [Tested]\r
-               public IDirectedCollectionValue<T> RangeAll()\r
-               { return new Range(this, false, default(T), false, default(T), EnumerationDirection.Forwards); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot) { return RangeFrom(bot); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); }\r
-\r
-\r
-               [Tested]\r
-               IDirectedEnumerable<T> ISorted<T>.RangeTo(T top) { return RangeTo(top); }\r
-\r
-\r
-               //Utility for CountXxxx. Actually always called with strict = true.\r
-               private int countTo(T item, bool strict)\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new NotSupportedException("Indexing not supported for snapshots");\r
-#endif\r
-#if MAINTAIN_SIZE\r
-                       int ind = 0, comp = 0; Node next = root;\r
-\r
-                       while (next != null)\r
-                       {\r
-                comp = comparer.Compare(item, next.item);\r
-                if (comp < 0)\r
-                                       next = next.left;\r
-                               else\r
-                               {\r
-                                       int leftcnt = next.left == null ? 0 : next.left.size;\r
-#if BAG\r
-                                       if (comp == 0)\r
-                                               return strict ? ind + leftcnt : ind + leftcnt + next.items;\r
-                                       else\r
-                                       {\r
-                                               ind = ind + next.items + leftcnt;\r
-                                               next = next.right;\r
-                                       }\r
-#else\r
-                                       if (comp == 0)\r
-                                               return strict ? ind + leftcnt : ind + leftcnt + 1;\r
-                                       else\r
-                                       {\r
-                                               ind = ind + 1 + leftcnt;\r
-                                               next = next.right;\r
-                                       }\r
-#endif\r
-                               }\r
-                       }\r
-\r
-                       //if we get here, we are at the same side of the whole collection:\r
-                       return ind;\r
-#else\r
-                       throw new NotSupportedException("Code compiled w/o size!");\r
-#endif\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Perform a search in the sorted collection for the ranges in which a\r
-               /// non-decreasing function from the item type to <code>int</code> is\r
-               /// negative, zero respectively positive. If the supplied cut function is\r
-               /// not non-decreasing, the result of this call is undefined.\r
-               /// </summary>\r
-               /// <param name="c">The cut function <code>T</code> to <code>int</code>, given\r
-               /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is\r
-               /// the <code>c.CompareTo(T that)</code> method.</param>\r
-               /// <param name="low">Returns the largest item in the collection, where the\r
-               /// cut function is negative (if any).</param>\r
-               /// <param name="lowIsValid">True if the cut function is negative somewhere\r
-               /// on this collection.</param>\r
-               /// <param name="high">Returns the least item in the collection, where the\r
-               /// cut function is positive (if any).</param>\r
-               /// <param name="highIsValid">True if the cut function is positive somewhere\r
-               /// on this collection.</param>\r
-               /// <returns></returns>\r
-               [Tested]\r
-               public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)\r
-               {\r
-                       Node cursor = root, lbest = null, rbest = null;\r
-                       bool res = false;\r
-\r
-                       while (cursor != null)\r
-                       {\r
-                               int comp = c.CompareTo(cursor.item);\r
-\r
-                               if (comp > 0)\r
-                               {\r
-                                       lbest = cursor;\r
-                                       cursor = right(cursor);\r
-                               }\r
-                               else if (comp < 0)\r
-                               {\r
-                                       rbest = cursor;\r
-                                       cursor = left(cursor);\r
-                               }\r
-                               else\r
-                               {\r
-                                       res = true;\r
-\r
-                                       Node tmp = left(cursor);\r
-\r
-                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
-                                               tmp = left(tmp);\r
-\r
-                                       if (tmp != null)\r
-                                       {\r
-                                               lbest = tmp;\r
-                                               tmp = right(tmp);\r
-                                               while (tmp != null)\r
-                                               {\r
-                                                       if (c.CompareTo(tmp.item) > 0)\r
-                                                       {\r
-                                                               lbest = tmp;\r
-                                                               tmp = right(tmp);\r
-                                                       }\r
-                                                       else\r
-                                                               tmp = left(tmp);\r
-                                               }\r
-                                       }\r
-\r
-                                       tmp = right(cursor);\r
-                                       while (tmp != null && c.CompareTo(tmp.item) == 0)\r
-                                               tmp = right(tmp);\r
-\r
-                                       if (tmp != null)\r
-                                       {\r
-                                               rbest = tmp;\r
-                                               tmp = left(tmp);\r
-                                               while (tmp != null)\r
-                                               {\r
-                                                       if (c.CompareTo(tmp.item) < 0)\r
-                                                       {\r
-                                                               rbest = tmp;\r
-                                                               tmp = left(tmp);\r
-                                                       }\r
-                                                       else\r
-                                                               tmp = right(tmp);\r
-                                               }\r
-                                       }\r
-\r
-                                       break;\r
-                               }\r
-                       }\r
-\r
-                       if (highIsValid = (rbest != null))\r
-                               high = rbest.item;\r
-                       else\r
-                               high = default(T);\r
-\r
-                       if (lowIsValid = (lbest != null))\r
-                               low = lbest.item;\r
-                       else\r
-                               low = default(T);\r
-\r
-                       return res;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items at or above a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountFrom(T bot) { return size - countTo(bot, true); }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="bot">The lower bound (inclusive)</param>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountFromTo(T bot, T top)\r
-               {\r
-            if (comparer.Compare(bot, top) >= 0)\r
-                return 0;\r
-\r
-                       return countTo(top, true) - countTo(bot, true);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Determine the number of items below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="top">The upper bound (exclusive)</param>\r
-               /// <returns>The number of matcing items.</returns>\r
-               [Tested]\r
-               public int CountTo(T top) { return countTo(top, true); }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection above or at a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeFrom(T low)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int count = CountFrom(low);\r
-\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       for (int i = 0; i < count; i++)\r
-                               DeleteMax();\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection between two supplied thresholds.\r
-               /// </summary>\r
-               /// <param name="low">The lower threshold (inclusive).</param>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeFromTo(T low, T hi)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int count = CountFromTo(low, hi);\r
-\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       for (int i = 0; i < count; i++)\r
-                               Remove(Predecessor(hi));\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Remove all items of this collection below a supplied threshold.\r
-               /// </summary>\r
-               /// <param name="hi">The upper threshold (exclusive).</param>\r
-               [Tested]\r
-               public void RemoveRangeTo(T hi)\r
-               {\r
-                       updatecheck();\r
-\r
-                       int count = CountTo(hi);\r
-\r
-                       if (count == 0)\r
-                               return;\r
-\r
-                       for (int i = 0; i < count; i++)\r
-                               DeleteMin();\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IPersistent<T> Members\r
-\r
-               private bool disposed;\r
-\r
-\r
-\r
-               /// <summary>\r
-               /// If this tree is a snapshot, remove registration in base tree\r
-               /// </summary>\r
-               [Tested]\r
-               public void Dispose()\r
-               {\r
-                       Dispose(true);\r
-                       GC.SuppressFinalize(this);\r
-               }\r
-\r
-\r
-               private void Dispose(bool disposing)\r
-               {\r
-                       if (!disposed)\r
-                       {\r
-                               if (disposing) { }\r
-#if NCP\r
-                               if (isSnapShot)\r
-                               {\r
-                                       snapdata.Remove(generation, disposing);\r
-                                       snapdata = null;\r
-                                       root = null;\r
-                                       dirs = null;\r
-                                       path = null;\r
-                                       comparer = null;\r
-                                       disposed = true;\r
-                               }\r
-                               else { }\r
-#endif\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// If this tree is a snapshot, remove registration in base tree\r
-               /// </summary>\r
-               ~TreeBag()\r
-               {\r
-                       Dispose(false);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Make a (read-only) snap shot of this collection.\r
-               /// </summary>\r
-               /// <returns>The snap shot.</returns>\r
-               [Tested]\r
-               public ISorted<T> Snapshot()\r
-               {\r
-#if NCP\r
-                       if (isSnapShot)\r
-                               throw new InvalidOperationException("Cannot snapshot a snapshot");\r
-\r
-                       if (snapdata == null)\r
-                       {\r
-                               snapdata = new SnapData(this);\r
-                       }\r
-\r
-                       snapdata.Add(generation, this);\r
-\r
-                       TreeBag<T> res = (TreeBag<T>)MemberwiseClone();\r
-\r
-                       res.isReadOnly = true; res.isSnapShot = true;\r
-                       maxsnapid = generation++;\r
-                       return res;\r
-#endif\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Snapdata nested class\r
-               //In a class by itself: the tree itself and snapshots must have a ref to \r
-               //the snapids, but we do not want snapshots to have a (strong) ref to the full\r
-               //updatable tree, which should be garbagecollectable even if there are still \r
-               //live snapshots!\r
-               //\r
-               //Access to SnapData should be thread safe since we expect finalisers \r
-               //of snapshots to remove a snapid that is garbagecollected without \r
-               //having been explicitly Disposed. Therefore we access SnapData through \r
-               //synchronized method/properties.\r
-\r
-#if NCP\r
-               class SnapData\r
-               {\r
-                       TreeBag<int> snapids = new TreeBag<int>(new IC());\r
-\r
-                       WeakReference master;\r
-\r
-\r
-                       internal SnapData(TreeBag<T> tree)\r
-                       {\r
-                               master = new WeakReference(tree);\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       public bool Add(int i, TreeBag<T> tree)\r
-                       {\r
-                               lock (this)\r
-                               {\r
-                                       bool res = snapids.Add(i);\r
-\r
-                                       //assert the following will be i:\r
-                                       tree.maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
-                                       return res;\r
-                               }\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       public bool Remove(int i, bool updmaxsnapid)\r
-                       {\r
-                               lock (this)\r
-                               {\r
-                                       bool res = snapids.Remove(i);\r
-\r
-                                       if (updmaxsnapid)\r
-                                       {\r
-                                               //Is this safe or/and overkill?\r
-                                               object t = master.Target;\r
-\r
-                                               if (t != null && master.IsAlive)\r
-                                               {\r
-                                                       ((TreeBag<T>)t).maxsnapid = snapids.Count > 0 ? snapids.FindMax() : -1;\r
-                                               }\r
-                                       }\r
-\r
-                                       return res;\r
-                               }\r
-                       }\r
-               }\r
-\r
-#endif\r
-               #endregion\r
-\r
-               #region TreeBag.Range nested class\r
-                       \r
-               internal class Range: CollectionValueBase<T>, IDirectedCollectionValue<T>\r
-               {\r
-                       //We actually need exclusive upper and lower bounds, and flags to \r
-                       //indicate whether the bound is present (we canot rely on default(T))\r
-                       private int stamp;\r
-\r
-                       private TreeBag<T> basis;\r
-\r
-                       private T lowend, highend;\r
-\r
-                       private bool haslowend, hashighend;\r
-\r
-                       EnumerationDirection direction;\r
-\r
-\r
-                       [Tested]\r
-                       public Range(TreeBag<T> basis, bool haslowend, T lowend, bool hashighend, T highend, EnumerationDirection direction)\r
-                       {\r
-                               this.basis = basis;\r
-                               stamp = basis.stamp;\r
-\r
-                               //lowind will be const; should we cache highind?\r
-                               this.lowend = lowend; //Inclusive\r
-                               this.highend = highend;//Exclusive\r
-                               this.haslowend = haslowend;\r
-                               this.hashighend = hashighend;\r
-                               this.direction = direction;\r
-                       }\r
-                       #region IEnumerable<T> Members\r
-\r
-\r
-                       #region TreeBag.Range.Enumerator nested class\r
-                       \r
-                       public class Enumerator: MSG.IEnumerator<T>\r
-                       {\r
-                               #region Private Fields\r
-                               private bool valid = false, ready = true;\r
-\r
-                               private IComparer<T> comparer;\r
-\r
-                               private T current;\r
-#if BAG\r
-                               int togo;\r
-#endif\r
-\r
-                               private Node cursor;\r
-\r
-                               private Node[] path; // stack of nodes\r
-\r
-                               private int level = 0;\r
-\r
-                               private Range range;\r
-\r
-                               private bool forwards;\r
-\r
-                               #endregion\r
-                               [Tested]\r
-                               public Enumerator(Range range)\r
-                               {\r
-                                       comparer = range.basis.comparer;\r
-                                       path = new Node[2 * range.basis.blackdepth];\r
-                                       this.range = range;\r
-                                       forwards = range.direction == EnumerationDirection.Forwards;\r
-                                       cursor = new Node();\r
-                                       if (forwards)\r
-                                               cursor.right = range.basis.root;\r
-                                       else\r
-                                               cursor.left = range.basis.root;\r
-                                       range.basis.modifycheck(range.stamp);\r
-                               }\r
-\r
-\r
-                               int compare(T i1, T i2) { return comparer.Compare(i1, i2); }\r
-\r
-\r
-                               /// <summary>\r
-                               /// Undefined if enumerator is not valid (MoveNext hash been called returning true)\r
-                               /// </summary>\r
-                               /// <value>The current value of the enumerator.</value>\r
-                               [Tested]\r
-                               public T Current\r
-                               {\r
-                                       [Tested]\r
-                                       get\r
-                                       {\r
-                                               if (valid)\r
-                                                       return current;\r
-                                               else\r
-                                                       throw new InvalidOperationException();\r
-                                       }\r
-                               }\r
-\r
-\r
-                               //Maintain a stack of nodes that are roots of\r
-                               //subtrees not completely exported yet. Invariant:\r
-                               //The stack nodes together with their right subtrees\r
-                               //consists of exactly the items we have not passed\r
-                               //yet (the top of the stack holds current item).\r
-                               /// <summary>\r
-                               /// Move enumerator to next item in tree, or the first item if\r
-                               /// this is the first call to MoveNext. \r
-                               /// <exception cref="InvalidOperationException"/> if underlying tree was modified.\r
-                               /// </summary>\r
-                               /// <returns>True if enumerator is valid now</returns>\r
-                               [Tested]\r
-                               public bool MoveNext()\r
-                               {\r
-                                       range.basis.modifycheck(range.stamp);\r
-                                       if (!ready)\r
-                                               return false;\r
-#if BAG\r
-                                       if (--togo> 0)\r
-                                               return true;\r
-#endif\r
-                                       if (forwards)\r
-                                       {\r
-                                               if (!valid && range.haslowend)\r
-                                               {\r
-                                                       cursor = cursor.right;\r
-                                                       while (cursor != null)\r
-                                                       {\r
-                                                               int comp = compare(cursor.item, range.lowend);\r
-\r
-                                                               if (comp > 0)\r
-                                                               {\r
-                                                                       path[level++] = cursor;\r
-#if NCP\r
-                                                                       cursor = range.basis.left(cursor);\r
-#else\r
-                                                                       cursor = cursor.left;\r
-#endif\r
-                                                               }\r
-                                                               else if (comp < 0)\r
-                                                               {\r
-#if NCP\r
-                                                                       cursor = range.basis.right(cursor);\r
-#else\r
-                                                                       cursor = cursor.right;\r
-#endif\r
-                                                               }\r
-                                                               else\r
-                                                               {\r
-                                                                       path[level] = cursor;\r
-                                                                       break;\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       if (cursor == null)\r
-                                                       {\r
-                                                               if (level == 0)\r
-                                                                       return valid = ready = false;\r
-                                                               else\r
-                                                                       cursor = path[--level];\r
-                                                       }\r
-                                               }\r
-#if NCP\r
-                                               else if (range.basis.right(cursor) != null)\r
-                                               {\r
-                                                       path[level] = cursor = range.basis.right(cursor);\r
-\r
-                                                       Node next = range.basis.left(cursor);\r
-\r
-                                                       while (next != null)\r
-                                                       {\r
-                                                               path[++level] = cursor = next;\r
-                                                               next = range.basis.left(cursor);\r
-                                                       }\r
-                                               }\r
-#else\r
-                                               else if (cursor.right != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.right;\r
-                                                       while (cursor.left != null)\r
-                                                               path[++level] = cursor = cursor.left;\r
-                                               }\r
-#endif\r
-                                               else if (level == 0)\r
-                                                       return valid = ready = false;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-                                               if (range.hashighend && compare(current, range.highend) >= 0)\r
-                                                       return valid = ready = false;\r
-\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                               return valid = true;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               if (!valid && range.hashighend)\r
-                                               {\r
-                                                       cursor = cursor.left;\r
-                                                       while (cursor != null)\r
-                                                       {\r
-                                                               int comp = compare(cursor.item, range.highend);\r
-\r
-                                                               if (comp < 0)\r
-                                                               {\r
-                                                                       path[level++] = cursor;\r
-#if NCP\r
-                                                                       cursor = range.basis.right(cursor);\r
-#else\r
-                                                                       cursor = cursor.right;\r
-#endif\r
-                                                               }\r
-                                                               else\r
-                                                               {\r
-#if NCP\r
-                                                                       cursor = range.basis.left(cursor);\r
-#else\r
-                                                                       cursor = cursor.left;\r
-#endif\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       if (cursor == null)\r
-                                                       {\r
-                                                               if (level == 0)\r
-                                                                       return valid = ready = false;\r
-                                                               else\r
-                                                                       cursor = path[--level];\r
-                                                       }\r
-                                               }\r
-#if NCP\r
-                                               else if (range.basis.left(cursor) != null)\r
-                                               {\r
-                                                       path[level] = cursor = range.basis.left(cursor);\r
-\r
-                                                       Node next = range.basis.right(cursor);\r
-\r
-                                                       while (next != null)\r
-                                                       {\r
-                                                               path[++level] = cursor = next;\r
-                                                               next = range.basis.right(cursor);\r
-                                                       }\r
-                                               }\r
-#else\r
-                                               else if (cursor.left != null)\r
-                                               {\r
-                                                       path[level] = cursor = cursor.left;\r
-                                                       while (cursor.right != null)\r
-                                                               path[++level] = cursor = cursor.right;\r
-                                               }\r
-#endif\r
-                                               else if (level == 0)\r
-                                                       return valid = ready = false;\r
-                                               else\r
-                                                       cursor = path[--level];\r
-\r
-                                               current = cursor.item;\r
-                                               if (range.haslowend && compare(current, range.lowend) < 0)\r
-                                                       return valid = ready = false;\r
-\r
-#if BAG\r
-                                               togo = cursor.items;\r
-#endif\r
-                                               return valid = true;\r
-                                       }\r
-                               }\r
-\r
-                               void SC.IEnumerator.Reset ()\r
-                               {\r
-                                       throw new NotImplementedException ();\r
-                               }\r
-\r
-                               object SC.IEnumerator.Current {\r
-                                       get {\r
-                                               return Current;\r
-                                       }\r
-                               }\r
-\r
-                               [Tested]\r
-                               public void Dispose()\r
-                               {\r
-                                       comparer = null;\r
-                                       current = default(T);\r
-                                       cursor = null;\r
-                                       path = null;\r
-                                       range = null;\r
-                               }\r
-                       }\r
-\r
-                       #endregion\r
-\r
-                       [Tested]\r
-                       public override MSG.IEnumerator<T> GetEnumerator() { return new Enumerator(this); }\r
-\r
-\r
-                       [Tested]\r
-                       public EnumerationDirection Direction { [Tested]get { return direction; } }\r
-\r
-\r
-                       #endregion\r
-\r
-                       #region Utility\r
-                       \r
-                       bool inside(T item)\r
-                       {\r
-                return (!haslowend || basis.comparer.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer.Compare(item, highend) < 0);\r
-            }\r
-\r
-\r
-                       void checkstamp()\r
-                       {\r
-                               if (stamp < basis.stamp)\r
-                                       throw new InvalidOperationException("Base collection was modified behind my back!");\r
-                       }\r
-\r
-\r
-                       void syncstamp() { stamp = basis.stamp; }\r
-                       \r
-                       #endregion\r
-\r
-                       [Tested]\r
-                       public IDirectedCollectionValue<T> Backwards()\r
-                       {\r
-                               Range b = (Range)MemberwiseClone();\r
-\r
-                               b.direction = direction == EnumerationDirection.Forwards ? EnumerationDirection.Backwards : EnumerationDirection.Forwards;\r
-                               return b;\r
-                       }\r
-\r
-\r
-                       [Tested]\r
-                       IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
-\r
-\r
-                       [Tested]\r
-                       public override int Count\r
-                       {\r
-                               [Tested]\r
-                               get\r
-                               {\r
-                                       return haslowend ? (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : (hashighend ? basis.CountTo(highend) : basis.Count);\r
-                               }\r
-                       }\r
-\r
-            //TODO: check that this is correct\r
-            public override Speed CountSpeed { get { return Speed.Log; } }\r
-\r
-        }\r
-\r
-               #endregion\r
-\r
-               #region fixheight utility\r
-\r
-#if MAINTAIN_HEIGHT\r
-               public void fixheight(Node n)\r
-               {\r
-                       int lh = n.left == null ? 0 : n.left.height + 1;\r
-                       int rh = n.right == null ? 0 : n.right.height + 1;\r
-\r
-                       n.height = (short)(lh > rh ? lh : rh);\r
-               }\r
-#endif\r
-\r
-               #endregion\r
-\r
-               #region Diagnostics\r
-               /// <summary>\r
-               /// Display this node on the console, and recursively its subnodes.\r
-               /// </summary>\r
-               /// <param name="n">Node to display</param>\r
-               /// <param name="space">Indentation</param>\r
-               private void minidump(Node n, string space)\r
-               {\r
-                       if (n == null)\r
-                       {\r
-                               //      System.Console.WriteLine(space + "null");\r
-                       }\r
-                       else\r
-                       {\r
-                               minidump(n.right, space + "  ");\r
-                               Console.WriteLine(String.Format("{0} {4} (rank={5}, size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, \r
-#if MAINTAIN_SIZE\r
-                               n.size, \r
-#else\r
-                               0,\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               n.height, \r
-#else\r
-                               0,\r
-#endif\r
-#if NCP\r
-                               n.generation, \r
-#endif\r
-                               n.red ? "RED" : "BLACK", \r
-#if MAINTAIN_RANK\r
-                               n.rank, \r
-#else\r
-                               0,\r
-#endif\r
-#if TRACE_ID\r
-                                       n.id,\r
-#else\r
-                               0,\r
-#endif\r
-#if NCP\r
-#if SEPARATE_EXTRA\r
-                               n.extra == null ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.extra.lastgeneration, n.extra.leftnode ? "L" : "R", n.extra.oldref == null ? "()" : "" + n.extra.oldref.item),\r
-#else\r
-                               n.lastgeneration == -1 ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item),\r
-#endif\r
-#else\r
-                               "",\r
-#endif\r
-#if BAG\r
-                               n.items\r
-#else\r
-                               1\r
-#endif\r
-                               ));\r
-                               minidump(n.left, space + "  ");\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Print the tree structure to the console stdout.\r
-               /// </summary>\r
-               [Tested(via = "Sawtooth")]\r
-               public void dump() { dump(""); }\r
-\r
-\r
-               /// <summary>\r
-               /// Print the tree structure to the console stdout.\r
-               /// </summary>\r
-               [Tested(via = "Sawtooth")]\r
-               public void dump(string msg)\r
-               {\r
-                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
-#if MAINTAIN_HEIGHT\r
-                       depth\r
-#else\r
-                       0\r
-#endif\r
-                       , \r
-#if NCP\r
-                       generation\r
-#endif\r
-                       ));\r
-                       minidump(root, "");\r
-                       check("", Console.Out); Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Display this tree on the console.\r
-               /// </summary>\r
-               /// <param name="msg">Identifying string of this call to dump</param>\r
-               /// <param name="err">Extra (error)message to include</param>\r
-               void dump(string msg, string err)\r
-               {\r
-                       Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,\r
-#if MAINTAIN_HEIGHT\r
-                       depth\r
-#else\r
-                       0\r
-#endif\r
-                       ,  \r
-#if NCP\r
-                       generation                              \r
-#endif\r
-                       ));\r
-                       minidump(root, ""); Console.Write(err);\r
-                       Console.WriteLine("<<<<<<<<<<<<<<<<<<<");\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Print warning m on o if b is false.\r
-               /// </summary>\r
-               /// <param name="b">Condition that should hold</param>\r
-               /// <param name="n">Place (used for id display)</param>\r
-               /// <param name="m">Message</param>\r
-               /// <param name="o">Output stream</param>\r
-               /// <returns>b</returns>\r
-               bool massert(bool b, Node n, string m, System.IO.TextWriter o)\r
-               {\r
-                       if (!b) o.WriteLine("*** Node (item={0}, id={1}): {2}", n.item, \r
-#if TRACE_ID\r
-                               n.id\r
-#else\r
-                               0\r
-#endif\r
-                               , m);\r
-\r
-                       return b;\r
-               }\r
-\r
-\r
-               bool rbminicheck(Node n, bool redp, int prank, System.IO.TextWriter o, out T min, out T max, out int blackheight, int maxgen)\r
-               {//Red-Black invariant\r
-                       bool res = true;\r
-\r
-                       res = massert(!(n.red && redp), n, "RED parent of RED node", o) && res;\r
-                       res = massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty", o) && res;\r
-                       res = massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty", o) && res;\r
-#if MAINTAIN_RANK\r
-                       res = massert(n.red == (n.rank == prank), n, "Bad color", o) && res;\r
-                       res = massert(prank <= n.rank + 1, n, "Parentrank-rank >= 2", o) && res;\r
-                       res = massert((n.left != null && n.right != null) || n.rank == 1, n, "Rank>1 but empty child", o) && res;\r
-#endif\r
-#if BAG\r
-                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;\r
-\r
-                       res = massert(sb, n, "Bad size", o) && res;\r
-#elif MAINTAIN_SIZE\r
-                       bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;\r
-\r
-                       res = massert(sb, n, "Bad size", o) && res;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                       int lh = n.left == null ? 0 : n.left.height + 1;\r
-                       int rh = n.right == null ? 0 : n.right.height + 1;\r
-\r
-                       res = massert(n.height == (lh < rh ? rh : lh), n, "Bad height", o) && res;\r
-#endif\r
-                       int therank =\r
-#if MAINTAIN_RANK\r
-                       n.rank;\r
-#else\r
-                       0;\r
-#endif\r
-                       min = max = n.item;\r
-\r
-                       T otherext;\r
-                       int lbh = 0, rbh = 0;\r
-\r
-                       if (n.left != null)\r
-                       {\r
-                               res = rbminicheck(n.left, n.red, therank, o, out min, out otherext, out lbh, generation) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
-            }\r
-\r
-                       if (n.right != null)\r
-                       {\r
-                               res = rbminicheck(n.right, n.red, therank, o, out otherext, out max, out rbh, generation) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
-            }\r
-\r
-                       res = massert(rbh == lbh, n, "Different blackheights of children", o) && res;\r
-                       blackheight = n.red ? rbh : rbh + 1;\r
-#if MAINTAIN_RANK\r
-                       //The rank is the number of black nodes from this one to\r
-                       //the leaves, not counting this one, but counting 1 for the empty\r
-                       //virtual leaf nodes.\r
-                       res = massert(n.rank == rbh + 1, n, "rank!=blackheight " + blackheight, o) && res;\r
-#endif\r
-                       return res;\r
-               }\r
-\r
-\r
-\r
-\r
-#if NCP\r
-\r
-               bool rbminisnapcheck(Node n, System.IO.TextWriter o, out int size, out T min, out T max)\r
-               {\r
-                       bool res = true;\r
-\r
-                       min = max = n.item;\r
-\r
-                       int lsz = 0, rsz = 0;\r
-                       T otherext;\r
-#if SEPARATE_EXTRA\r
-                       Node.Extra extra = n.extra;\r
-                       Node child = (extra != null && extra.lastgeneration >= treegen && extra.leftnode) ? extra.oldref : n.left;\r
-#else\r
-                       Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left;\r
-#endif\r
-                       if (child != null)\r
-                       {\r
-                               res = rbminisnapcheck(child, o, out lsz, out min, out otherext) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;\r
-            }\r
-\r
-#if SEPARATE_EXTRA\r
-                       child = (extra != null && extra.lastgeneration >= treegen && !extra.leftnode) ? extra.oldref : n.right;\r
-#else\r
-                       child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right;\r
-#endif\r
-                       if (child != null)\r
-                       {\r
-                               res = rbminisnapcheck(child, o, out rsz, out otherext, out max) && res;\r
-                res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;\r
-            }\r
-#if BAG\r
-                       size = n.items + lsz + rsz;\r
-#else\r
-                       size = 1 + lsz + rsz;\r
-#endif\r
-                       return res;\r
-               }\r
-#endif\r
-\r
-               /// <summary>\r
-               /// Checks red-black invariant. Dumps tree to console if bad\r
-               /// </summary>\r
-               /// <param name="name">Title of dump</param>\r
-               /// <returns>false if invariant violation</returns>\r
-               [Tested(via = "Sawtooth")]\r
-               public bool Check(string name)\r
-               {\r
-                       System.Text.StringBuilder e = new System.Text.StringBuilder();\r
-                       System.IO.TextWriter o = new System.IO.StringWriter(e);\r
-\r
-                       if (!check(name, o))\r
-                               return true;\r
-                       else\r
-                       {\r
-                               dump(name, e.ToString());\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Checks red-black invariant. Dumps tree to console if bad\r
-               /// </summary>\r
-               /// <returns>false if invariant violation</returns>\r
-               [Tested]\r
-               public bool Check()\r
-               {\r
-                       //return check("", System.IO.TextWriter.Null);\r
-                       //Console.WriteLine("bamse");\r
-                       return Check("-");\r
-               }\r
-\r
-\r
-               bool check(string msg, System.IO.TextWriter o)\r
-               {\r
-                       if (root != null)\r
-                       {\r
-                               T max, min;\r
-                               int blackheight;\r
-#if NCP\r
-                               if (isSnapShot)\r
-                               {\r
-                                       //Console.WriteLine("Im'a snapshot");\r
-                                       int thesize;\r
-                                       bool rv = rbminisnapcheck(root, o, out thesize, out min, out max);\r
-\r
-                                       rv = massert(size == thesize, root, "bad snapshot size", o) && rv;\r
-                                       return !rv;\r
-                               }\r
-#endif\r
-#if MAINTAIN_RANK\r
-                               bool res = rbminicheck(root, false, root.rank + 1, o, out min, out max, out blackheight, generation);\r
-\r
-                               res = massert(root.rank == blackdepth, root, "blackdepth!=root.rank", o) && res;\r
-#else\r
-                               bool res = rbminicheck(root, false, 0, o, out min, out max, out blackheight, generation);\r
-#endif\r
-                               res = massert(blackheight == blackdepth, root, "bad blackh/d", o) && res;\r
-                               res = massert(!root.red, root, "root is red", o) && res;\r
-#if MAINTAIN_SIZE\r
-                               res = massert(root.size == size, root, "count!=root.size", o) && res;\r
-#endif\r
-#if MAINTAIN_HEIGHT\r
-                               res = massert(root.height == depth, root, "depth!=root.height", o) && res;\r
-#endif\r
-                               return !res;\r
-                       }\r
-                       else\r
-                               return false;\r
-               }\r
-               #endregion                      \r
-       }\r
-}\r
-\r
-#endif\r
diff --git a/mcs/class/Mono.C5/trees/TreeDictionary.cs b/mcs/class/Mono.C5/trees/TreeDictionary.cs
deleted file mode 100644 (file)
index 6194c20..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#if NET_2_0\r
-/*\r
- Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>\r
- Permission is hereby granted, free of charge, to any person obtaining a copy\r
- of this software and associated documentation files (the "Software"), to deal\r
- in the Software without restriction, including without limitation the rights\r
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- copies of the Software, and to permit persons to whom the Software is\r
- furnished to do so, subject to the following conditions:\r
\r
- The above copyright notice and this permission notice shall be included in\r
- all copies or substantial portions of the Software.\r
\r
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- SOFTWARE.\r
-*/\r
-\r
-using System;\r
-using MSG = System.Collections.Generic;\r
-\r
-namespace C5\r
-{\r
-       /// <summary>\r
-       /// A sorted generic dictionary based on a red-black tree set.\r
-       /// </summary>\r
-       public class TreeDictionary<K,V>: DictionaryBase<K,V>, IDictionary<K,V>, ISortedDictionary<K,V>\r
-       {\r
-               #region Fields\r
-\r
-               private TreeSet<KeyValuePair<K,V>> sortedpairs;\r
-\r
-               #endregion\r
-\r
-               #region Constructors\r
-\r
-               /// <summary>\r
-               /// Create a red-black tree dictionary using the natural comparer for keys.\r
-               /// <exception cref="ArgumentException"/> if the key type K is not comparable.\r
-               /// </summary>\r
-               public TreeDictionary() : this(ComparerBuilder.FromComparable<K>.Examine()) { }\r
-\r
-               /// <summary>\r
-               /// Create a red-black tree dictionary using an external comparer for keys.\r
-               /// </summary>\r
-               /// <param name="c">The external comparer</param>\r
-               public TreeDictionary(IComparer<K> c)\r
-               {\r
-                       pairs = sortedpairs = new TreeSet<KeyValuePair<K,V>>(new KeyValuePairComparer<K,V>(c));\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region ISortedDictionary<K,V> Members\r
-\r
-               /// <summary>\r
-               /// Get the entry in the dictionary whose key is the\r
-               /// predecessor of a specified key.\r
-               /// </summary>\r
-               /// <param name="key">The key</param>\r
-               /// <returns>The entry</returns>\r
-               [Tested]\r
-               public KeyValuePair<K,V> Predecessor(K key)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       return sortedpairs.Predecessor(p);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get the entry in the dictionary whose key is the\r
-               /// weak predecessor of a specified key.\r
-               /// </summary>\r
-               /// <param name="key">The key</param>\r
-               /// <returns>The entry</returns>\r
-               [Tested]\r
-               public KeyValuePair<K,V> WeakPredecessor(K key)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       return sortedpairs.WeakPredecessor(p);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get the entry in the dictionary whose key is the\r
-               /// successor of a specified key.\r
-               /// </summary>\r
-               /// <param name="key">The key</param>\r
-               /// <returns>The entry</returns>\r
-               [Tested]\r
-               public KeyValuePair<K,V> Successor(K key)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       return sortedpairs.Successor(p);\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Get the entry in the dictionary whose key is the\r
-               /// weak successor of a specified key.\r
-               /// </summary>\r
-               /// <param name="key">The key</param>\r
-               /// <returns>The entry</returns>\r
-               [Tested]\r
-               public KeyValuePair<K,V> WeakSuccessor(K key)\r
-               {\r
-                       KeyValuePair<K,V> p = new KeyValuePair<K,V>(key);\r
-\r
-                       return sortedpairs.WeakSuccessor(p);\r
-               }\r
-\r
-               #endregion\r
-\r
-               //TODO: put in interface\r
-               /// <summary>\r
-               /// Make a snapshot of the current state of this dictionary\r
-               /// </summary>\r
-               /// <returns>The snapshot</returns>\r
-               [Tested]\r
-               public MSG.IEnumerable<KeyValuePair<K,V>> Snapshot()\r
-               {\r
-                       TreeDictionary<K,V> res = (TreeDictionary<K,V>)MemberwiseClone();\r
-\r
-                       res.pairs = (TreeSet<KeyValuePair<K,V>>)sortedpairs.Snapshot();\r
-                       return res;\r
-               }\r
-       }\r
-}\r
-#endif\r
diff --git a/mcs/class/Mono.C5/trees/set2bag.pl b/mcs/class/Mono.C5/trees/set2bag.pl
deleted file mode 100644 (file)
index 86de856..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/perl\r
-\r
-use strict;\r
-\r
-open(RBTS,"RedBlackTree.cs") || die "Can't open infile";\r
-\r
-rename "RedBlackTreeBag.cs", "RedBlackTreeBag.cs.old" || die "Can't backup";\r
-\r
-open(RBTB,">RedBlackTreeBag.cs")  || die "Can't open outfile";\r
-\r
-my @cond=(1);\r
-my $printing = 1;\r
-\r
-#Assume all conditions on BAG symbol is '#if BAG'\r
-while (<RBTS>) {\r
-  if (/^#define BAG/) {\r
-    print RBTB "#define BAG\r\n";\r
-    next;\r
-  }\r
-  s/TreeSet/TreeBag/g;\r
-  print RBTB;\r
-}\r
-\r
-close(RBTS) || die "Can't close infile";\r
-close(RBTB) || die "Can't close outfile";\r