Bringing C5 1.0 into the main branch.
authorMartin Baulig <martin@novell.com>
Thu, 16 Feb 2006 14:00:18 +0000 (14:00 -0000)
committerMartin Baulig <martin@novell.com>
Thu, 16 Feb 2006 14:00:18 +0000 (14:00 -0000)
svn path=/trunk/mcs/; revision=56931

33 files changed:
mcs/class/Mono.C5/C5/AssemblyInfo.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Attributes.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Builtin.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/C5.csproj [new file with mode: 0644]
mcs/class/Mono.C5/C5/ClsdiagWork.png [new file with mode: 0644]
mcs/class/Mono.C5/C5/Collections.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Comparer.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Delegates.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Dictionaries.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Enums.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Events.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Exceptions.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Formatting.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Hashers.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Interfaces.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/MappedEnumerators.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Random.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Records.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/Sorting.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/ViewSupport.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/WrappedArray.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/CircularQueue.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/LinkedList.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/trees/.cvsignore [new file with mode: 0644]
mcs/class/Mono.C5/C5/trees/RedBlackTreeDictionary.cs [new file with mode: 0644]
mcs/class/Mono.C5/C5/trees/RedBlackTreeSet.cs [new file with mode: 0644]

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..a649742
--- /dev/null
@@ -0,0 +1,79 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 release 1.0.0")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("")]\r
+[assembly: AssemblyCopyright("(c) 2003-2006 Niels Kokholm and Peter Sestoft")]\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("1.0.0")]\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(false)]\r
+//[assembly: AssemblyKeyFile("..\\..\\..\\c5.snk")]\r
+//[assembly: AssemblyKeyName("")]\r
diff --git a/mcs/class/Mono.C5/C5/Attributes.cs b/mcs/class/Mono.C5/C5/Attributes.cs
new file mode 100644 (file)
index 0000000..9302996
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+using System;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+namespace C5\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
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Builtin.cs b/mcs/class/Mono.C5/C5/Builtin.cs
new file mode 100644 (file)
index 0000000..3b6a4b0
--- /dev/null
@@ -0,0 +1,186 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+using System;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  #region int stuff\r
+  [Serializable]\r
+  class IntComparer : SCG.IComparer<int>\r
+  {\r
+    [Tested]\r
+    public int Compare(int a, int b) { return a > b ? 1 : a < b ? -1 : 0; }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An equalityComparer for System.Int32 integers. \r
+  /// <para>This class is a singleton and the instance can be accessed\r
+  /// via the static <see cref="P:C5.IntEqualityComparer.Default"/> property</para>\r
+  /// </summary>\r
+  [Serializable]\r
+  public class IntEqualityComparer : SCG.IEqualityComparer<int>\r
+  {\r
+    static IntEqualityComparer cached;\r
+    IntEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    [Tested]\r
+    public static IntEqualityComparer Default { get { return cached ?? (cached = new IntEqualityComparer()); } }\r
+    /// <summary>\r
+    /// Get the hash code of this integer, that is, 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
+    /// Determine whether two integers are equal\r
+    /// </summary>\r
+    /// <param name="int1">first integer</param>\r
+    /// <param name="int2">second integer</param>\r
+    /// <returns>True if equal</returns>\r
+    [Tested]\r
+    public bool Equals(int int1, int int2) { return int1 == int2; }\r
+  }\r
+\r
+  #endregion\r
+\r
+  #region double stuff\r
+  class DoubleComparer : SCG.IComparer<double>\r
+  {\r
+    public int Compare(double a, double b) { return a > b ? 1 : a < b ? -1 : 0; }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An equalityComparer for double. \r
+  /// <para>This class is a singleton and the instance can be accessed\r
+  /// via the static <see cref="P:C5.DoubleEqualityComparer.Default"/> property</para>\r
+  /// </summary>\r
+  public class DoubleEqualityComparer : SCG.IEqualityComparer<double>\r
+  {\r
+    static DoubleEqualityComparer cached;\r
+    DoubleEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    [Tested]\r
+    public static DoubleEqualityComparer Default { get { return cached ?? (cached = new DoubleEqualityComparer()); } }\r
+    /// <summary>\r
+    /// Get the hash code of this double,\r
+    /// </summary>\r
+    /// <param name="item">The double</param>\r
+    /// <returns>The same</returns>\r
+    [Tested]\r
+    public int GetHashCode(double item) { return item.GetHashCode(); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if two doubles are equal\r
+    /// </summary>\r
+    /// <param name="item1">first double</param>\r
+    /// <param name="item2">second double</param>\r
+    /// <returns>True if equal</returns>\r
+    [Tested]\r
+    public bool Equals(double item1, double item2) { return item1 == item2; }\r
+  }\r
+  #endregion\r
+\r
+  #region byte stuff\r
+  class ByteComparer : SCG.IComparer<byte>\r
+  {\r
+    public int Compare(byte a, byte b) { return a > b ? 1 : a < b ? -1 : 0; }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An equalityComparer for byte\r
+  /// <para>This class is a singleton and the instance can be accessed\r
+  /// via the <see cref="P:C5.ByteEqualityComparer.Default"/> property</para>\r
+  /// </summary>\r
+  public class ByteEqualityComparer : SCG.IEqualityComparer<byte>\r
+  {\r
+    static ByteEqualityComparer cached = new ByteEqualityComparer();\r
+    ByteEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public static ByteEqualityComparer Default { get { return cached ?? (cached = new ByteEqualityComparer()); } }\r
+    /// <summary>\r
+    /// Get the hash code of this byte, i.e. itself\r
+    /// </summary>\r
+    /// <param name="item">The byte</param>\r
+    /// <returns>The same</returns>\r
+    public int GetHashCode(byte item) { return item; }\r
+\r
+    /// <summary>\r
+    /// Check if two bytes are equal\r
+    /// </summary>\r
+    /// <param name="item1">first byte</param>\r
+    /// <param name="item2">second byte</param>\r
+    /// <returns>True if equal</returns>\r
+    public bool Equals(byte item1, byte item2) { return item1 == item2; }\r
+  }\r
+  #endregion\r
+\r
+  #region char stuff\r
+  class CharComparer : SCG.IComparer<char>\r
+  {\r
+    public int Compare(char a, char b) { return a > b ? 1 : a < b ? -1 : 0; }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An equalityComparer for char.\r
+  /// </summary>\r
+  public class CharEqualityComparer : SCG.IEqualityComparer<char>\r
+  {\r
+    static CharEqualityComparer cached = new CharEqualityComparer();\r
+    CharEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public static CharEqualityComparer Default { get { return cached ?? (cached = new CharEqualityComparer()); } }\r
+\r
+    /// <summary>\r
+    /// Get the hash code of this char\r
+    /// </summary>\r
+    /// <param name="item">The char</param>\r
+    /// <returns>The same</returns>\r
+    public int GetHashCode(char item) { return item.GetHashCode(); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if two chars are equal\r
+    /// </summary>\r
+    /// <param name="item1">first char</param>\r
+    /// <param name="item2">second char</param>\r
+    /// <returns>True if equal</returns>\r
+    public bool Equals(char item1, char item2) { return item1 == item2; }\r
+  }\r
+  #endregion\r
+\r
+}
\ No newline at end of file
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..eb0c5b0
--- /dev/null
@@ -0,0 +1,128 @@
+<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</DefineConstants>\r
+    <WarningLevel>4</WarningLevel>\r
+    <IncrementalBuild>false</IncrementalBuild>\r
+    <DocumentationFile>c5.xml</DocumentationFile>\r
+    <FxCopRules>+ComRules.dll;+DesignRules.dll|AbstractTypesShouldNotHaveConstructors;+DesignRules.dll|AddAndSubtractOverrideShouldHaveOperatorEqualsOverride;-DesignRules.dll|AssembliesAreMarkedClsCompliant;-DesignRules.dll|AssembliesHaveStrongNames;+DesignRules.dll|AssembliesHaveVersionNumbers;-DesignRules.dll|AssembliesShouldBeComVisibleAttributed;+DesignRules.dll|AttributesAreAttributeUsageAttributed;+DesignRules.dll|AttributesShouldHaveAccessorsForAllArguments;+DesignRules.dll|AvoidNamespacesWithFewMembers;-DesignRules.dll|AvoidOutParameters;+DesignRules.dll|AvoidValueTypesPassedAsByRefParameters;+DesignRules.dll|ConsiderHavingOnlyOneDimensionForIndexer;+DesignRules.dll|ConsiderPassingBaseTypesAsParameters;+DesignRules.dll|ConsiderReplacingMethodsWithProperties;+DesignRules.dll|ConsiderReplacingRepetitiveArgsWithParameterArray;+DesignRules.dll|DefaultParametersAreNotUsed;+DesignRules.dll|EnumerationsShouldBeFlagsAttributed;+DesignRules.dll|EnumerationsShouldBeInt32;+DesignRules.dll|EnumerationsShouldBeIntegralType;+DesignRules.dll|EventFirstParametersAreTypeObject;+DesignRules.dll|EventHandlersReturnVoid;+DesignRules.dll|EventSecondParametersAreEventArgsType;+DesignRules.dll|EventsHaveTwoParameters;+DesignRules.dll|EventsShouldBeUsed;+DesignRules.dll|ExceptionAndSystemExceptionTypesAreNotCaught;+DesignRules.dll|ExceptionsRequireMultipleConstructors;-DesignRules.dll|ExplicitMethodImplementationsInUnsealedClassesHaveVisibleAlternates;+DesignRules.dll|ExternallyVisibleNestedTypesShouldNotBeUsed;+DesignRules.dll|ICollectionImplementationsHaveStronglyTypedMembers;+DesignRules.dll|IComparableImplementationsOverrideEquals;+DesignRules.dll|IComparableImplementationsOverrideOperators;+DesignRules.dll|IEnumeratorImplementationsHaveStronglyTypedMembers;+DesignRules.dll|IListImplementationsHaveStronglyTypedMembers;+DesignRules.dll|InterfacesShouldNotBeEmpty;+DesignRules.dll|ISerializableTypesAreMarkedSerializable;+DesignRules.dll|ObsoleteAttributeOnMemberShouldProvideMessage;+DesignRules.dll|ObsoleteAttributeOnTypeShouldProvideMessage;-DesignRules.dll|OnlyIntegralValuesOrStringsShouldBeUsedForIndexers;+DesignRules.dll|PropertiesShouldNotBeWriteOnly;+DesignRules.dll|ReferenceTypesAreNotPassedAsByRefParameters;+DesignRules.dll|ReferenceTypesShouldNotOverrideOperatorEquals;+DesignRules.dll|SealedTypesDoNotDeclareProtectedMembers;+DesignRules.dll|SealedTypesDoNotDeclareVirtualMembers;+DesignRules.dll|TypesAllocatingUnmanagedResourcesImplementIDisposable;+DesignRules.dll|TypesBelongToNamespaces;+DesignRules.dll|TypesDoNotHavePublicInstanceFields;+DesignRules.dll|TypesHavingOnlyStaticMembersShouldBeSealed;+DesignRules.dll|TypesHavingOnlyStaticMembersShouldNotHaveConstructors;+DesignRules.dll|UriParametersShouldNotBeStrings;+DesignRules.dll|UriPropertiesShouldNotBeStrings;+DesignRules.dll|UriReturnValuesShouldNotBeStrings;+GlobalizationRules.dll;+MaintainabilityRules.dll;+NamingRules.dll;+PerformanceRules.dll;+ReliabilityRules.dll;+SecurityRules.dll;+UsageRules.dll</FxCopRules>\r
+    <RunFxCop>false</RunFxCop>\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
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Compile Include="arrays\CircularQueue.cs" />\r
+    <Compile Include="arrays\HashedArrayList.cs" />\r
+    <Compile Include="AssemblyInfo.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Attributes.cs" />\r
+    <Compile Include="Builtin.cs" />\r
+    <Compile Include="Comparer.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="Delegates.cs" />\r
+    <Compile Include="Enums.cs" />\r
+    <Compile Include="Exceptions.cs" />\r
+    <Compile Include="Formatting.cs" />\r
+    <Compile Include="Hashers.cs" />\r
+    <Compile Include="Events.cs" />\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="linkedlists\HashedLinkedList.cs" />\r
+    <Compile Include="Random.cs" />\r
+    <Compile Include="Records.cs" />\r
+    <Compile Include="Sorting.cs" />\r
+    <Compile Include="ViewSupport.cs" />\r
+    <Compile Include="MappedEnumerators.cs" />\r
+    <Compile Include="WrappedArray.cs" />\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\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\LinkedList.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="trees\RedBlackTreeSet.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="trees\RedBlackTreeBag.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+    <Compile Include="trees\RedBlackTreeDictionary.cs">\r
+      <SubType>Code</SubType>\r
+    </Compile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <AppDesigner Include="Properties\" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Folder Include="Properties\" />\r
+  </ItemGroup>\r
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />\r
+  <PropertyGroup>\r
+    <PreBuildEvent>"$(SolutionDir)PreProcess\$(OutDir)PreProcess.exe"</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/ClsdiagWork.png b/mcs/class/Mono.C5/C5/ClsdiagWork.png
new file mode 100644 (file)
index 0000000..9a18666
Binary files /dev/null and b/mcs/class/Mono.C5/C5/ClsdiagWork.png differ
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..98acf96
--- /dev/null
@@ -0,0 +1,1520 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 IMPROVED_COLLECTION_HASHFUNCTION\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// A base class for implementing an IEnumerable&lt;T&gt;\r
+  /// </summary>\r
+  [Serializable]\r
+  public abstract class EnumerableBase<T> : SCG.IEnumerable<T>\r
+  {\r
+    /// <summary>\r
+    /// Create an enumerator for this collection.\r
+    /// </summary>\r
+    /// <returns>The enumerator</returns>\r
+    public abstract SCG.IEnumerator<T> GetEnumerator();\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
+    [Tested]\r
+    protected static int countItems(SCG.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 (SCG.IEnumerator<T> e = items.GetEnumerator())\r
+        while (e.MoveNext()) count++;\r
+\r
+      return count;\r
+    }\r
+\r
+    #region IEnumerable Members\r
+\r
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
+    {\r
+      return GetEnumerator();\r
+    }\r
+\r
+    #endregion\r
+  }\r
+\r
+\r
+  /// <summary>\r
+  /// Base class for classes implementing ICollectionValue[T]\r
+  /// </summary>\r
+  [Serializable]\r
+  public abstract class CollectionValueBase<T> : EnumerableBase<T>, ICollectionValue<T>, IShowable\r
+  {\r
+    #region Event handling\r
+    EventBlock<T> eventBlock;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual EventTypeEnum ListenableEvents { get { return 0; } }\r
+\r
+    /// <summary>\r
+    /// A flag bitmap of the events currently subscribed to by this collection.\r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual EventTypeEnum ActiveEvents { get { return eventBlock == null ? 0 : eventBlock.events; } }\r
+\r
+    private void checkWillListen(EventTypeEnum eventType)\r
+    {\r
+      if ((ListenableEvents & eventType) == 0)\r
+        throw new UnlistenableEventException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// The change event. Will be raised for every change operation on the collection.\r
+    /// </summary>\r
+    public virtual event CollectionChangedHandler<T> CollectionChanged\r
+    {\r
+      add { checkWillListen(EventTypeEnum.Changed); (eventBlock ?? (eventBlock = new EventBlock<T>())).CollectionChanged += value; }\r
+      remove\r
+      {\r
+        checkWillListen(EventTypeEnum.Changed);\r
+        if (eventBlock != null)\r
+        {\r
+          eventBlock.CollectionChanged -= value;\r
+          if (eventBlock.events == 0) eventBlock = null;\r
+        }\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// Fire the CollectionChanged event\r
+    /// </summary>\r
+    protected virtual void raiseCollectionChanged()\r
+    { if (eventBlock != null) eventBlock.raiseCollectionChanged(this); }\r
+\r
+    /// <summary>\r
+    /// The clear event. Will be raised for every Clear operation on the collection.\r
+    /// </summary>\r
+    public virtual event CollectionClearedHandler<T> CollectionCleared\r
+    {\r
+      add { checkWillListen(EventTypeEnum.Cleared); (eventBlock ?? (eventBlock = new EventBlock<T>())).CollectionCleared += value; }\r
+      remove\r
+      {\r
+        checkWillListen(EventTypeEnum.Cleared);\r
+        if (eventBlock != null)\r
+        {\r
+          eventBlock.CollectionCleared -= value;\r
+          if (eventBlock.events == 0) eventBlock = null;\r
+        }\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// Fire the CollectionCleared event\r
+    /// </summary>\r
+    protected virtual void raiseCollectionCleared(bool full, int count)\r
+    { if (eventBlock != null) eventBlock.raiseCollectionCleared(this, full, count); }\r
+\r
+    /// <summary>\r
+    /// Fire the CollectionCleared event\r
+    /// </summary>\r
+    protected virtual void raiseCollectionCleared(bool full, int count, int? offset)\r
+    { if (eventBlock != null) eventBlock.raiseCollectionCleared(this, full, count, offset); }\r
+\r
+    /// <summary>\r
+    /// The item added  event. Will be raised for every individual addition to the collection.\r
+    /// </summary>\r
+    public virtual event ItemsAddedHandler<T> ItemsAdded\r
+    {\r
+      add { checkWillListen(EventTypeEnum.Added); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemsAdded += value; }\r
+      remove\r
+      {\r
+        checkWillListen(EventTypeEnum.Added);\r
+        if (eventBlock != null)\r
+        {\r
+          eventBlock.ItemsAdded -= value;\r
+          if (eventBlock.events == 0) eventBlock = null;\r
+        }\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// Fire the ItemsAdded event\r
+    /// </summary>\r
+    /// <param name="item">The item that was added</param>\r
+    /// <param name="count"></param>\r
+    protected virtual void raiseItemsAdded(T item, int count)\r
+    { if (eventBlock != null) eventBlock.raiseItemsAdded(this, item, count); }\r
+\r
+    /// <summary>\r
+    /// The item removed event. Will be raised for every individual removal from the collection.\r
+    /// </summary>\r
+    public virtual event ItemsRemovedHandler<T> ItemsRemoved\r
+    {\r
+      add { checkWillListen(EventTypeEnum.Removed); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemsRemoved += value; }\r
+      remove\r
+      {\r
+        checkWillListen(EventTypeEnum.Removed);\r
+        if (eventBlock != null)\r
+        {\r
+          eventBlock.ItemsRemoved -= value;\r
+          if (eventBlock.events == 0) eventBlock = null;\r
+        }\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// Fire the ItemsRemoved event\r
+    /// </summary>\r
+    /// <param name="item">The item that was removed</param>\r
+    /// <param name="count"></param>\r
+    protected virtual void raiseItemsRemoved(T item, int count)\r
+    { if (eventBlock != null) eventBlock.raiseItemsRemoved(this, item, count); }\r
+\r
+    /// <summary>\r
+    /// The item added  event. Will be raised for every individual addition to the collection.\r
+    /// </summary>\r
+    public virtual event ItemInsertedHandler<T> ItemInserted\r
+    {\r
+      add { checkWillListen(EventTypeEnum.Inserted); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemInserted += value; }\r
+      remove\r
+      {\r
+        checkWillListen(EventTypeEnum.Inserted);\r
+        if (eventBlock != null)\r
+        {\r
+          eventBlock.ItemInserted -= value;\r
+          if (eventBlock.events == 0) eventBlock = null;\r
+        }\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// Fire the ItemInserted event\r
+    /// </summary>\r
+    /// <param name="item">The item that was added</param>\r
+    /// <param name="index"></param>\r
+    protected virtual void raiseItemInserted(T item, int index)\r
+    { if (eventBlock != null) eventBlock.raiseItemInserted(this, item, index); }\r
+\r
+    /// <summary>\r
+    /// The item removed event. Will be raised for every individual removal from the collection.\r
+    /// </summary>\r
+    public virtual event ItemRemovedAtHandler<T> ItemRemovedAt\r
+    {\r
+      add { checkWillListen(EventTypeEnum.RemovedAt); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemRemovedAt += value; }\r
+      remove\r
+      {\r
+        checkWillListen(EventTypeEnum.RemovedAt);\r
+        if (eventBlock != null)\r
+        {\r
+          eventBlock.ItemRemovedAt -= value;\r
+          if (eventBlock.events == 0) eventBlock = null;\r
+        }\r
+      }\r
+    }\r
+    /// <summary> \r
+    /// Fire the ItemRemovedAt event\r
+    /// </summary>\r
+    /// <param name="item">The item that was removed</param>\r
+    /// <param name="index"></param>\r
+    protected virtual void raiseItemRemovedAt(T item, int index)\r
+    { if (eventBlock != null) eventBlock.raiseItemRemovedAt(this, item, index); }\r
+\r
+    #region Event support for IList\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="index"></param>\r
+    /// <param name="value"></param>\r
+    /// <param name="item"></param>\r
+    protected virtual void raiseForSetThis(int index, T value, T item)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsRemoved(item, 1);\r
+        raiseItemRemovedAt(item, index);\r
+        raiseItemsAdded(value, 1);\r
+        raiseItemInserted(value, index);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="i"></param>\r
+    /// <param name="item"></param>\r
+    protected virtual void raiseForInsert(int i, T item)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemInserted(item, i);\r
+        raiseItemsAdded(item, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    protected void raiseForRemove(T item)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsRemoved(item, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="count"></param>\r
+    protected void raiseForRemove(T item, int count)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsRemoved(item, count);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="index"></param>\r
+    /// <param name="item"></param>\r
+    protected void raiseForRemoveAt(int index, T item)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemRemovedAt(item, index);\r
+        raiseItemsRemoved(item, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region Event  Support for ICollection\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="newitem"></param>\r
+    /// <param name="olditem"></param>\r
+    protected virtual void raiseForUpdate(T newitem, T olditem)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsRemoved(olditem, 1);\r
+        raiseItemsAdded(newitem, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="newitem"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <param name="count"></param>\r
+    protected virtual void raiseForUpdate(T newitem, T olditem, int count)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsRemoved(olditem, count);\r
+        raiseItemsAdded(newitem, count);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    protected virtual void raiseForAdd(T item)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsAdded(item, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="wasRemoved"></param>\r
+    protected virtual void raiseForRemoveAll(ICollectionValue<T> wasRemoved)\r
+    {\r
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)\r
+        foreach (T item in wasRemoved)\r
+          raiseItemsRemoved(item, 1);\r
+      if (wasRemoved != null && wasRemoved.Count > 0)\r
+        raiseCollectionChanged();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    protected class RaiseForRemoveAllHandler\r
+    {\r
+      CollectionValueBase<T> collection;\r
+      CircularQueue<T> wasRemoved;\r
+      bool wasChanged = false;\r
+\r
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      /// <param name="collection"></param>\r
+      public RaiseForRemoveAllHandler(CollectionValueBase<T> collection)\r
+      {\r
+        this.collection = collection;\r
+        mustFireRemoved = (collection.ActiveEvents & EventTypeEnum.Removed) != 0;\r
+        MustFire = (collection.ActiveEvents & (EventTypeEnum.Removed | EventTypeEnum.Changed)) != 0;\r
+      }\r
+\r
+      bool mustFireRemoved;\r
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      public readonly bool MustFire;\r
+\r
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      /// <param name="item"></param>\r
+      public void Remove(T item)\r
+      {\r
+        if (mustFireRemoved)\r
+        {\r
+          if (wasRemoved == null)\r
+            wasRemoved = new CircularQueue<T>();\r
+          wasRemoved.Enqueue(item);\r
+        }\r
+        if (!wasChanged)\r
+          wasChanged = true;\r
+      }\r
+\r
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      public void Raise()\r
+      {\r
+        if (wasRemoved != null)\r
+          foreach (T item in wasRemoved)\r
+            collection.raiseItemsRemoved(item, 1);\r
+        if (wasChanged)\r
+          collection.raiseCollectionChanged();\r
+      }\r
+    }\r
+    #endregion\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// Check if collection is empty.\r
+    /// </summary>\r
+    /// <value>True if empty</value>\r
+    public abstract bool IsEmpty { get;}\r
+\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
+    /// <summary>\r
+    /// Copy the items of this collection to part of an array.\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if <code>index</code> \r
+    /// is not a valid index\r
+    /// into the array (i.e. negative or not less than the size of the array)\r
+    /// or the array does not have room for the items.</exception>\r
+    /// <param name="array">The array to copy to.</param>\r
+    /// <param name="index">The starting index.</param>\r
+    [Tested]\r
+    public virtual void CopyTo(T[] array, int index)\r
+    {\r
+#warning This code does not fit the doc comment and unit tests\r
+      if (index < 0 || index + Count > array.Length)\r
+        throw new ArgumentOutOfRangeException();\r
+\r
+      foreach (T item in this) array[index++] = 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 single argument action, <see cref="T:C5.Act`1"/> to this enumerable\r
+    /// </summary>\r
+    /// <param name="action">The action delegate</param>\r
+    [Tested]\r
+    public virtual void Apply(Act<T> action)\r
+    {\r
+      foreach (T item in this)\r
+        action(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="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R = bool</code>) \r
+    /// defining the predicate</param>\r
+    /// <returns>True if such an item exists</returns>\r
+    [Tested]\r
+    public virtual bool Exists(Fun<T, bool> predicate)\r
+    {\r
+      foreach (T item in this)\r
+        if (predicate(item))\r
+          return true;\r
+\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the first one in enumeration order.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <param name="item"></param>\r
+    /// <returns>True is such an item exists</returns>\r
+    public virtual bool Find(Fun<T, bool> predicate, out T item)\r
+    {\r
+      foreach (T jtem in this)\r
+        if (predicate(jtem))\r
+        {\r
+          item = jtem;\r
+          return true;\r
+        }\r
+      item = default(T);\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if all items in this collection satisfies a specific predicate.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R = bool</code>) \r
+    /// defining the predicate</param>\r
+    /// <returns>True if all items satisfies the predicate</returns>\r
+    [Tested]\r
+    public virtual bool All(Fun<T, bool> predicate)\r
+    {\r
+      foreach (T item in this)\r
+        if (!predicate(item))\r
+          return false;\r
+\r
+      return true;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create an enumerable, enumerating the items of this collection that satisfies \r
+    /// a certain condition.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R = bool</code>) \r
+    /// defining the predicate</param>\r
+    /// <returns>The filtered enumerable</returns>\r
+    public virtual SCG.IEnumerable<T> Filter(Fun<T, bool> predicate)\r
+    {\r
+      foreach (T item in this)\r
+        if (predicate(item))\r
+          yield return item;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Choose some item of this collection. \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    public abstract T Choose();\r
+\r
+\r
+    /// <summary>\r
+    /// Create an enumerator for this collection.\r
+    /// </summary>\r
+    /// <returns>The enumerator</returns>\r
+    public override abstract SCG.IEnumerator<T> GetEnumerator();\r
+\r
+    #region IShowable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowCollectionValue<T>(this, stringbuilder, ref rest, formatProvider);\r
+    }\r
+    #endregion\r
+\r
+    #region IFormattable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public virtual string ToString(string format, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowString(this, format, formatProvider);\r
+    }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return ToString(null, null);\r
+    }\r
+\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public abstract class DirectedCollectionValueBase<T> : CollectionValueBase<T>, IDirectedCollectionValue<T>\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
+    public virtual EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public abstract IDirectedCollectionValue<T> Backwards();\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return this.Backwards(); }\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the first one in enumeration order.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <param name="item"></param>\r
+    /// <returns>True is such an item exists</returns>\r
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item)\r
+    {\r
+      foreach (T jtem in Backwards())\r
+        if (predicate(jtem))\r
+        {\r
+          item = jtem;\r
+          return true;\r
+        }\r
+      item = default(T);\r
+      return false;\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// Base class (abstract) for ICollection implementations.\r
+  /// </summary>\r
+  [Serializable]\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 equalityComparer of the collection\r
+    /// </summary>\r
+    protected readonly SCG.IEqualityComparer<T> itemequalityComparer;\r
+\r
+    int iUnSequencedHashCode, iUnSequencedHashCodeStamp = -1;\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="itemequalityComparer"></param>\r
+    public CollectionBase(SCG.IEqualityComparer<T> itemequalityComparer)\r
+    {\r
+      if (itemequalityComparer == null)\r
+        throw new NullReferenceException("Item EqualityComparer cannot be null.");\r
+      this.itemequalityComparer = itemequalityComparer;\r
+    }\r
+\r
+    #region Util\r
+\r
+    /// <summary>\r
+    /// Utility method for range checking.\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative or\r
+    ///  if the range does not fit within collection size.</exception>\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 || start + count > size)\r
+        throw new ArgumentOutOfRangeException();\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="itemequalityComparer">The item equalityComparer</param>\r
+    /// <returns>The hash code</returns>\r
+    [Tested]\r
+    public static int ComputeHashCode(ICollectionValue<T> items, SCG.IEqualityComparer<T> itemequalityComparer)\r
+    {\r
+      int h = 0;\r
+\r
+#if IMPROVED_COLLECTION_HASHFUNCTION\r
+      //But still heuristic: \r
+      //Note: the three odd factors should really be random, \r
+      //but there will be a problem with serialization/deserialization!\r
+      //Two products is too few\r
+      foreach (T item in items)\r
+      {\r
+        uint h1 = (uint)itemequalityComparer.GetHashCode(item);\r
+\r
+        h += (int)((h1 * 1529784657 + 1) ^ (h1 * 2912831877) ^ (h1 * 1118771817 + 2));\r
+      }\r
+\r
+      return h;\r
+      /*\r
+            The pairs (-1657792980, -1570288808) and (1862883298, -272461342) gives the same\r
+            unsequenced hashcode with this hashfunction. The pair was found with code like\r
+\r
+            HashDictionary<int, int[]> set = new HashDictionary<int, int[]>();\r
+            Random rnd = new C5Random(12345);\r
+            while (true)\r
+            {\r
+                int[] a = new int[2];\r
+                a[0] = rnd.Next(); a[1] = rnd.Next();\r
+                int h = unsequencedhashcode(a);\r
+                int[] b = a;\r
+                if (set.FindOrAdd(h, ref b))\r
+                {\r
+                    Console.WriteLine("Code {5}, Pair ({1},{2}) number {0} matched other pair ({3},{4})", set.Count, a[0], a[1], b[0], b[1], h);\r
+                }\r
+            }\r
+            */\r
+#else\r
+            foreach (T item in items)\r
+                               h ^= itemequalityComparer.GetHashCode(item);\r
+\r
+                       return (items.Count << 16) + h;\r
+#endif\r
+    }\r
+\r
+    static Type isortedtype = typeof(ISorted<T>);\r
+\r
+    /// <summary>\r
+    /// Examine if tit and tat are equal as unsequenced collections\r
+    /// using the specified item equalityComparer (assumed compatible with the two collections).\r
+    /// </summary>\r
+    /// <param name="collection1">The first collection</param>\r
+    /// <param name="collection2">The second collection</param>\r
+    /// <param name="itemequalityComparer">The item equalityComparer to use for comparison</param>\r
+    /// <returns>True if equal</returns>\r
+    [Tested]\r
+    public static bool StaticEquals(ICollection<T> collection1, ICollection<T> collection2, SCG.IEqualityComparer<T> itemequalityComparer)\r
+    {\r
+      if (object.ReferenceEquals(collection1, collection2))\r
+        return true;\r
+\r
+      if (collection1.Count != collection2.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
+      //TODO: cehck equal equalityComparers, at least here!\r
+      if (collection1.GetUnsequencedHashCode() != collection2.GetUnsequencedHashCode())\r
+        return false;\r
+\r
+      //TODO: move this to the sorted implementation classes? \r
+      //Really depends on speed of IntanceOfType: we could save a cast\r
+      {\r
+        ISorted<T> stit, stat;\r
+        if ((stit = collection1 as ISorted<T>) != null && (stat = collection2 as ISorted<T>) != null && stit.Comparer == stat.Comparer)\r
+        {\r
+          using (SCG.IEnumerator<T> dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator())\r
+          {\r
+            while (dit.MoveNext())\r
+            {\r
+              dat.MoveNext();\r
+              if (!itemequalityComparer.Equals(dit.Current, dat.Current))\r
+                return false;\r
+            }\r
+            return true;\r
+          }\r
+        }\r
+      }\r
+\r
+      if (!collection1.AllowsDuplicates && (collection2.AllowsDuplicates || collection2.ContainsSpeed >= collection1.ContainsSpeed))\r
+      {\r
+        foreach (T x in collection1) if (!collection2.Contains(x)) return false;\r
+      }\r
+      else if (!collection2.AllowsDuplicates)\r
+      {\r
+        foreach (T x in collection2) if (!collection1.Contains(x)) return false;\r
+      }\r
+      // Now tit.AllowsDuplicates && tat.AllowsDuplicates\r
+      else if (collection1.DuplicatesByCounting && collection2.DuplicatesByCounting)\r
+      {\r
+        foreach (T item in collection2) if (collection1.ContainsCount(item) != collection2.ContainsCount(item)) return false;\r
+      }\r
+      else\r
+      {\r
+        //To avoid an O(n^2) algorithm, we make an aux hashtable to hold the count of items\r
+        HashDictionary<T, int> dict = new HashDictionary<T, int>();\r
+        foreach (T item in collection2)\r
+        {\r
+          int count = 1;\r
+          if (dict.FindOrAdd(item, ref count))\r
+            dict[item] = count + 1;\r
+        }\r
+        foreach (T item in collection1)\r
+        {\r
+          int count;\r
+          if (dict.Find(item, out count) && count > 0)\r
+            dict[item] = count - 1;\r
+          else\r
+            return false;\r
+        }\r
+        return true;\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
+    public virtual int GetUnsequencedHashCode()\r
+    {\r
+      if (iUnSequencedHashCodeStamp == stamp)\r
+        return iUnSequencedHashCode;\r
+\r
+      iUnSequencedHashCode = ComputeHashCode(this, itemequalityComparer);\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 equalityComparer of this collection. \r
+    /// Assuming that the item EqualityComparer is compatible with otherCollection!\r
+    /// </summary>\r
+    /// <param name="otherCollection">The collection to compare to.</param>\r
+    /// <returns>True if  equal</returns>\r
+    public virtual bool UnsequencedEquals(ICollection<T> otherCollection)\r
+    {\r
+      return otherCollection != null && StaticEquals((ICollection<T>)this, otherCollection, itemequalityComparer);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if the collection has been modified since a specified time, expressed as a stamp value.\r
+    /// </summary>\r
+    /// <exception cref="CollectionModifiedException"> if this collection has been updated \r
+    /// since a target time</exception>\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 CollectionModifiedException();\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if it is valid to perform update operations, and if so increment stamp.\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException">If colection is read-only</exception>\r
+    protected virtual void updatecheck()\r
+    {\r
+      if (isReadOnly)\r
+        throw new ReadOnlyCollectionException();\r
+\r
+      stamp++;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICollection<T> members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>True if this collection is read only</value>\r
+    [Tested]\r
+    public virtual bool IsReadOnly { [Tested]get { return isReadOnly; } }\r
+\r
+    #endregion\r
+\r
+    #region ICollectionValue<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 IExtensible<T> members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return itemequalityComparer; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>A distinguished object to use for locking to synchronize multithreaded access</value>\r
+    [Tested]\r
+    public virtual object SyncRoot { get { return syncroot; } }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>True if this collection is empty</value>\r
+    [Tested]\r
+    public override bool IsEmpty { [Tested]get { return size == 0; } }\r
+\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 SCG.IEnumerator<T> GetEnumerator();\r
+    #endregion\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  [Serializable]\r
+  public abstract class DirectedCollectionBase<T> : CollectionBase<T>, IDirectedCollectionValue<T>\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="itemequalityComparer"></param>\r
+    public DirectedCollectionBase(SCG.IEqualityComparer<T> itemequalityComparer) : base(itemequalityComparer) { }\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
+    public virtual EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public abstract IDirectedCollectionValue<T> Backwards();\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return this.Backwards(); }\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the first one in enumeration order.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <param name="item"></param>\r
+    /// <returns>True is such an item exists</returns>\r
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item)\r
+    {\r
+      foreach (T jtem in Backwards())\r
+        if (predicate(jtem))\r
+        {\r
+          item = jtem;\r
+          return true;\r
+        }\r
+      item = default(T);\r
+      return false;\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// Base class (abstract) for sequenced collection implementations.\r
+  /// </summary>\r
+  [Serializable]\r
+  public abstract class SequencedBase<T> : DirectedCollectionBase<T>, IDirectedCollectionValue<T>\r
+  {\r
+    #region Fields\r
+\r
+    int iSequencedHashCode, iSequencedHashCodeStamp = -1;\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="itemequalityComparer"></param>\r
+    public SequencedBase(SCG.IEqualityComparer<T> itemequalityComparer) : base(itemequalityComparer) { }\r
+\r
+    #region Util\r
+\r
+    //TODO: make random for release\r
+    const int HASHFACTOR = 31;\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="itemequalityComparer">The item equalityComparer</param>\r
+    /// <returns>The hash code</returns>\r
+    [Tested]\r
+    public static int ComputeHashCode(ISequenced<T> items, SCG.IEqualityComparer<T> itemequalityComparer)\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
+      //NBNBNB: the current hashcode has the very bad property that items with hashcode 0\r
+      // is ignored.\r
+      int iIndexedHashCode = 0;\r
+\r
+      foreach (T item in items)\r
+        iIndexedHashCode = iIndexedHashCode * HASHFACTOR + itemequalityComparer.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 equalityComparer (assumed compatible with the two collections).\r
+    /// </summary>\r
+    /// <param name="collection1">The first collection</param>\r
+    /// <param name="collection2">The second collection</param>\r
+    /// <param name="itemequalityComparer">The item equalityComparer to use for comparison</param>\r
+    /// <returns>True if equal</returns>\r
+    [Tested]\r
+    public static bool StaticEquals(ISequenced<T> collection1, ISequenced<T> collection2, SCG.IEqualityComparer<T> itemequalityComparer)\r
+    {\r
+      if (object.ReferenceEquals(collection1, collection2))\r
+        return true;\r
+\r
+      if (collection1.Count != collection2.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 (collection1.GetSequencedHashCode() != collection2.GetSequencedHashCode())\r
+        return false;\r
+\r
+      using (SCG.IEnumerator<T> dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator())\r
+      {\r
+        while (dit.MoveNext())\r
+        {\r
+          dat.MoveNext();\r
+          if (!itemequalityComparer.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
+    public virtual int GetSequencedHashCode()\r
+    {\r
+      if (iSequencedHashCodeStamp == stamp)\r
+        return iSequencedHashCode;\r
+\r
+      iSequencedHashCode = ComputeHashCode((ISequenced<T>)this, itemequalityComparer);\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 equalityComparer of this collection.\r
+    /// </summary>\r
+    /// <param name="otherCollection">The collection to compare to.</param>\r
+    /// <returns>True if  equal</returns>\r
+    public virtual bool SequencedEquals(ISequenced<T> otherCollection)\r
+    {\r
+      return StaticEquals((ISequenced<T>)this, otherCollection, itemequalityComparer);\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 SCG.IEnumerator<T> GetEnumerator();\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 override EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the index of the first one.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>the index, if found, a negative value else</returns>\r
+    public int FindIndex(Fun<T, bool> predicate)\r
+    {\r
+      int index = 0;\r
+      foreach (T item in this)\r
+      {\r
+        if (predicate(item))\r
+          return index;\r
+        index++;\r
+      }\r
+      return -1;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the index of the last one.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>the index, if found, a negative value else</returns>\r
+    public int FindLastIndex(Fun<T, bool> predicate)\r
+    {\r
+      int index = Count - 1;\r
+      foreach (T item in Backwards())\r
+      {\r
+        if (predicate(item))\r
+          return index;\r
+        index--;\r
+      }\r
+      return -1;\r
+    }\r
+\r
+  }\r
+\r
+\r
+  /// <summary>\r
+  /// Base class for collection classes of dynamic array type implementations.\r
+  /// </summary>\r
+  [Serializable]\r
+  public abstract 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="itemequalityComparer">The item equalityComparer to use, primarily for item equality</param>\r
+    public ArrayBase(int capacity, SCG.IEqualityComparer<T> itemequalityComparer)\r
+      : base(itemequalityComparer)\r
+    {\r
+      int newlength = 8;\r
+      while (newlength < capacity) newlength *= 2;\r
+      array = new T[newlength];\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IIndexed members\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException">If the arguments does not describe a \r
+    /// valid range in the indexed collection, cf. <see cref="M:C5.CollectionBase`1.checkRange(System.Int32,System.Int32)"/>.</exception>\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 virtual 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, offset, res, 0, 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 override IDirectedCollectionValue<T> Backwards() { return this[0, size].Backwards(); }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// Choose some item of this collection. The result is the last item in the internal array,\r
+    /// making it efficient to remove.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    public override T Choose() { if (size > 0) return array[size - 1]; throw new NoSuchItemException(); }\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 SCG.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 : DirectedCollectionValueBase<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
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>\r
+      /// <value>True if this collection is empty.</value>\r
+      public override bool IsEmpty { get { thebase.modifycheck(stamp); return count == 0; } }\r
+\r
+\r
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>\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
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>\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
+      /// Choose some item of this collection. \r
+      /// </summary>\r
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>\r
+      /// <exception cref="NoSuchItemException">if range is empty.</exception>\r
+      /// <returns></returns>\r
+      public override T Choose()\r
+      {\r
+        thebase.modifycheck(stamp);\r
+        if (count == 0)\r
+          throw new NoSuchItemException();\r
+        return thebase.array[start];\r
+      }\r
+\r
+\r
+      /// <summary>\r
+      /// Create an enumerator for this range of an array based collection.\r
+      /// </summary>\r
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>\r
+      /// <returns>The enumerator</returns>\r
+      [Tested]\r
+      public override SCG.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
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>\r
+      /// <returns>The mirrored collection.</returns>\r
+      [Tested]\r
+      public override 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
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>\r
+      /// <value>The enumeration direction relative to the original collection.</value>\r
+      [Tested]\r
+      public override 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
diff --git a/mcs/class/Mono.C5/C5/Comparer.cs b/mcs/class/Mono.C5/C5/Comparer.cs
new file mode 100644 (file)
index 0000000..784b015
--- /dev/null
@@ -0,0 +1,152 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+using SCG = System.Collections.Generic;\r
+\r
+namespace C5\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 static class Comparer<T>\r
+  {\r
+    readonly static Type naturalComparerO = typeof(NaturalComparerO<>);\r
+\r
+    readonly static Type naturalComparer = typeof(NaturalComparer<>);\r
+\r
+    static SCG.IComparer<T> cachedComparer = null;\r
+\r
+    /// <summary>\r
+    /// Create a default comparer. \r
+    /// <para>The IComparer[T] object is constructed when this class is initialised, i.e. \r
+    /// its static constructors called. Thus, the property will be the same object \r
+    /// for the duration of an invocation of the runtime, but a value serialized in \r
+    /// another invocation and deserialized here will not be the same object.</para>\r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">If T is not comparable</exception>\r
+    /// <value>The comparer</value>\r
+    [Tested]\r
+    public static SCG.IComparer<T> Default\r
+    {\r
+      get\r
+      {\r
+        if (cachedComparer != null)\r
+          return cachedComparer;\r
+\r
+        Type t = typeof(T);\r
+\r
+        if (t.IsValueType)\r
+        {\r
+          if (t.Equals(typeof(int)))\r
+            return cachedComparer = (SCG.IComparer<T>)(new IntComparer());\r
+\r
+          if (t.Equals(typeof(double)))\r
+            return cachedComparer = (SCG.IComparer<T>)(new DoubleComparer());\r
+\r
+          if (t.Equals(typeof(byte)))\r
+            return cachedComparer = (SCG.IComparer<T>)(new ByteComparer());\r
+        }\r
+\r
+        if (typeof(IComparable<T>).IsAssignableFrom(t))\r
+        {\r
+          Type c = naturalComparer.MakeGenericType(new Type[] { t });\r
+\r
+          return cachedComparer = (SCG.IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
+        }\r
+\r
+        if (t.GetInterface("System.IComparable") != null)\r
+        {\r
+          Type c = naturalComparerO.MakeGenericType(new Type[] { t });\r
+\r
+          return cachedComparer = (SCG.IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));\r
+        }\r
+\r
+        throw new NotComparableException(String.Format("Cannot make comparer for type {0}", t));\r
+      }\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// A natural generic IComparer for an IComparable&lt;T&gt; item type\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class NaturalComparer<T> : SCG.IComparer<T>\r
+      where T : IComparable<T>\r
+  {\r
+    /// <summary>\r
+    /// Compare two items\r
+    /// </summary>\r
+    /// <param name="item1">First item</param>\r
+    /// <param name="item2">Second item</param>\r
+    /// <returns>item1 &lt;=&gt; item2</returns>\r
+    [Tested]\r
+    public int Compare(T item1, T item2) { return item1 != null ? item1.CompareTo(item2) : item2 != null ? -1 : 0; }\r
+  }\r
+\r
+  /// <summary>\r
+  /// A natural generic IComparer for a System.IComparable item type\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class NaturalComparerO<T> : SCG.IComparer<T>\r
+      where T : System.IComparable\r
+  {\r
+    /// <summary>\r
+    /// Compare two items\r
+    /// </summary>\r
+    /// <param name="item1">First item</param>\r
+    /// <param name="item2">Second item</param>\r
+    /// <returns>item1 &lt;=&gt; item2</returns>\r
+    [Tested]\r
+    public int Compare(T item1, T item2) { return item1 != null ? item1.CompareTo(item2) : item2 != null ? -1 : 0; }\r
+  }\r
+\r
+  /// <summary>\r
+  /// A generic comparer for type T based on a Comparison[T] delegate\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class DelegateComparer<T> : SCG.IComparer<T>\r
+  {\r
+    readonly Comparison<T> cmp;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="comparison"></param>\r
+    public DelegateComparer(Comparison<T> comparison)\r
+    {\r
+      if (comparison == null)\r
+        throw new NullReferenceException("Comparison cannot be null");\r
+      this.cmp = comparison;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item1">First item</param>\r
+    /// <param name="item2">Second item</param>\r
+    /// <returns>item1 &lt;=&gt; item2</returns>\r
+    public int Compare(T item1, T item2) { return cmp(item1, item2); }\r
+  }\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Delegates.cs b/mcs/class/Mono.C5/C5/Delegates.cs
new file mode 100644 (file)
index 0000000..36792d8
--- /dev/null
@@ -0,0 +1,131 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+\r
+#pragma warning disable 1711\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  public delegate void Act();\r
+  /// <summary>\r
+  /// <para>\r
+  /// The type Act[T] corresponds to System.Action[T] in the .Net\r
+  /// Framework class library.\r
+  ///</para>\r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <param name="x1"></param>\r
+  public delegate void Act<A1>(A1 x1);\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <typeparam name="A2"></typeparam>\r
+  /// <param name="x1"></param>\r
+  /// <param name="x2"></param>\r
+  public delegate void Act<A1, A2>(A1 x1, A2 x2);\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <typeparam name="A2"></typeparam>\r
+  /// <typeparam name="A3"></typeparam>\r
+  /// <param name="x1"></param>\r
+  /// <param name="x2"></param>\r
+  /// <param name="x3"></param>\r
+  public delegate void Act<A1, A2, A3>(A1 x1, A2 x2, A3 x3);\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <typeparam name="A2"></typeparam>\r
+  /// <typeparam name="A3"></typeparam>\r
+  /// <typeparam name="A4"></typeparam>\r
+  /// <param name="x1"></param>\r
+  /// <param name="x2"></param>\r
+  /// <param name="x3"></param>\r
+  /// <param name="x4"></param>\r
+  public delegate void Act<A1, A2, A3, A4>(A1 x1, A2 x2, A3 x3, A4 x4);\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="R"></typeparam>\r
+  /// <returns></returns>\r
+  public delegate R Fun<R>();\r
+  /// <summary>\r
+  /// Delegate type Fun[A1,R] is the type of functions (methods) from A1\r
+  /// to R, used to compute some transformation for a given collection\r
+  /// item. \r
+  /// <para>\r
+  /// The type Fun[T,U] corresponds to System.Converter[T,U] in the .Net\r
+  /// Framework class library, and the type Fun[T,bool] corresponds\r
+  /// System.Predicate[T] in the .Net Framework class library.</para>\r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <typeparam name="R"></typeparam>\r
+  /// <param name="x1"></param>\r
+  /// <returns></returns>\r
+  public delegate R Fun<A1, R>(A1 x1);\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <typeparam name="A2"></typeparam>\r
+  /// <typeparam name="R"></typeparam>\r
+  /// <param name="x1"></param>\r
+  /// <param name="x2"></param>\r
+  /// <returns></returns>\r
+  public delegate R Fun<A1, A2, R>(A1 x1, A2 x2);\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <typeparam name="A2"></typeparam>\r
+  /// <typeparam name="A3"></typeparam>\r
+  /// <typeparam name="R"></typeparam>\r
+  /// <param name="x1"></param>\r
+  /// <param name="x2"></param>\r
+  /// <param name="x3"></param>\r
+  /// <returns></returns>\r
+  public delegate R Fun<A1, A2, A3, R>(A1 x1, A2 x2, A3 x3);\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="A1"></typeparam>\r
+  /// <typeparam name="A2"></typeparam>\r
+  /// <typeparam name="A3"></typeparam>\r
+  /// <typeparam name="A4"></typeparam>\r
+  /// <typeparam name="R"></typeparam>\r
+  /// <param name="x1"></param>\r
+  /// <param name="x2"></param>\r
+  /// <param name="x3"></param>\r
+  /// <param name="x4"></param>\r
+  /// <returns></returns>\r
+  public delegate R Fun<A1, A2, A3, A4, R>(A1 x1, A2 x2, A3 x3, A4 x4);\r
+}\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..4370461
--- /dev/null
@@ -0,0 +1,1295 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// An entry in a dictionary from K to V.\r
+  /// </summary>\r
+  [Serializable]\r
+  public struct KeyValuePair<K, V> : IEquatable<KeyValuePair<K, V>>, IShowable\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
+    /// <summary>\r
+    /// Create an entry with specified key and value\r
+    /// </summary>\r
+    /// <param name="key">The key</param>\r
+    /// <param name="value">The value</param>\r
+    public KeyValuePair(K key, V value) { Key = key; Value = value; }\r
+\r
+\r
+    /// <summary>\r
+    /// Create an entry with a specified key. The value will be the default value of type <code>V</code>.\r
+    /// </summary>\r
+    /// <param name="key">The key</param>\r
+    public KeyValuePair(K key) { Key = key; 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 and value</returns>\r
+    [Tested]\r
+    public override bool Equals(object obj)\r
+    {\r
+      if (!(obj is KeyValuePair<K, V>))\r
+        return false;\r
+      KeyValuePair<K, V> other = (KeyValuePair<K, V>)obj;\r
+      return Equals(other);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the hash code of the pair.\r
+    /// </summary>\r
+    /// <returns>The hash code</returns>\r
+    [Tested]\r
+    public override int GetHashCode() { return EqualityComparer<K>.Default.GetHashCode(Key) + 13984681 * EqualityComparer<V>.Default.GetHashCode(Value); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="other"></param>\r
+    /// <returns></returns>\r
+    public bool Equals(KeyValuePair<K, V> other)\r
+    {\r
+      return EqualityComparer<K>.Default.Equals(Key, other.Key) && EqualityComparer<V>.Default.Equals(Value, other.Value);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="pair1"></param>\r
+    /// <param name="pair2"></param>\r
+    /// <returns></returns>\r
+    public static bool operator ==(KeyValuePair<K, V> pair1, KeyValuePair<K, V> pair2) { return pair1.Equals(pair2); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="pair1"></param>\r
+    /// <param name="pair2"></param>\r
+    /// <returns></returns>\r
+    public static bool operator !=(KeyValuePair<K, V> pair1, KeyValuePair<K, V> pair2) { return !pair1.Equals(pair2); }\r
+\r
+    #region IShowable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <param name="rest"></param>\r
+    /// <returns></returns>\r
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      if (rest < 0)\r
+        return false;\r
+      if (!Showing.Show(Key, stringbuilder, ref rest, formatProvider))\r
+        return false;\r
+      stringbuilder.Append(" => ");\r
+      rest -= 4;\r
+      if (!Showing.Show(Value, stringbuilder, ref rest, formatProvider))\r
+        return false;\r
+      return rest >= 0;\r
+    }\r
+    #endregion\r
+\r
+    #region IFormattable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public string ToString(string format, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowString(this, format, formatProvider);\r
+    }\r
+\r
+    #endregion\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// Default comparer for dictionary entries in a sorted dictionary.\r
+  /// Entry comparisons only look at keys and uses an externally defined comparer for that.\r
+  /// </summary>\r
+  [Serializable]\r
+  public class KeyValuePairComparer<K, V> : SCG.IComparer<KeyValuePair<K, V>>\r
+  {\r
+    SCG.IComparer<K> comparer;\r
+\r
+\r
+    /// <summary>\r
+    /// Create an entry comparer for a item comparer of the keys\r
+    /// </summary>\r
+    /// <param name="comparer">Comparer of keys</param>\r
+    public KeyValuePairComparer(SCG.IComparer<K> comparer)\r
+    {\r
+      if (comparer == null)\r
+        throw new NullReferenceException();\r
+      this.comparer = comparer;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Compare two entries\r
+    /// </summary>\r
+    /// <param name="entry1">First entry</param>\r
+    /// <param name="entry2">Second entry</param>\r
+    /// <returns>The result of comparing the keys</returns>\r
+    [Tested]\r
+    public int Compare(KeyValuePair<K, V> entry1, KeyValuePair<K, V> entry2)\r
+    { return comparer.Compare(entry1.Key, entry2.Key); }\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// Default equalityComparer for dictionary entries.\r
+  /// Operations only look at keys and uses an externaly defined equalityComparer for that.\r
+  /// </summary>\r
+  [Serializable]\r
+  public sealed class KeyValuePairEqualityComparer<K, V> : SCG.IEqualityComparer<KeyValuePair<K, V>>\r
+  {\r
+    SCG.IEqualityComparer<K> keyequalityComparer;\r
+\r
+\r
+    /// <summary>\r
+    /// Create an entry equalityComparer using the default equalityComparer for keys\r
+    /// </summary>\r
+    public KeyValuePairEqualityComparer() { keyequalityComparer = EqualityComparer<K>.Default; }\r
+\r
+\r
+    /// <summary>\r
+    /// Create an entry equalityComparer from a specified item equalityComparer for the keys\r
+    /// </summary>\r
+    /// <param name="keyequalityComparer">The key equalityComparer</param>\r
+    public KeyValuePairEqualityComparer(SCG.IEqualityComparer<K> keyequalityComparer)\r
+    {\r
+      if (keyequalityComparer == null)\r
+        throw new NullReferenceException("Key equality comparer cannot be null");\r
+      this.keyequalityComparer = keyequalityComparer;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the hash code of the entry\r
+    /// </summary>\r
+    /// <param name="entry">The entry</param>\r
+    /// <returns>The hash code of the key</returns>\r
+    [Tested]\r
+    public int GetHashCode(KeyValuePair<K, V> entry) { return keyequalityComparer.GetHashCode(entry.Key); }\r
+\r
+\r
+    /// <summary>\r
+    /// Test two entries for equality\r
+    /// </summary>\r
+    /// <param name="entry1">First entry</param>\r
+    /// <param name="entry2">Second entry</param>\r
+    /// <returns>True if keys are equal</returns>\r
+    [Tested]\r
+    public bool Equals(KeyValuePair<K, V> entry1, KeyValuePair<K, V> entry2)\r
+    { return keyequalityComparer.Equals(entry1.Key, entry2.Key); }\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A base class for implementing a dictionary based on a set collection implementation.\r
+  /// <i>See the source code for <see cref="T:C5.HashDictionary`2"/> for an example</i>\r
+  /// \r
+  /// </summary>\r
+  [Serializable]\r
+  public abstract class DictionaryBase<K, V> : CollectionValueBase<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
+    SCG.IEqualityComparer<K> keyequalityComparer;\r
+\r
+    #region Events\r
+    ProxyEventBlock<KeyValuePair<K, V>> eventBlock;\r
+\r
+    /// <summary>\r
+    /// The change event. Will be raised for every change operation on the collection.\r
+    /// </summary>\r
+    public override event CollectionChangedHandler<KeyValuePair<K, V>> CollectionChanged\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).CollectionChanged += value; }\r
+      remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The change event. Will be raised for every change operation on the collection.\r
+    /// </summary>\r
+    public override event CollectionClearedHandler<KeyValuePair<K, V>> CollectionCleared\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).CollectionCleared += value; }\r
+      remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The item added  event. Will be raised for every individual addition to the collection.\r
+    /// </summary>\r
+    public override event ItemsAddedHandler<KeyValuePair<K, V>> ItemsAdded\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).ItemsAdded += value; }\r
+      remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The item added  event. Will be raised for every individual removal from the collection.\r
+    /// </summary>\r
+    public override event ItemsRemovedHandler<KeyValuePair<K, V>> ItemsRemoved\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).ItemsRemoved += value; }\r
+      remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public override EventTypeEnum ListenableEvents\r
+    {\r
+      get\r
+      {\r
+        return EventTypeEnum.Basic;\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public override EventTypeEnum ActiveEvents\r
+    {\r
+      get\r
+      {\r
+        return pairs.ActiveEvents;\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="keyequalityComparer"></param>\r
+    public DictionaryBase(SCG.IEqualityComparer<K> keyequalityComparer) {\r
+      if (keyequalityComparer == null)\r
+        throw new NullReferenceException("Key equality comparer cannot be null");\r
+      this.keyequalityComparer = keyequalityComparer; }\r
+\r
+    #region IDictionary<K,V> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual SCG.IEqualityComparer<K> EqualityComparer { get { return keyequalityComparer; } }\r
+\r
+\r
+    /// <summary>\r
+    /// Add a new (key, value) pair (a mapping) to the dictionary.\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException"> if there already is an entry with the same key. </exception>\r
+    /// <param name="key">Key to add</param>\r
+    /// <param name="value">Value to add</param>\r
+    [Tested]\r
+    public virtual void Add(K key, V value)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);\r
+\r
+      if (!pairs.Add(p))\r
+        throw new DuplicateNotAllowedException("Key being added: '" + key + "'");\r
+    }\r
+\r
+    /// <summary>\r
+    /// Add the entries from a collection of <see cref="T:C5.KeyValuePair`2"/> pairs to this dictionary.\r
+    /// <para><b>TODO: add restrictions L:K and W:V when the .Net SDK allows it </b></para>\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException"> \r
+    /// If the input contains duplicate keys or a key already present in this dictionary.</exception>\r
+    /// <param name="entries"></param>\r
+    public virtual void AddAll<L,W>(SCG.IEnumerable<KeyValuePair<L, W>> entries)\r
+        where L : K\r
+        where W : V\r
+    {\r
+      foreach (KeyValuePair<L, W> pair in entries)\r
+      {\r
+        KeyValuePair<K, V> p = new KeyValuePair<K, V>(pair.Key, pair.Value);\r
+        if (!pairs.Add(p))\r
+          throw new DuplicateNotAllowedException("Key being added: '" + pair.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 virtual 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="value">On exit, the value of the removed entry</param>\r
+    /// <returns>True if an entry was found (and removed)</returns>\r
+    [Tested]\r
+    public virtual bool Remove(K key, out V value)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);\r
+\r
+      if (pairs.Remove(p, out p))\r
+      {\r
+        value = p.Value;\r
+        return true;\r
+      }\r
+      else\r
+      {\r
+        value = default(V);\r
+        return false;\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove all entries from the dictionary\r
+    /// </summary>\r
+    [Tested]\r
+    public virtual void Clear() { pairs.Clear(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual Speed ContainsSpeed { get { return pairs.ContainsSpeed; } }\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 virtual bool Contains(K key)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);\r
+\r
+      return pairs.Contains(p);\r
+    }\r
+\r
+      class LiftedEnumerable<H> : SCG.IEnumerable<KeyValuePair<K, V>> where H : K\r
+      {\r
+          SCG.IEnumerable<H> keys;\r
+          public LiftedEnumerable(SCG.IEnumerable<H> keys) { this.keys = keys; }\r
+          public SCG.IEnumerator<KeyValuePair<K, V>> GetEnumerator() { foreach (H key in keys) yield return new KeyValuePair<K, V>(key); }\r
+\r
+          #region IEnumerable Members\r
+\r
+          System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
+          {\r
+              throw new Exception("The method or operation is not implemented.");\r
+          }\r
+\r
+          #endregion\r
+      }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="keys"></param>\r
+    /// <returns></returns>\r
+      public virtual bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K\r
+      {\r
+          return pairs.ContainsAll(new LiftedEnumerable<H>(keys));\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="value">On exit, the value of the entry</param>\r
+    /// <returns>True if key was found</returns>\r
+    [Tested]\r
+    public virtual bool Find(K key, out V value)\r
+    {\r
+      return Find(ref key, out value);\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="value">On exit, the value of the entry</param>\r
+    /// <returns>True if key was found</returns>\r
+    public virtual bool Find(ref K key, out V value)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);\r
+\r
+      if (pairs.Find(ref p))\r
+      {\r
+        key = p.Key;\r
+        value = p.Value;\r
+        return true;\r
+      }\r
+      else\r
+      {\r
+        value = 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="value">The new value</param>\r
+    /// <returns>True if key was found</returns>\r
+    [Tested]\r
+    public virtual bool Update(K key, V value)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);\r
+\r
+      return pairs.Update(p);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="key"></param>\r
+    /// <param name="value"></param>\r
+    /// <param name="oldvalue"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Update(K key, V value, out V oldvalue)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);\r
+\r
+      bool retval = pairs.Update(p, out p);\r
+      oldvalue = p.Value;\r
+      return retval;\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">On entry the key to look for</param>\r
+    /// <param name="value">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 virtual bool FindOrAdd(K key, ref V value)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);\r
+\r
+      if (!pairs.FindOrAdd(ref p))\r
+        return false;\r
+      else\r
+      {\r
+        value = p.Value;\r
+        //key = p.key;\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="value">The value to add or replace with.</param>\r
+    /// <returns>True if entry was updated.</returns>\r
+    [Tested]\r
+    public virtual bool UpdateOrAdd(K key, V value)\r
+    {\r
+      return pairs.UpdateOrAdd(new KeyValuePair<K, V>(key, value));\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 and the old value if any.\r
+    /// </summary>\r
+    /// <param name="key"></param>\r
+    /// <param name="value"></param>\r
+    /// <param name="oldvalue"></param>\r
+    /// <returns></returns>\r
+    public virtual bool UpdateOrAdd(K key, V value, out V oldvalue)\r
+    {\r
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);\r
+      bool retval = pairs.UpdateOrAdd(p, out p);\r
+      oldvalue = p.Value;\r
+      return retval;\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
+      public override V Choose() { return pairs.Choose().Value; }\r
+\r
+      [Tested]\r
+      public override SCG.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
+      public override bool IsEmpty { get { return pairs.IsEmpty; } }\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
+      public override K Choose() { return pairs.Choose().Key; }\r
+\r
+      [Tested]\r
+      public override SCG.IEnumerator<K> GetEnumerator()\r
+      {\r
+        foreach (KeyValuePair<K, V> p in pairs)\r
+          yield return p.Key;\r
+      }\r
+\r
+      public override bool IsEmpty { get { return pairs.IsEmpty; } }\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 virtual 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 virtual ICollectionValue<V> Values { [Tested]get { return new ValuesCollection(pairs); } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public virtual Fun<K, V> Fun { get { return delegate(K k) { return this[k]; }; } }\r
+\r
+    /// <summary>\r
+    /// Indexer by key for dictionary. \r
+    /// <para>The get method will throw an exception if no entry is found. </para>\r
+    /// <para>The set method behaves like <see cref="M:C5.DictionaryBase`2.UpdateOrAdd(`0,`1)"/>.</para>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> On get if no entry is found. </exception>\r
+    /// <value>The value corresponding to the key</value>\r
+    [Tested]\r
+    public virtual 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 NoSuchItemException("Key '" + key.ToString() + "' 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 virtual bool IsReadOnly { [Tested]get { return pairs.IsReadOnly; } }\r
+\r
+\r
+    /// <summary>\r
+    /// Check the integrity of the internal data structures of this dictionary.\r
+    /// </summary>\r
+    /// <returns>True if check does not fail.</returns>\r
+    [Tested]\r
+    public virtual bool Check() { return pairs.Check(); }\r
+\r
+    #endregion\r
+\r
+    #region ICollectionValue<KeyValuePair<K,V>> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>True if this collection is empty.</value>\r
+    public override bool IsEmpty { get { return pairs.IsEmpty; } }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The number of entrues in the dictionary</value>\r
+    [Tested]\r
+    public override int Count { [Tested]get { return pairs.Count; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The number of entrues in the dictionary</value>\r
+    [Tested]\r
+    public override Speed CountSpeed { [Tested]get { return pairs.CountSpeed; } }\r
+\r
+    /// <summary>\r
+    /// Choose some entry in this Dictionary. \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    public override KeyValuePair<K, V> Choose() { return pairs.Choose(); }\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 SCG.IEnumerator<KeyValuePair<K, V>> GetEnumerator()\r
+    {\r
+      return pairs.GetEnumerator(); ;\r
+    }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowDictionary<K, V>(this, stringbuilder, ref rest, formatProvider);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public abstract object Clone();\r
+\r
+  }\r
+\r
+  /// <summary>\r
+  /// A base class for implementing a sorted dictionary based on a sorted set collection implementation.\r
+  /// <i>See the source code for <see cref="T:C5.TreeDictionary`2"/> for an example</i>\r
+  /// \r
+  /// </summary>\r
+  public abstract class SortedDictionaryBase<K, V> : DictionaryBase<K, V>, ISortedDictionary<K, V>\r
+  {\r
+    #region Fields\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    protected ISorted<KeyValuePair<K, V>> sortedpairs;\r
+    SCG.IComparer<K> keycomparer;\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="keycomparer"></param>\r
+    /// <param name="keyequalityComparer"></param>\r
+    public SortedDictionaryBase(SCG.IComparer<K> keycomparer, SCG.IEqualityComparer<K> keyequalityComparer) : base(keyequalityComparer) { this.keycomparer = keycomparer; }\r
+\r
+    #endregion\r
+\r
+    #region ISortedDictionary<K,V> Members\r
+\r
+    /// <summary>\r
+    /// The key comparer used by this dictionary.\r
+    /// </summary>\r
+    /// <value></value>\r
+    public SCG.IComparer<K> Comparer { get { return keycomparer; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public new ISorted<K> Keys { get { return new SortedKeysCollection(this, sortedpairs, keycomparer, EqualityComparer); } }\r
+\r
+    /// <summary>\r
+    /// Get the entry in the dictionary whose key is the\r
+    /// predecessor of a specified key.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"></exception>\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
+    /// <exception cref="NoSuchItemException"></exception>\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
+    /// <exception cref="NoSuchItemException"></exception>\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
+    /// <exception cref="NoSuchItemException"></exception>\r
+    /// <param name="key">The key</param>\r
+    /// <returns>The entry</returns>\r
+    [Tested]\r
+    public KeyValuePair<K, V> WeakSuccessor(K key)\r
+    {\r
+      return sortedpairs.WeakSuccessor(new KeyValuePair<K, V>(key));\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ISortedDictionary<K,V> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> FindMin()\r
+    {\r
+      return sortedpairs.FindMin();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> DeleteMin()\r
+    {\r
+      return sortedpairs.DeleteMin();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> FindMax()\r
+    {\r
+      return sortedpairs.FindMax();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> DeleteMax()\r
+    {\r
+      return sortedpairs.DeleteMax();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="cutter"></param>\r
+    /// <param name="lowEntry"></param>\r
+    /// <param name="lowIsValid"></param>\r
+    /// <param name="highEntry"></param>\r
+    /// <param name="highIsValid"></param>\r
+    /// <returns></returns>\r
+    public bool Cut(IComparable<K> cutter, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)\r
+    {\r
+      return sortedpairs.Cut(new KeyValuePairComparable(cutter), out lowEntry, out lowIsValid, out highEntry, out highIsValid);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)\r
+    {\r
+      return sortedpairs.RangeFrom(new KeyValuePair<K, V>(bot));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)\r
+    {\r
+      return sortedpairs.RangeFromTo(new KeyValuePair<K, V>(bot), new KeyValuePair<K, V>(top));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)\r
+    {\r
+      return sortedpairs.RangeTo(new KeyValuePair<K, V>(top));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()\r
+    {\r
+      return sortedpairs.RangeAll();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="items"></param>\r
+    public void AddSorted(SCG.IEnumerable<KeyValuePair<K, V>> items)\r
+    {\r
+      sortedpairs.AddSorted(items);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="lowKey"></param>\r
+    public void RemoveRangeFrom(K lowKey)\r
+    {\r
+      sortedpairs.RemoveRangeFrom(new KeyValuePair<K, V>(lowKey));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="lowKey"></param>\r
+    /// <param name="highKey"></param>\r
+    public void RemoveRangeFromTo(K lowKey, K highKey)\r
+    {\r
+      sortedpairs.RemoveRangeFromTo(new KeyValuePair<K, V>(lowKey), new KeyValuePair<K, V>(highKey));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="highKey"></param>\r
+    public void RemoveRangeTo(K highKey)\r
+    {\r
+      sortedpairs.RemoveRangeTo(new KeyValuePair<K, V>(highKey));\r
+    }\r
+\r
+    #endregion\r
+\r
+    class KeyValuePairComparable : IComparable<KeyValuePair<K, V>>\r
+    {\r
+      IComparable<K> cutter;\r
+\r
+      internal KeyValuePairComparable(IComparable<K> cutter) { this.cutter = cutter; }\r
+\r
+      public int CompareTo(KeyValuePair<K, V> other) { return cutter.CompareTo(other.Key); }\r
+\r
+      public bool Equals(KeyValuePair<K, V> other) { return cutter.Equals(other.Key); }\r
+    }\r
+\r
+    class ProjectedDirectedEnumerable : MappedDirectedEnumerable<KeyValuePair<K, V>, K>\r
+    {\r
+      public ProjectedDirectedEnumerable(IDirectedEnumerable<KeyValuePair<K, V>> directedpairs) : base(directedpairs) { }\r
+\r
+      public override K Map(KeyValuePair<K, V> pair) { return pair.Key; }\r
+\r
+    }\r
+\r
+    class ProjectedDirectedCollectionValue : MappedDirectedCollectionValue<KeyValuePair<K, V>, K>\r
+    {\r
+      public ProjectedDirectedCollectionValue(IDirectedCollectionValue<KeyValuePair<K, V>> directedpairs) : base(directedpairs) { }\r
+\r
+      public override K Map(KeyValuePair<K, V> pair) { return pair.Key; }\r
+\r
+    }\r
+\r
+    class SortedKeysCollection : SequencedBase<K>, ISorted<K>\r
+    {\r
+      ISortedDictionary<K, V> sorteddict;\r
+      //TODO: eliminate this. Only problem is the Find method because we lack method on dictionary that also \r
+      //      returns the actual key.\r
+      ISorted<KeyValuePair<K, V>> sortedpairs;\r
+      SCG.IComparer<K> comparer;\r
+\r
+      internal SortedKeysCollection(ISortedDictionary<K, V> sorteddict, ISorted<KeyValuePair<K, V>> sortedpairs, SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> itemequalityComparer) \r
+        :base(itemequalityComparer)\r
+      {\r
+        this.sorteddict = sorteddict;\r
+        this.sortedpairs = sortedpairs;\r
+        this.comparer = comparer;\r
+      }\r
+\r
+      public override K Choose() { return sorteddict.Choose().Key; }\r
+\r
+      public override SCG.IEnumerator<K> GetEnumerator()\r
+      {\r
+        foreach (KeyValuePair<K, V> p in sorteddict)\r
+          yield return p.Key;\r
+      }\r
+\r
+      public override bool IsEmpty { get { return sorteddict.IsEmpty; } }\r
+\r
+      public override int Count { [Tested]get { return sorteddict.Count; } }\r
+\r
+      public override Speed CountSpeed { get { return sorteddict.CountSpeed; } }\r
+\r
+      #region ISorted<K> Members\r
+\r
+      public K FindMin() { return sorteddict.FindMin().Key; }\r
+\r
+      public K DeleteMin() { throw new ReadOnlyCollectionException(); }\r
+\r
+      public K FindMax() { return sorteddict.FindMax().Key; }\r
+\r
+      public K DeleteMax() { throw new ReadOnlyCollectionException(); }\r
+\r
+      public SCG.IComparer<K> Comparer { get { return comparer; } }\r
+\r
+      public K Predecessor(K item) { return sorteddict.Predecessor(item).Key; }\r
+\r
+      public K Successor(K item) { return sorteddict.Successor(item).Key; }\r
+\r
+      public K WeakPredecessor(K item) { return sorteddict.WeakPredecessor(item).Key; }\r
+\r
+      public K WeakSuccessor(K item) { return sorteddict.WeakSuccessor(item).Key; }\r
+\r
+      public bool Cut(IComparable<K> c, out K low, out bool lowIsValid, out K high, out bool highIsValid)\r
+      {\r
+        KeyValuePair<K, V> lowpair, highpair;\r
+        bool retval = sorteddict.Cut(c, out lowpair, out lowIsValid, out highpair, out highIsValid);\r
+        low = lowpair.Key;\r
+        high = highpair.Key;\r
+        return retval;\r
+      }\r
+\r
+      public IDirectedEnumerable<K> RangeFrom(K bot)\r
+      {\r
+        return new ProjectedDirectedEnumerable(sorteddict.RangeFrom(bot));\r
+      }\r
+\r
+      public IDirectedEnumerable<K> RangeFromTo(K bot, K top)\r
+      {\r
+        return new ProjectedDirectedEnumerable(sorteddict.RangeFromTo(bot, top));\r
+      }\r
+\r
+      public IDirectedEnumerable<K> RangeTo(K top)\r
+      {\r
+        return new ProjectedDirectedEnumerable(sorteddict.RangeTo(top));\r
+      }\r
+\r
+      public IDirectedCollectionValue<K> RangeAll()\r
+      {\r
+        return new ProjectedDirectedCollectionValue(sorteddict.RangeAll());\r
+      }\r
+\r
+      public void AddSorted<U>(SCG.IEnumerable<U> items) where U : K { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void RemoveRangeFrom(K low) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void RemoveRangeFromTo(K low, K hi) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void RemoveRangeTo(K hi) { throw new ReadOnlyCollectionException(); }\r
+      #endregion\r
+\r
+      #region ICollection<K> Members\r
+      public Speed ContainsSpeed { get { return sorteddict.ContainsSpeed; } }\r
+\r
+      public bool Contains(K key) { return sorteddict.Contains(key); ;      }\r
+\r
+      public int ContainsCount(K item) { return sorteddict.Contains(item) ? 1 : 0; }\r
+\r
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      /// <returns></returns>\r
+      public virtual ICollectionValue<K> UniqueItems()\r
+      {\r
+        return this;\r
+      }\r
+\r
+      /// <summary>\r
+      /// \r
+      /// </summary>\r
+      /// <returns></returns>\r
+      public virtual ICollectionValue<KeyValuePair<K, int>> ItemMultiplicities()\r
+      {\r
+        return new MultiplicityOne<K>(this);\r
+      }\r
+\r
+\r
+      public bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : K\r
+      {\r
+        //TODO: optimize?\r
+        foreach (K item in items)\r
+          if (!sorteddict.Contains(item))\r
+            return false;\r
+        return true;\r
+      }\r
+\r
+      public bool Find(ref K item)\r
+      {\r
+        KeyValuePair<K, V> p = new KeyValuePair<K, V>(item);\r
+        bool retval = sortedpairs.Find(ref p);\r
+        item = p.Key;\r
+        return retval;\r
+      }\r
+\r
+      public bool FindOrAdd(ref K item) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public bool Update(K item) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public bool Update(K item, out K olditem) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public bool UpdateOrAdd(K item) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public bool UpdateOrAdd(K item, out K olditem) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public bool Remove(K item) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public bool Remove(K item, out K removeditem) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void RemoveAllCopies(K item) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void RemoveAll<U> (SCG.IEnumerable<U> items)  where U : K { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void Clear() { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void RetainAll<U>(SCG.IEnumerable<U> items) where U : K { throw new ReadOnlyCollectionException(); }\r
+\r
+      #endregion\r
+\r
+      #region IExtensible<K> Members\r
+      public override bool IsReadOnly { get { return true; } }\r
+\r
+      public bool AllowsDuplicates { get { return false; } }\r
+\r
+      public bool DuplicatesByCounting { get { return true; } }\r
+\r
+      public bool Add(K item) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void AddAll(System.Collections.Generic.IEnumerable<K> items) { throw new ReadOnlyCollectionException(); }\r
+\r
+      public void AddAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : K { throw new ReadOnlyCollectionException(); }\r
+\r
+      public bool Check() { return sorteddict.Check(); }\r
+\r
+      #endregion\r
+\r
+      #region IDirectedCollectionValue<K> Members\r
+\r
+      public override IDirectedCollectionValue<K> Backwards()\r
+      {\r
+        return RangeAll().Backwards();\r
+      }\r
+\r
+      #endregion\r
+\r
+      #region IDirectedEnumerable<K> Members\r
+\r
+      IDirectedEnumerable<K> IDirectedEnumerable<K>.Backwards() { return Backwards(); }\r
+      #endregion\r
+\r
+      #region ICloneable Members\r
+\r
+      //TODO: test\r
+      /// <summary>\r
+      /// Make a shallow copy of this SortedKeysCollection.\r
+      /// </summary>\r
+      /// <returns></returns>\r
+      public virtual object Clone()\r
+      {\r
+        //\r
+        SortedArrayDictionary<K, V> dictclone = new SortedArrayDictionary<K, V>(sortedpairs.Count, comparer, EqualityComparer);\r
+        SortedArray<KeyValuePair<K, V>> sortedpairsclone = (SortedArray<KeyValuePair<K, V>>)(dictclone.sortedpairs);\r
+        foreach (K key in sorteddict.Keys)\r
+        {\r
+          sortedpairsclone.Add(new KeyValuePair<K, V>(key, default(V)));\r
+        }\r
+        return new SortedKeysCollection(dictclone, sortedpairsclone, comparer, EqualityComparer);\r
+      }\r
+\r
+      #endregion\r
+\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowDictionary<K, V>(this, stringbuilder, ref rest, formatProvider);\r
+    }\r
+\r
+  }\r
+\r
+  class SortedArrayDictionary<K, V> : SortedDictionaryBase<K, V>, IDictionary<K, V>, ISortedDictionary<K, V>\r
+  {\r
+    #region Constructors\r
+\r
+    public SortedArrayDictionary() : this(Comparer<K>.Default, EqualityComparer<K>.Default) { }\r
+\r
+    /// <summary>\r
+    /// Create a red-black tree dictionary using an external comparer for keys.\r
+    /// </summary>\r
+    /// <param name="comparer">The external comparer</param>\r
+    public SortedArrayDictionary(SCG.IComparer<K> comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer<K>(comparer)) { }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="comparer"></param>\r
+    /// <param name="equalityComparer"></param>\r
+    public SortedArrayDictionary(SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> equalityComparer) : base(comparer,equalityComparer)\r
+    {\r
+      pairs = sortedpairs = new SortedArray<KeyValuePair<K, V>>(new KeyValuePairComparer<K, V>(comparer));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="comparer"></param>\r
+    /// <param name="equalityComparer"></param>\r
+    /// <param name="capacity"></param>\r
+    public SortedArrayDictionary(int capacity, SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> equalityComparer) : base(comparer,equalityComparer)\r
+    {\r
+      pairs = sortedpairs = new SortedArray<KeyValuePair<K, V>>(capacity, new KeyValuePairComparer<K, V>(comparer));\r
+    }\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override object Clone()\r
+    {\r
+      SortedArrayDictionary<K, V> clone = new SortedArrayDictionary<K, V>(Comparer, EqualityComparer);\r
+      clone.sortedpairs.AddSorted(sortedpairs);\r
+      return clone;\r
+    }\r
+\r
+  }\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Enums.cs b/mcs/class/Mono.C5/C5/Enums.cs
new file mode 100644 (file)
index 0000000..a92301d
--- /dev/null
@@ -0,0 +1,98 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+namespace C5\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
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  public enum ItemEqualityTypeEnum\r
+  {\r
+    /// <summary>\r
+    /// Only an Equals(T,T)\r
+    /// </summary>\r
+    Equator, \r
+    /// <summary>\r
+    /// Equals(T,T) and GetHashCode(T)\r
+    /// </summary>\r
+    HashingEqualityComparer, \r
+    /// <summary>\r
+    /// Compare(T,T)\r
+    /// </summary>\r
+    Comparer, \r
+    /// <summary>\r
+    /// Compatible Compare(T,T) and GetHashCode(T)\r
+    /// </summary>\r
+    Both\r
+  }\r
+*/\r
+\r
+  /// <summary>\r
+  /// Direction of enumeration order relative to original collection.\r
+  /// </summary>\r
+  public enum EnumerationDirection\r
+  {\r
+    /// <summary>\r
+    /// Same direction\r
+    /// </summary>\r
+    Forwards,\r
+    /// <summary>\r
+    /// Opposite direction\r
+    /// </summary>\r
+    Backwards\r
+  }\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Events.cs b/mcs/class/Mono.C5/C5/Events.cs
new file mode 100644 (file)
index 0000000..4a5d8d7
--- /dev/null
@@ -0,0 +1,532 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  [Flags]\r
+  public enum EventTypeEnum\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    None = 0x00000000,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    Changed = 0x00000001,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    Cleared = 0x00000002,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    Added = 0x00000004,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    Removed = 0x00000008,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    Basic = 0x0000000f,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    Inserted = 0x00000010,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    RemovedAt = 0x00000020,\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    All = 0x0000003f\r
+  }\r
+\r
+  /// <summary>\r
+  /// Holds the real events for a collection\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  [Serializable]\r
+  internal sealed class EventBlock<T>\r
+  {\r
+    internal EventTypeEnum events;\r
+\r
+    event CollectionChangedHandler<T> collectionChanged;\r
+    internal event CollectionChangedHandler<T> CollectionChanged\r
+    {\r
+      add\r
+      {\r
+        collectionChanged += value;\r
+        events |= EventTypeEnum.Changed;\r
+      }\r
+      remove\r
+      {\r
+        collectionChanged -= value;\r
+        if (collectionChanged == null)\r
+          events &= ~EventTypeEnum.Changed;\r
+      }\r
+    }\r
+    internal void raiseCollectionChanged(object sender)\r
+    { if (collectionChanged != null) collectionChanged(sender); }\r
+\r
+    event CollectionClearedHandler<T> collectionCleared;\r
+    internal event CollectionClearedHandler<T> CollectionCleared\r
+    {\r
+      add\r
+      {\r
+        collectionCleared += value;\r
+        events |= EventTypeEnum.Cleared;\r
+      }\r
+      remove\r
+      {\r
+        collectionCleared -= value;\r
+        if (collectionCleared == null)\r
+          events &= ~EventTypeEnum.Cleared;\r
+      }\r
+    }\r
+    internal void raiseCollectionCleared(object sender, bool full, int count)\r
+    { if (collectionCleared != null) collectionCleared(sender, new ClearedEventArgs(full, count)); }\r
+    internal void raiseCollectionCleared(object sender, bool full, int count, int? start)\r
+    { if (collectionCleared != null) collectionCleared(sender, new ClearedRangeEventArgs(full, count, start)); }\r
+\r
+    event ItemsAddedHandler<T> itemsAdded;\r
+    internal event ItemsAddedHandler<T> ItemsAdded\r
+    {\r
+      add\r
+      {\r
+        itemsAdded += value;\r
+        events |= EventTypeEnum.Added;\r
+      }\r
+      remove\r
+      {\r
+        itemsAdded -= value;\r
+        if (itemsAdded == null)\r
+          events &= ~EventTypeEnum.Added;\r
+      }\r
+    }\r
+    internal void raiseItemsAdded(object sender, T item, int count)\r
+    { if (itemsAdded != null) itemsAdded(sender, new ItemCountEventArgs<T>(item, count)); }\r
+\r
+    event ItemsRemovedHandler<T> itemsRemoved;\r
+    internal event ItemsRemovedHandler<T> ItemsRemoved\r
+    {\r
+      add\r
+      {\r
+        itemsRemoved += value;\r
+        events |= EventTypeEnum.Removed;\r
+      }\r
+      remove\r
+      {\r
+        itemsRemoved -= value;\r
+        if (itemsRemoved == null)\r
+          events &= ~EventTypeEnum.Removed;\r
+      }\r
+    }\r
+    internal void raiseItemsRemoved(object sender, T item, int count)\r
+    { if (itemsRemoved != null) itemsRemoved(sender, new ItemCountEventArgs<T>(item, count)); }\r
+\r
+    event ItemInsertedHandler<T> itemInserted;\r
+    internal event ItemInsertedHandler<T> ItemInserted\r
+    {\r
+      add\r
+      {\r
+        itemInserted += value;\r
+        events |= EventTypeEnum.Inserted;\r
+      }\r
+      remove\r
+      {\r
+        itemInserted -= value;\r
+        if (itemInserted == null)\r
+          events &= ~EventTypeEnum.Inserted;\r
+      }\r
+    }\r
+    internal void raiseItemInserted(object sender, T item, int index)\r
+    { if (itemInserted != null) itemInserted(sender, new ItemAtEventArgs<T>(item, index)); }\r
+\r
+    event ItemRemovedAtHandler<T> itemRemovedAt;\r
+    internal event ItemRemovedAtHandler<T> ItemRemovedAt\r
+    {\r
+      add\r
+      {\r
+        itemRemovedAt += value;\r
+        events |= EventTypeEnum.RemovedAt;\r
+      }\r
+      remove\r
+      {\r
+        itemRemovedAt -= value;\r
+        if (itemRemovedAt == null)\r
+          events &= ~EventTypeEnum.RemovedAt;\r
+      }\r
+    }\r
+    internal void raiseItemRemovedAt(object sender, T item, int index)\r
+    { if (itemRemovedAt != null) itemRemovedAt(sender, new ItemAtEventArgs<T>(item, index)); }\r
+  }\r
+\r
+  /// <summary>\r
+  /// Tentative, to conserve memory in GuardedCollectionValueBase\r
+  /// This should really be nested in Guarded collection value, only have a guardereal field\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  [Serializable]\r
+  internal sealed class ProxyEventBlock<T>\r
+  {\r
+    ICollectionValue<T> proxy, real;\r
+\r
+    internal ProxyEventBlock(ICollectionValue<T> proxy, ICollectionValue<T> real)\r
+    { this.proxy = proxy; this.real = real; }\r
+\r
+    event CollectionChangedHandler<T> collectionChanged;\r
+    CollectionChangedHandler<T> collectionChangedProxy;\r
+    internal event CollectionChangedHandler<T> CollectionChanged\r
+    {\r
+      add\r
+      {\r
+        if (collectionChanged == null)\r
+        {\r
+          if (collectionChangedProxy == null)\r
+            collectionChangedProxy = delegate(object sender) { collectionChanged(proxy); };\r
+          real.CollectionChanged += collectionChangedProxy;\r
+        }\r
+        collectionChanged += value;\r
+      }\r
+      remove\r
+      {\r
+        collectionChanged -= value;\r
+        if (collectionChanged == null)\r
+          real.CollectionChanged -= collectionChangedProxy;\r
+      }\r
+    }\r
+\r
+    event CollectionClearedHandler<T> collectionCleared;\r
+    CollectionClearedHandler<T> collectionClearedProxy;\r
+    internal event CollectionClearedHandler<T> CollectionCleared\r
+    {\r
+      add\r
+      {\r
+        if (collectionCleared == null)\r
+        {\r
+          if (collectionClearedProxy == null)\r
+            collectionClearedProxy = delegate(object sender, ClearedEventArgs e) { collectionCleared(proxy, e); };\r
+          real.CollectionCleared += collectionClearedProxy;\r
+        }\r
+        collectionCleared += value;\r
+      }\r
+      remove\r
+      {\r
+        collectionCleared -= value;\r
+        if (collectionCleared == null)\r
+          real.CollectionCleared -= collectionClearedProxy;\r
+      }\r
+    }\r
+\r
+    event ItemsAddedHandler<T> itemsAdded;\r
+    ItemsAddedHandler<T> itemsAddedProxy;\r
+    internal event ItemsAddedHandler<T> ItemsAdded\r
+    {\r
+      add\r
+      {\r
+        if (itemsAdded == null)\r
+        {\r
+          if (itemsAddedProxy == null)\r
+            itemsAddedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsAdded(proxy, e); };\r
+          real.ItemsAdded += itemsAddedProxy;\r
+        }\r
+        itemsAdded += value;\r
+      }\r
+      remove\r
+      {\r
+        itemsAdded -= value;\r
+        if (itemsAdded == null)\r
+          real.ItemsAdded -= itemsAddedProxy;\r
+      }\r
+    }\r
+\r
+    event ItemInsertedHandler<T> itemInserted;\r
+    ItemInsertedHandler<T> itemInsertedProxy;\r
+    internal event ItemInsertedHandler<T> ItemInserted\r
+    {\r
+      add\r
+      {\r
+        if (itemInserted == null)\r
+        {\r
+          if (itemInsertedProxy == null)\r
+            itemInsertedProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemInserted(proxy, e); };\r
+          real.ItemInserted += itemInsertedProxy;\r
+        }\r
+        itemInserted += value;\r
+      }\r
+      remove\r
+      {\r
+        itemInserted -= value;\r
+        if (itemInserted == null)\r
+          real.ItemInserted -= itemInsertedProxy;\r
+      }\r
+    }\r
+\r
+    event ItemsRemovedHandler<T> itemsRemoved;\r
+    ItemsRemovedHandler<T> itemsRemovedProxy;\r
+    internal event ItemsRemovedHandler<T> ItemsRemoved\r
+    {\r
+      add\r
+      {\r
+        if (itemsRemoved == null)\r
+        {\r
+          if (itemsRemovedProxy == null)\r
+            itemsRemovedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsRemoved(proxy, e); };\r
+          real.ItemsRemoved += itemsRemovedProxy;\r
+        }\r
+        itemsRemoved += value;\r
+      }\r
+      remove\r
+      {\r
+        itemsRemoved -= value;\r
+        if (itemsRemoved == null)\r
+          real.ItemsRemoved -= itemsRemovedProxy;\r
+      }\r
+    }\r
+\r
+    event ItemRemovedAtHandler<T> itemRemovedAt;\r
+    ItemRemovedAtHandler<T> itemRemovedAtProxy;\r
+    internal event ItemRemovedAtHandler<T> ItemRemovedAt\r
+    {\r
+      add\r
+      {\r
+        if (itemRemovedAt == null)\r
+        {\r
+          if (itemRemovedAtProxy == null)\r
+            itemRemovedAtProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemRemovedAt(proxy, e); };\r
+          real.ItemRemovedAt += itemRemovedAtProxy;\r
+        }\r
+        itemRemovedAt += value;\r
+      }\r
+      remove\r
+      {\r
+        itemRemovedAt -= value;\r
+        if (itemRemovedAt == null)\r
+          real.ItemRemovedAt -= itemRemovedAtProxy;\r
+      }\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class ItemAtEventArgs<T> : EventArgs\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T Item;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly int Index;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="index"></param>\r
+    public ItemAtEventArgs(T item, int index) { Item = item; Index = index; }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return String.Format("(ItemAtEventArgs {0} '{1}')", Index, Item);\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class ItemCountEventArgs<T> : EventArgs\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T Item;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly int Count;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="count"></param>\r
+    /// <param name="item"></param>\r
+    public ItemCountEventArgs(T item, int count) { Item = item; Count = count; }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return String.Format("(ItemCountEventArgs {0} '{1}')", Count, Item);\r
+    }\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  public class ClearedEventArgs : EventArgs\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly bool Full;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly int Count;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// \r
+    /// <param name="full">True if the operation cleared all of the collection</param>\r
+    /// <param name="count">The number of items removed by the clear.</param>\r
+    public ClearedEventArgs(bool full, int count) { Full = full; Count = count; }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return String.Format("(ClearedEventArgs {0} {1})", Count, Full);\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  public class ClearedRangeEventArgs : ClearedEventArgs\r
+  {\r
+    //WE could let this be of type int? to  allow \r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly int? Start;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="full"></param>\r
+    /// <param name="count"></param>\r
+    /// <param name="start"></param>\r
+    public ClearedRangeEventArgs(bool full, int count, int? start) : base(full,count) { Start = start; }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return String.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start);\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// The type of event raised after an operation on a collection has changed its contents.\r
+  /// Normally, a multioperation like AddAll, \r
+  /// <see cref="M:C5.IExtensible`1.AddAll(System.Collections.Generic.IEnumerable{`0})"/> \r
+  /// will only fire one CollectionChanged event. Any operation that changes the collection\r
+  /// must fire CollectionChanged as its last event.\r
+  /// </summary>\r
+  public delegate void CollectionChangedHandler<T>(object sender);\r
+\r
+  /// <summary>\r
+  /// The type of event raised after the Clear() operation on a collection.\r
+  /// <para/>\r
+  /// Note: The Clear() operation will not fire ItemsRemoved events. \r
+  /// </summary>\r
+  /// <param name="sender"></param>\r
+  /// <param name="eventArgs"></param>\r
+  public delegate void CollectionClearedHandler<T>(object sender, ClearedEventArgs eventArgs);\r
+\r
+  /// <summary>\r
+  /// The type of event raised after an item has been added to a collection.\r
+  /// The event will be raised at a point of time, where the collection object is \r
+  /// in an internally consistent state and before the corresponding CollectionChanged \r
+  /// event is raised.\r
+  /// <para/>\r
+  /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.\r
+  /// <para/>\r
+  /// Note: When an item is inserted into a list (<see cref="T:C5.IList`1"/>), both\r
+  /// ItemInserted and ItemsAdded events will be fired.\r
+  /// </summary>\r
+  /// <param name="sender"></param>\r
+  /// <param name="eventArgs">An object with the item that was added</param>\r
+  public delegate void ItemsAddedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);\r
+\r
+  /// <summary>\r
+  /// The type of event raised after an item has been removed from a collection.\r
+  /// The event will be raised at a point of time, where the collection object is \r
+  /// in an internally consistent state and before the corresponding CollectionChanged \r
+  /// event is raised.\r
+  /// <para/>\r
+  /// Note: The Clear() operation will not fire ItemsRemoved events. \r
+  /// <para/>\r
+  /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.\r
+  /// <para/>\r
+  /// Note: When an item is removed from a list by the RemoveAt operation, both an \r
+  /// ItemsRemoved and an ItemRemovedAt event will be fired.\r
+  /// </summary>\r
+  /// <param name="sender"></param>\r
+  /// <param name="eventArgs">An object with the item that was removed</param>\r
+  public delegate void ItemsRemovedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);\r
+\r
+  /// <summary>\r
+  /// The type of event raised after an item has been inserted into a list by an Insert, \r
+  /// InsertFirst or InsertLast operation.\r
+  /// The event will be raised at a point of time, where the collection object is \r
+  /// in an internally consistent state and before the corresponding CollectionChanged \r
+  /// event is raised.\r
+  /// <para/>\r
+  /// Note: an ItemsAdded event will also be fired.\r
+  /// </summary>\r
+  /// <param name="sender"></param>\r
+  /// <param name="eventArgs"></param>\r
+  public delegate void ItemInsertedHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);\r
+\r
+  /// <summary>\r
+  /// The type of event raised after an item has been removed from a list by a RemoveAt(int i)\r
+  /// operation (or RemoveFirst(), RemoveLast(), Remove() operation).\r
+  /// The event will be raised at a point of time, where the collection object is \r
+  /// in an internally consistent state and before the corresponding CollectionChanged \r
+  /// event is raised.\r
+  /// <para/>\r
+  /// Note: an ItemRemoved event will also be fired.\r
+  /// </summary>\r
+  /// <param name="sender"></param>\r
+  /// <param name="eventArgs"></param>\r
+  public delegate void ItemRemovedAtHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Exceptions.cs b/mcs/class/Mono.C5/C5/Exceptions.cs
new file mode 100644 (file)
index 0000000..2480b22
--- /dev/null
@@ -0,0 +1,244 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// An exception to throw from library code when an internal inconsistency is encountered.\r
+  /// </summary>\r
+  public class InternalException : Exception\r
+  {\r
+    internal InternalException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An exception thrown by an update operation on a Read-Only collection or dictionary.\r
+  /// <para>This exception will be thrown unconditionally when an update operation \r
+  /// (method or set property) is called. No check is made to see if the update operation, \r
+  /// if allowed, would actually change the collection. </para>\r
+  /// </summary>\r
+  [Serializable]\r
+  public class ReadOnlyCollectionException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public ReadOnlyCollectionException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public ReadOnlyCollectionException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  [Serializable]\r
+  public class FixedSizeCollectionException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public FixedSizeCollectionException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public FixedSizeCollectionException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  [Serializable]\r
+  public class UnlistenableEventException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public UnlistenableEventException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public UnlistenableEventException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An exception thrown by enumerators, range views etc. when accessed after \r
+  /// the underlying collection has been modified.\r
+  /// </summary>\r
+  [Serializable]\r
+  public class CollectionModifiedException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public CollectionModifiedException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public CollectionModifiedException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An excption thrown when trying to access a view (a list view on a <see cref="T:C5.IList`1"/> or \r
+  /// a snapshot on a <see cref="T:C5.IPersistentSorted`1"/>)\r
+  /// that has been invalidated by some earlier operation.\r
+  /// <para>\r
+  /// The typical scenario is a view on a list that hash been invalidated by a call to \r
+  /// Sort, Reverse or Shuffle on some other, overlapping view or the whole list.\r
+  /// </para>\r
+  /// </summary>\r
+  [Serializable]\r
+  public class ViewDisposedException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public ViewDisposedException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public ViewDisposedException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An exception thrown by a lookup or lookup with update operation that does not \r
+  /// find the lookup item and has no other means to communicate failure.\r
+  /// <para>The typical scenario is a lookup by key in a dictionary with an indexer,\r
+  /// see e.g. <see cref="P:C5.IDictionary`2.Item(`0)"/></para>\r
+  /// </summary>\r
+  [Serializable]\r
+  public class NoSuchItemException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public NoSuchItemException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public NoSuchItemException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An exception thrown by an operation on a list (<see cref="T:C5.IList`1"/>)\r
+  /// that only makes sense for a view, not for an underlying list.\r
+  /// </summary>\r
+  [Serializable]\r
+  public class NotAViewException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public NotAViewException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public NotAViewException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An exception thrown when an operation attempts to create a duplicate in a collection with set semantics \r
+  /// (<see cref="P:C5.IExtensible`1.AllowsDuplicates"/> is false) or attempts to create a duplicate key in a dictionary.\r
+  /// <para>With collections this can only happen with Insert operations on lists, since the Add operations will\r
+  /// not try to create duplictes and either ignore the failure or report it in a bool return value.\r
+  /// </para>\r
+  /// <para>With dictionaries this can happen with the <see cref="M:C5.IDictionary`2.Add(`0,`1)"/> metod.</para>\r
+  /// </summary>\r
+  [Serializable]\r
+  public class DuplicateNotAllowedException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public DuplicateNotAllowedException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public DuplicateNotAllowedException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  [Serializable]\r
+  public class InvalidPriorityQueueHandleException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public InvalidPriorityQueueHandleException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public InvalidPriorityQueueHandleException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An exception thrown by an operation that need to construct a natural\r
+  /// comparer for a type.\r
+  /// </summary>\r
+  [Serializable]\r
+  public class NotComparableException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public NotComparableException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public NotComparableException(string message) : base(message) { }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An exception thrown by operations on a list that expects an argument\r
+  /// that is a view on the same underlying list.\r
+  /// </summary>\r
+  [Serializable]\r
+  public class IncompatibleViewException : Exception\r
+  {\r
+    /// <summary>\r
+    /// Create a simple exception with no further explanation.\r
+    /// </summary>\r
+    public IncompatibleViewException() : base() { }\r
+    /// <summary>\r
+    /// Create the exception with an explanation of the reason.\r
+    /// </summary>\r
+    /// <param name="message"></param>\r
+    public IncompatibleViewException(string message) : base(message) { }\r
+  }\r
+\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Formatting.cs b/mcs/class/Mono.C5/C5/Formatting.cs
new file mode 100644 (file)
index 0000000..5d4a144
--- /dev/null
@@ -0,0 +1,247 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+using System.Text;\r
+\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// <i>(Describe usage of "L:300" format string.)</i>\r
+  /// </summary>\r
+  public interface IShowable : IFormattable\r
+  {\r
+    //TODO: wonder if we should use TextWriters instead of StringBuilders?\r
+    /// <summary>\r
+    /// Format <code>this</code> using at most approximately <code>rest</code> chars and \r
+    /// append the result, possibly truncated, to stringbuilder.\r
+    /// Subtract the actual number of used chars from <code>rest</code>.\r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns>True if the appended formatted string was complete (not truncated).</returns>\r
+    bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider);\r
+  }\r
+  // ------------------------------------------------------------\r
+\r
+  // Static helper methods for Showing collections \r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  public static class Showing\r
+  {\r
+    /// <summary>\r
+    /// Show  <code>Object obj</code> by appending it to <code>stringbuilder</code>\r
+    /// </summary>\r
+    /// <param name="obj"></param>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns>True if <code>obj</code> was shown completely.</returns>\r
+    public static bool Show(Object obj, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      if (rest <= 0)\r
+        return false;\r
+      else if (obj is IShowable)\r
+        return ((IShowable)obj).Show(stringbuilder, ref rest, formatProvider);\r
+      int oldLength = stringbuilder.Length;\r
+      stringbuilder.AppendFormat(formatProvider, "{0}", obj);\r
+      rest -= (stringbuilder.Length - oldLength);\r
+      return true;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="showable"></param>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public static String ShowString(IShowable showable, String format, IFormatProvider formatProvider)\r
+    {\r
+      int rest = maxLength(format);\r
+      StringBuilder sb = new StringBuilder();\r
+      showable.Show(sb, ref rest, formatProvider);\r
+      return sb.ToString();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <returns></returns>\r
+    static int maxLength(String format)\r
+    {\r
+      //TODO: validate format string\r
+      if (format == null)\r
+        return 80;\r
+      if (format.Length > 1 && format.StartsWith("L"))\r
+      {\r
+        return int.Parse(format.Substring(1));\r
+      }\r
+      else\r
+        return int.MaxValue;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="T"></typeparam>\r
+    /// <param name="items"></param>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns>True if collection was shown completely</returns>\r
+    public static bool ShowCollectionValue<T>(ICollectionValue<T> items, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      string startdelim = "{ ", enddelim = " }";\r
+      bool showIndexes = false;\r
+      bool showMultiplicities = false;\r
+      //TODO: do not test here at run time, but select code at compile time\r
+      //      perhaps by delivering the print type to this metod\r
+      if (items is IList<T>)\r
+      {\r
+        startdelim = "[ ";\r
+        enddelim = " ]";\r
+        //TODO: should have been (items as IIndexed<T>).IndexingSpeed\r
+        showIndexes = (items as IList<T>).IndexingSpeed == Speed.Constant;\r
+      }\r
+      else if (items is ICollection<T>)\r
+      {\r
+        ICollection<T> coll = items as ICollection<T>;\r
+        if (coll.AllowsDuplicates)\r
+        {\r
+          startdelim = "{{ ";\r
+          enddelim = " }}";\r
+          if (coll.DuplicatesByCounting)\r
+            showMultiplicities = true;\r
+        }\r
+      }\r
+\r
+      stringbuilder.Append(startdelim);\r
+      rest -= 2 * startdelim.Length;\r
+      bool first = true;\r
+      bool complete = true;\r
+      int index = 0;\r
+\r
+      if (showMultiplicities)\r
+      {\r
+        foreach (KeyValuePair<T, int> p in (items as ICollection<T>).ItemMultiplicities())\r
+        {\r
+          complete = false;\r
+          if (rest <= 0)\r
+            break;\r
+          if (first)\r
+            first = false;\r
+          else\r
+          {\r
+            stringbuilder.Append(", ");\r
+            rest -= 2;\r
+          }\r
+          if (complete = Showing.Show(p.Key, stringbuilder, ref rest, formatProvider))\r
+          {\r
+            string multiplicityString = string.Format("(*{0})", p.Value);\r
+            stringbuilder.Append(multiplicityString);\r
+            rest -= multiplicityString.Length;\r
+          }\r
+        }\r
+      }\r
+      else\r
+      {\r
+        foreach (T x in items)\r
+        {\r
+          complete = false;\r
+          if (rest <= 0)\r
+            break;\r
+          if (first)\r
+            first = false;\r
+          else\r
+          {\r
+            stringbuilder.Append(", ");\r
+            rest -= 2;\r
+          }\r
+          if (showIndexes)\r
+          {\r
+            string indexString = string.Format("{0}:", index++);\r
+            stringbuilder.Append(indexString);\r
+            rest -= indexString.Length;\r
+          }\r
+          complete = Showing.Show(x, stringbuilder, ref rest, formatProvider);\r
+        }\r
+      }\r
+      if (!complete)\r
+      {\r
+        stringbuilder.Append("...");\r
+        rest -= 3;\r
+      }\r
+      stringbuilder.Append(enddelim);\r
+      return complete;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="K"></typeparam>\r
+    /// <typeparam name="V"></typeparam>\r
+    /// \r
+    /// <param name="dictionary"></param>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <param name="rest"></param>\r
+    /// <returns></returns>\r
+    public static bool ShowDictionary<K, V>(IDictionary<K, V> dictionary, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      bool sorted = dictionary is ISortedDictionary<K, V>;\r
+      stringbuilder.Append(sorted ? "[ " : "{ ");\r
+      rest -= 4;                                  // Account for "( " and " )"\r
+      bool first = true;\r
+      bool complete = true;\r
+\r
+      foreach (KeyValuePair<K, V> p in dictionary)\r
+      {\r
+        complete = false;\r
+        if (rest <= 0)\r
+          break;\r
+        if (first)\r
+          first = false;\r
+        else\r
+        {\r
+          stringbuilder.Append(", ");\r
+          rest -= 2;\r
+        }\r
+        complete = Showing.Show(p, stringbuilder, ref rest, formatProvider);\r
+      }\r
+      if (!complete)\r
+      {\r
+        stringbuilder.Append("...");\r
+        rest -= 3;\r
+      }\r
+      stringbuilder.Append(sorted ? " ]" : " }");\r
+      return complete;\r
+    }\r
+  }\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Hashers.cs b/mcs/class/Mono.C5/C5/Hashers.cs
new file mode 100644 (file)
index 0000000..70778c5
--- /dev/null
@@ -0,0 +1,489 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+using SCG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// Utility class for building default generic equalityComparers.\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public static class EqualityComparer<T>\r
+  {\r
+    readonly static Type isequenced = typeof(ISequenced<>);\r
+\r
+    readonly static Type icollection = typeof(ICollection<>);\r
+\r
+    readonly static Type orderedcollectionequalityComparer = typeof(SequencedCollectionEqualityComparer<,>);\r
+\r
+    readonly static Type unorderedcollectionequalityComparer = typeof(UnsequencedCollectionEqualityComparer<,>);\r
+\r
+    readonly static Type equalityequalityComparer = typeof(EquatableEqualityComparer<>);\r
+\r
+    readonly static Type iequalitytype = typeof(IEquatable<T>);\r
+\r
+    static SCG.IEqualityComparer<T> cachedDefault = null;\r
+\r
+    //TODO: find the right word for initialized+invocation \r
+    /// <summary>\r
+    /// A default generic equalityComparer for type T. The procedure is as follows:\r
+    /// <list>\r
+    /// <item>If T is int, double, byte or char, \r
+    /// the equalityComparer will be a standard equalityComparer for that type</item>\r
+    /// <item>If the actual generic argument T implements the generic interface\r
+    /// <see cref="T:C5.ISequenced`1"/> for some value W of its generic parameter T,\r
+    /// the equalityComparer will be <see cref="T:C5.SequencedCollectionEqualityComparer`2"/></item>\r
+    /// <item>If the actual generic argument T implements \r
+    /// <see cref="T:C5.ICollectionValue`1"/> for some value W of its generic parameter T,\r
+    /// the equalityComparer will be <see cref="T:C5.UnsequencedCollectionEqualityComparer`2"/></item>\r
+    /// <item>If T is a type implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer\r
+    /// will be <see cref="T:C5.EquatableEqualityComparer`1"/></item>\r
+    /// <item>If T is a type not implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer\r
+    /// will be <see cref="T:C5.NaturalEqualityComparer`1"/> </item>\r
+    /// </list>   \r
+    /// The <see cref="T:C5.IEqualityComparer`1"/> object is constructed when this class is initialised, i.e. \r
+    /// its static constructors called. Thus, the property will be the same object \r
+    /// for the duration of an invocation of the runtime, but a value serialized in \r
+    /// another invocation and deserialized here will not be the same object.\r
+    /// </summary>\r
+    /// <value></value>\r
+    public static SCG.IEqualityComparer<T> Default\r
+    {\r
+      get\r
+      {\r
+        if (cachedDefault != null)\r
+          return cachedDefault;\r
+\r
+        Type t = typeof(T);\r
+\r
+        if (t.IsValueType)\r
+        {\r
+          if (t.Equals(typeof(int)))\r
+            return cachedDefault = (SCG.IEqualityComparer<T>)(IntEqualityComparer.Default);\r
+          else if (t.Equals(typeof(double)))\r
+            return cachedDefault = (SCG.IEqualityComparer<T>)(DoubleEqualityComparer.Default);\r
+          else if (t.Equals(typeof(byte)))\r
+            return cachedDefault = (SCG.IEqualityComparer<T>)(ByteEqualityComparer.Default);\r
+          else if (t.Equals(typeof(char)))\r
+            return cachedDefault = (SCG.IEqualityComparer<T>)(CharEqualityComparer.Default);\r
+        }\r
+        Type[] interfaces = t.GetInterfaces();\r
+        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(isequenced))\r
+          return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));\r
+        foreach (Type ty in interfaces)\r
+        {\r
+          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(isequenced))\r
+            return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));\r
+        }\r
+        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(icollection))\r
+          return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));\r
+        foreach (Type ty in interfaces)\r
+        {\r
+          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(icollection))\r
+            return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));\r
+        }\r
+        if (iequalitytype.IsAssignableFrom(t))\r
+          return createAndCache(equalityequalityComparer.MakeGenericType(new Type[] { t }));\r
+        else\r
+          return cachedDefault = NaturalEqualityComparer<T>.Default;\r
+      }\r
+    }\r
+    static SCG.IEqualityComparer<T> createAndCache(Type equalityComparertype)\r
+    {\r
+      return cachedDefault = (SCG.IEqualityComparer<T>)(equalityComparertype.GetProperty("Default", BindingFlags.Static | BindingFlags.Public).GetValue(null, null));\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// A default item equalityComparer calling through to\r
+  /// the GetHashCode and Equals methods inherited from System.Object.\r
+  /// </summary>\r
+  public sealed class NaturalEqualityComparer<T> : SCG.IEqualityComparer<T>\r
+  {\r
+    static NaturalEqualityComparer<T> cached;\r
+    NaturalEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public static NaturalEqualityComparer<T> Default { get { return cached ?? (cached = new NaturalEqualityComparer<T>()); } }\r
+    //TODO: check if null check is reasonable\r
+    //Answer: if we have struct C<T> { T t; int i;} and implement GetHashCode as\r
+    //the sum of hashcodes, and T may be any type, we cannot make the null check \r
+    //inside the definition of C<T> in a reasonable way.\r
+    /// <summary>\r
+    /// Get the hash code with respect to this item equalityComparer\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 == null ? 0 : item.GetHashCode(); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if two items are equal with respect to this item equalityComparer\r
+    /// </summary>\r
+    /// <param name="item1">first item</param>\r
+    /// <param name="item2">second item</param>\r
+    /// <returns>True if equal</returns>\r
+    [Tested]\r
+    public bool Equals(T item1, T item2)\r
+    {\r
+      return item1 == null ? item2 == null : item1.Equals(item2);\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// A default equalityComparer for a type, T, implementing <see cref="T:C5.IEquatable`1"/>. \r
+  /// \r
+  /// The equalityComparer forwards calls to GetHashCode and Equals to the methods \r
+  /// on T. The point is that it is Equals(T) and not Equals(object)\r
+  /// that is called. This will save a boxing/unboxing pair if T is a value type\r
+  /// and in general a runtime type check.\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class EquatableEqualityComparer<T> : SCG.IEqualityComparer<T> where T : IEquatable<T>\r
+  {\r
+    static EquatableEqualityComparer<T> cached = new EquatableEqualityComparer<T>();\r
+    EquatableEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public static EquatableEqualityComparer<T> Default { get { return cached ?? (cached = new EquatableEqualityComparer<T>()); } }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int GetHashCode(T item) { return item == null ? 0 : item.GetHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item1"></param>\r
+    /// <param name="item2"></param>\r
+    /// <returns></returns>\r
+    public bool Equals(T item1, T item2) { return item1 == null ? item2 == null : item1.Equals(item2); }\r
+  }\r
+\r
+  /// <summary>\r
+  /// A equalityComparer for a reference type that uses reference equality for equality and the hash code from object as hash code.\r
+  /// </summary>\r
+  /// <typeparam name="T">The item type. Must be a reference type.</typeparam>\r
+  public class ReferenceEqualityComparer<T> : SCG.IEqualityComparer<T> where T : class\r
+  {\r
+    static ReferenceEqualityComparer<T> cached;\r
+    ReferenceEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public static ReferenceEqualityComparer<T> Default { get { return cached ?? (cached = new ReferenceEqualityComparer<T>()); } }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int GetHashCode(T item)\r
+    {\r
+      return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(item);\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 object.ReferenceEquals(i1, i2);\r
+    }\r
+  }\r
+\r
+  /// <summary>\r
+  /// An equalityComparer compatible with a given comparer. All hash codes are 0, \r
+  /// meaning that anything based on hash codes will be quite inefficient.\r
+  /// <para><b>Note: this will give a new EqualityComparer each time created!</b></para>\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class ComparerZeroHashCodeEqualityComparer<T> : SCG.IEqualityComparer<T>\r
+  {\r
+    SCG.IComparer<T> comparer;\r
+    /// <summary>\r
+    /// Create a trivial <see cref="T:C5.IEqualityComparer`1"/> compatible with the \r
+    /// <see cref="T:C5.IComparer`1"/> <code>comparer</code>\r
+    /// </summary>\r
+    /// <param name="comparer"></param>\r
+    public ComparerZeroHashCodeEqualityComparer(SCG.IComparer<T> comparer)\r
+    {\r
+      if (comparer == null)\r
+        throw new NullReferenceException("Compaer cannot be null");\r
+      this.comparer = comparer;\r
+    }\r
+    /// <summary>\r
+    /// A trivial, inefficient hash fuction. Compatible with any equality relation.\r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns>0</returns>\r
+    public int GetHashCode(T item) { return 0; }\r
+    /// <summary>\r
+    /// Equality of two items as defined by the comparer.\r
+    /// </summary>\r
+    /// <param name="item1"></param>\r
+    /// <param name="item2"></param>\r
+    /// <returns></returns>\r
+    public bool Equals(T item1, T item2) { return comparer.Compare(item1, item2) == 0; }\r
+  }\r
+\r
+  /// <summary>\r
+  /// Prototype for an sequenced equalityComparer for something (T) that implements ISequenced[W]\r
+  /// This will use ISequenced[W] specific implementations of the equalityComparer operations\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  /// <typeparam name="W"></typeparam>\r
+  public class SequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>\r
+      where T : ISequenced<W>\r
+  {\r
+    static SequencedCollectionEqualityComparer<T, W> cached;\r
+    SequencedCollectionEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public static SequencedCollectionEqualityComparer<T, W> Default { get { return cached ?? (cached = new SequencedCollectionEqualityComparer<T, W>()); } }\r
+    /// <summary>\r
+    /// Get the hash code with respect to this sequenced equalityComparer\r
+    /// </summary>\r
+    /// <param name="collection">The collection</param>\r
+    /// <returns>The hash code</returns>\r
+    [Tested]\r
+    public int GetHashCode(T collection) { return collection.GetSequencedHashCode(); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if two items are equal with respect to this sequenced equalityComparer\r
+    /// </summary>\r
+    /// <param name="collection1">first collection</param>\r
+    /// <param name="collection2">second collection</param>\r
+    /// <returns>True if equal</returns>\r
+    [Tested]\r
+    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.SequencedEquals(collection2); }\r
+  }\r
+\r
+  /// <summary>\r
+  /// Prototype for an unsequenced equalityComparer for something (T) that implements ICollection[W]\r
+  /// This will use ICollection[W] specific implementations of the equalityComparer operations\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  /// <typeparam name="W"></typeparam>\r
+  public class UnsequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>\r
+      where T : ICollection<W>\r
+  {\r
+    static UnsequencedCollectionEqualityComparer<T, W> cached;\r
+    UnsequencedCollectionEqualityComparer() { }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public static UnsequencedCollectionEqualityComparer<T, W> Default { get { return cached ?? (cached = new UnsequencedCollectionEqualityComparer<T, W>()); } }\r
+    /// <summary>\r
+    /// Get the hash code with respect to this unsequenced equalityComparer\r
+    /// </summary>\r
+    /// <param name="collection">The collection</param>\r
+    /// <returns>The hash code</returns>\r
+    [Tested]\r
+    public int GetHashCode(T collection) { return collection.GetUnsequencedHashCode(); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if two collections are equal with respect to this unsequenced equalityComparer\r
+    /// </summary>\r
+    /// <param name="collection1">first collection</param>\r
+    /// <param name="collection2">second collection</param>\r
+    /// <returns>True if equal</returns>\r
+    [Tested]\r
+    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.UnsequencedEquals(collection2); }\r
+  }\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+#if EXPERIMENTAL\r
+namespace C5.EqualityComparerBuilder\r
+{\r
+\r
+  /// <summary>\r
+  /// IEqualityComparer 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, MakeEqualityComparer will return a default equalityComparer,\r
+  /// else this class will implement IequalityComparer[T] via Invoke() on the\r
+  /// reflected method infos.\r
+  /// </summary>\r
+  public class ByInvoke<T> : SCG.IEqualityComparer<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 SCG.IEqualityComparer<T> MakeEqualityComparer()\r
+    {\r
+      if (hinfo != null && einfo != null)\r
+        return new ByInvoke<T>();\r
+      else\r
+        return NaturalEqualityComparer<T>.Default;\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 equalityComparer by RTCG to\r
+  /// avoid the Invoke() overhead. \r
+  /// </summary>\r
+  public class ByRTCG\r
+  {\r
+    private static ModuleBuilder moduleBuilder;\r
+\r
+    private static AssemblyBuilder assemblyBuilder;\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="hinfo"></param>\r
+    /// <param name="einfo"></param>\r
+    /// <returns></returns>\r
+    public static SCG.IEqualityComparer<T> CreateEqualityComparer<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(T);\r
+      Type o_t = typeof(object);\r
+      Type h_t = typeof(SCG.IEqualityComparer<T>);\r
+      Type i_t = typeof(int);\r
+      //TODO: protect uid for thread safety!\r
+      string name = "C5.Dynamic.EqualityComparer_" + Guid.NewGuid().ToString();\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 equalityComparer_t = tb.CreateType();\r
+      object equalityComparer = equalityComparer_t.GetConstructor(new Type[0]).Invoke(null);\r
+\r
+      return (SCG.IEqualityComparer<T>)equalityComparer;\r
+    }\r
+\r
+/// <summary>\r
+/// \r
+/// </summary>\r
+/// <typeparam name="T"></typeparam>\r
+/// <returns></returns>\r
+    public static SCG.IEqualityComparer<T> build<T>()\r
+    {\r
+      MethodInfo hinfo = ByInvoke<T>.hinfo, einfo = ByInvoke<T>.einfo;\r
+\r
+      if (hinfo != null && einfo != null)\r
+        return CreateEqualityComparer<T>(hinfo, einfo);\r
+      else\r
+        return EqualityComparer<T>.Default;\r
+    }\r
+\r
+/// <summary>\r
+/// \r
+/// </summary>\r
+    public void dump()\r
+    {\r
+      assemblyBuilder.Save("LeFake.dll");\r
+    }\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..3ae5abe
--- /dev/null
@@ -0,0 +1,1884 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// A generic collection, that can be enumerated backwards.\r
+  /// </summary>\r
+  public interface IDirectedEnumerable<T> : SCG.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 typically 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
+  /// <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> : SCG.IEnumerable<T>, IShowable\r
+  {\r
+    /// <summary>\r
+    /// A flag bitmap of the events subscribable to by this collection.\r
+    /// </summary>\r
+    /// <value></value>\r
+    EventTypeEnum ListenableEvents { get;}\r
+\r
+    /// <summary>\r
+    /// A flag bitmap of the events currently subscribed to by this collection.\r
+    /// </summary>\r
+    /// <value></value>\r
+    EventTypeEnum ActiveEvents { get;}\r
+\r
+    /// <summary>\r
+    /// The change event. Will be raised for every change operation on the collection.\r
+    /// </summary>\r
+    event CollectionChangedHandler<T> CollectionChanged;\r
+\r
+    /// <summary>\r
+    /// The change event. Will be raised for every clear operation on the collection.\r
+    /// </summary>\r
+    event CollectionClearedHandler<T> CollectionCleared;\r
+\r
+    /// <summary>\r
+    /// The item added  event. Will be raised for every individual addition to the collection.\r
+    /// </summary>\r
+    event ItemsAddedHandler<T> ItemsAdded;\r
+\r
+    /// <summary>\r
+    /// The item inserted  event. Will be raised for every individual insertion to the collection.\r
+    /// </summary>\r
+    event ItemInsertedHandler<T> ItemInserted;\r
+\r
+    /// <summary>\r
+    /// The item removed event. Will be raised for every individual removal from the collection.\r
+    /// </summary>\r
+    event ItemsRemovedHandler<T> ItemsRemoved;\r
+\r
+    /// <summary>\r
+    /// The item removed at event. Will be raised for every individual removal at from the collection.\r
+    /// </summary>\r
+    event ItemRemovedAtHandler<T> ItemRemovedAt;\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>True if this collection is empty.</value>\r
+    bool IsEmpty { get;}\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="array">The array to copy to</param>\r
+    /// <param name="index">The index at which to copy the first item</param>\r
+    void CopyTo(T[] array, int index);\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="action">The delegate to apply</param>\r
+    void Apply(Act<T> action);\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="predicate">A  delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>True is such an item exists</returns>\r
+    bool Exists(Fun<T, bool> predicate);\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the first one in enumeration order.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <param name="item"></param>\r
+    /// <returns>True is such an item exists</returns>\r
+    bool Find(Fun<T, bool> predicate, out T item);\r
+\r
+\r
+    /// <summary>\r
+    /// Check if all items in this collection satisfies a specific predicate.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>True if all items satisfies the predicate</returns>\r
+    bool All(Fun<T, bool> predicate);\r
+\r
+    /// <summary>\r
+    /// Choose some item of this collection. \r
+    /// <para>Implementations must assure that the item \r
+    /// returned may be efficiently removed.</para>\r
+    /// <para>Implementors may decide to implement this method in a way such that repeated\r
+    /// calls do not necessarily give the same result, i.e. so that the result of the following \r
+    /// test is undetermined:\r
+    /// <code>coll.Choose() == coll.Choose()</code></para>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    T Choose();\r
+\r
+    /// <summary>\r
+    /// Create an enumerable, enumerating the items of this collection that satisfies \r
+    /// a certain condition.\r
+    /// </summary>\r
+    /// <param name="filter">The T->bool filter delegate defining the condition</param>\r
+    /// <returns>The filtered enumerable</returns>\r
+    SCG.IEnumerable<T> Filter(Fun<T, bool> 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 typically 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
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the first one in enumeration order.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <param name="item"></param>\r
+    /// <returns>True is such an item exists</returns>\r
+    bool FindLast(Fun<T, bool> predicate, out T item);\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>, ICloneable\r
+  {\r
+    /// <summary>\r
+    /// If true any call of an updating operation will throw an\r
+    /// <code>ReadOnlyCollectionException</code>\r
+    /// </summary>\r
+    /// <value>True if this collection is read-only.</value>\r
+    bool IsReadOnly { get;}\r
+\r
+    //TODO: wonder where the right position of this is\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
+    //TODO: wonder where the right position of this is. And the semantics.\r
+    /// <summary>\r
+    /// (Here should be a discussion of the role of equalityComparers. Any ). \r
+    /// </summary>\r
+    /// <value>The equalityComparer used by this collection to check equality of items. \r
+    /// Or null (????) if collection does not check equality at all or uses a comparer.</value>\r
+    SCG.IEqualityComparer<T> EqualityComparer { get;}\r
+\r
+    //ItemEqualityTypeEnum ItemEqualityType {get ;}\r
+\r
+    //TODO: find a good name\r
+\r
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    bool DuplicatesByCounting { get;}\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
+    /// <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>(SCG.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
+    /// <i>This is only relevant for developers of the library</i>\r
+    /// </summary>\r
+    /// <returns>True if check was passed.</returns>\r
+    bool Check();\r
+  }\r
+\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
+    //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
+    /// <para>See <see cref="T:C5.Speed"/> for the set of symbols.</para>\r
+    /// </summary>\r
+    /// <value>A characterization of the speed of lookup operations\r
+    /// (<code>Contains()</code> etc.) of the implementation of this collection.</value>\r
+    Speed ContainsSpeed { get;}\r
+\r
+    /// <summary>\r
+    /// The unordered collection hashcode is defined as the sum of \r
+    /// <code>h(hashcode(item))</code> over the items\r
+    /// of the collection, where the function <code>h</code> is a function from \r
+    /// int to int of the form <code> t -> (a0*t+b0)^(a1*t+b1)^(a2*t+b2)</code>, where \r
+    /// the ax and bx are the same for all collection classes. \r
+    /// <para>The current implementation uses fixed values for the ax and bx, \r
+    /// specified as constants in the code.</para>\r
+    /// </summary>\r
+    /// <returns>The unordered hashcode of this collection.</returns>\r
+    int GetUnsequencedHashCode();\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 itemequalityComparer\r
+    /// to compare individual items.\r
+    /// </summary>\r
+    /// <param name="otherCollection">The collection to compare to.</param>\r
+    /// <returns>True if this collection and that contains the same items.</returns>\r
+    bool UnsequencedEquals(ICollection<T> otherCollection);\r
+\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains (an item equivalent to according to the\r
+    /// itemequalityComparer) 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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    ICollectionValue<T> UniqueItems();\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities();\r
+\r
+    /// <summary>\r
+    /// Check whether this collection contains all the values in another collection.\r
+    /// If this collection has bag semantics (<code>AllowsDuplicates==true</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
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+    bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T;\r
+\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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
+    /// itemequalityComparer 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
+    /// itemequalityComparer to a particular value. If so, update the item in the collection \r
+    /// with a (binary copy of) the supplied value. If the collection has bag semantics,\r
+    /// it depends on the value of DuplicatesByCounting 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
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer to a particular value. If so, update the item in the collection \r
+    /// with a (binary copy of) the supplied value. If the collection has bag semantics,\r
+    /// it depends on the value of DuplicatesByCounting if this updates all equivalent copies in\r
+    /// the collection or just one.\r
+    /// </summary>\r
+    /// <param name="item">Value to update.</param>\r
+    /// <param name="olditem">On output the olditem, if found.</param>\r
+    /// <returns>True if the item was found and hence updated.</returns>\r
+    bool Update(T item, out T olditem);\r
+\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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
+    /// <param name="olditem">On output the olditem, if found.</param>\r
+    /// <returns>True if the item was found and updated (hence not added).</returns>\r
+    bool UpdateOrAdd(T item, out T olditem);\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
+    /// <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.</param>\r
+    /// <param name="removeditem">The value removed if any.</param>\r
+    /// <returns>True if the item was found (and removed).</returns>\r
+    bool Remove(T item, out T removeditem);\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to remove.</param>\r
+    void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T;\r
+\r
+    //void RemoveAll(Fun<T, bool> predicate);\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to retain.</param>\r
+    void RetainAll<U>(SCG.IEnumerable<U> items) where U : T;\r
+\r
+    //void RetainAll(Fun<T, bool> predicate);\r
+    //IDictionary<T> UniqueItems()\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// An editable collection maintaining a definite sequence order of the items.\r
+  ///\r
+  /// <i>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.</i>\r
+  /// <i>This interface is usually implemented by explicit interface implementation,\r
+  /// not as ordinary virtual methods.</i>\r
+  /// </summary>\r
+  public interface ISequenced<T> : ICollection<T>, IDirectedCollectionValue<T>\r
+  {\r
+    /// <summary>\r
+    /// The hashcode is defined as <code>h(...h(h(h(x1),x2),x3),...,xn)</code> for\r
+    /// <code>h(a,b)=CONSTANT*a+b</code> and the x's the hash codes of the items of \r
+    /// this collection.\r
+    /// </summary>\r
+    /// <returns>The sequence order hashcode of this collection.</returns>\r
+    int GetSequencedHashCode();\r
+\r
+\r
+    /// <summary>\r
+    /// Compare this sequenced collection to another one in sequence order.\r
+    /// </summary>\r
+    /// <param name="otherCollection">The sequenced collection to compare to.</param>\r
+    /// <returns>True if this collection and that contains equal (according to\r
+    /// this collection's itemequalityComparer) in the same sequence order.</returns>\r
+    bool SequencedEquals(ISequenced<T> otherCollection);\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
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or\r
+    /// &gt;= the size of the collection.</exception>\r
+    /// <value>The <code>index</code>'th item of this list.</value>\r
+    /// <param name="index">the index to lookup</param>\r
+    T this[int index] { get;}\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    Speed IndexingSpeed { get;}\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException"></exception>\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 forwards from the start. \r
+    /// </summary>\r
+    /// <param name="item">Item to search for.</param>\r
+    /// <returns>Index of item from start. A negative number if item not found, \r
+    /// namely the two-complement of the index at which the Add operation would put the item.</returns>\r
+    int IndexOf(T item);\r
+\r
+\r
+    /// <summary>\r
+    /// Searches for an item in the list going backwards from the end.\r
+    /// </summary>\r
+    /// <param name="item">Item to search for.</param>\r
+    /// <returns>Index of of item from the end. A negative number if item not found, \r
+    /// namely the two-complement of the index at which the Add operation would put the item.</returns>\r
+    int LastIndexOf(T item);\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the index of the first one.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>the index, if found, a negative value else</returns>\r
+    int FindIndex(Fun<T, bool> predicate);\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the index of the last one.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>the index, if found, a negative value else</returns>\r
+    int FindLastIndex(Fun<T, bool> predicate);\r
+\r
+\r
+    /// <summary>\r
+    /// Remove the item at a specific position of the list.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or\r
+    /// &gt;= the size of the collection.</exception>\r
+    /// <param name="index">The index of the item to remove.</param>\r
+    /// <returns>The removed item.</returns>\r
+    T RemoveAt(int index);\r
+\r
+\r
+    /// <summary>\r
+    /// Remove all items in an index interval.\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if start or count \r
+    /// is negative or start+count &gt; the size of the collection.</exception>\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> : IDirectedCollectionValue<T>\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    bool AllowsDuplicates { get;}\r
+    /// <summary>\r
+    /// Get the <code>index</code>'th element of the stack.  The bottom of the stack has index 0.\r
+    /// </summary>\r
+    /// <param name="index"></param>\r
+    /// <returns></returns>\r
+    T this[int index] { get;}\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
+  /// <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> : IDirectedCollectionValue<T>\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    bool AllowsDuplicates { get;}\r
+    /// <summary>\r
+    /// Get the <code>index</code>'th element of the queue.  The front of the queue has index 0.\r
+    /// </summary>\r
+    /// <param name="index"></param>\r
+    /// <returns></returns>\r
+    T this[int index] { get;}\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 need a description of the view functionality here!\r
+  /// </summary>\r
+  public interface IList<T> : IIndexed<T>, IDisposable\r
+  {\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <value>The first item in this list.</value>\r
+    T First { get;}\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <value>The last item in this list.</value>\r
+    T Last { get;}\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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    bool IsFixedSize { get; }\r
+\r
+    /// <summary>\r
+    /// On this list, this indexer is read/write.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or\r
+    /// &gt;= the size of the collection.</exception>\r
+    /// <value>The index'th item of this list.</value>\r
+    /// <param name="index">The index of the item to fetch or store.</param>\r
+    new T this[int index] { get; set;}\r
+\r
+    /// <summary>\r
+    /// Insert an item at a specific index location in this list. \r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or\r
+    /// &gt; the size of the collection.</exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> if the list has\r
+    /// <code>AllowsDuplicates==false</code> and the item is \r
+    /// already in the list.</exception>\r
+    /// <param name="index">The index at which to insert.</param>\r
+    /// <param name="item">The item to insert.</param>\r
+    void Insert(int index, T item);\r
+\r
+    /// <summary>\r
+    /// Insert an item at the end of a compatible view, used as a pointer.\r
+    /// <para>The <code>pointer</code> must be a view on the same list as\r
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be\r
+    /// a valid insertion point of <code>this</code></para>\r
+    /// </summary>\r
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> \r
+    /// is not a view on the same list as <code>this</code></exception>\r
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of \r
+    ///  <code>pointer</code> is not inside <code>this</code></exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> if the list has\r
+    /// <code>AllowsDuplicates==false</code> and the item is \r
+    /// already in the list.</exception>\r
+    /// <param name="pointer"></param>\r
+    /// <param name="item"></param>\r
+    void Insert(IList<T> pointer, T item);\r
+\r
+    /// <summary>\r
+    /// Insert an item at the front of this list.\r
+    /// <exception cref="DuplicateNotAllowedException"/> if the list has\r
+    /// <code>AllowsDuplicates==false</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
+    /// <summary>\r
+    /// Insert an item at the back of this list.\r
+    /// <exception cref="DuplicateNotAllowedException"/> if the list has\r
+    /// <code>AllowsDuplicates==false</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
+    /// <summary>\r
+    /// Insert into this list all items from an enumerable collection starting \r
+    /// at a particular index.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or\r
+    /// &gt; the size of the collection.</exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> if the list has \r
+    /// <code>AllowsDuplicates==false</code> and one of the items to insert is\r
+    /// already in the list.</exception>\r
+    /// <param name="index">Index to start inserting at</param>\r
+    /// <param name="items">Items to insert</param>\r
+    /// <typeparam name="U"></typeparam>\r
+    void InsertAll<U>(int index, SCG.IEnumerable<U> items) where U : T;\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(Fun<T, bool> filter);\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 equalityComparer 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>(Fun<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 equalityComparer 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="equalityComparer">The equalityComparer to use for the new list</param>\r
+    /// <returns>The new list.</returns>\r
+    IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer);\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="NoSuchItemException"/> if this list is empty.\r
+    /// </summary>\r
+    /// <returns>The removed item.</returns>\r
+    T Remove();\r
+\r
+    /// <summary>\r
+    /// Remove one item from the front of the list.\r
+    /// <exception cref="NoSuchItemException"/> if this list is empty.\r
+    /// </summary>\r
+    /// <returns>The removed item.</returns>\r
+    T RemoveFirst();\r
+\r
+    /// <summary>\r
+    /// Remove one item from the back of the list.\r
+    /// <exception cref="NoSuchItemException"/> if this list is empty.\r
+    /// </summary>\r
+    /// <returns>The removed item.</returns>\r
+    T RemoveLast();\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
+    /// <summary>\r
+    /// Create a list view on this list containing the (first) occurrence of a particular item. \r
+    /// <exception cref="NoSuchItemException"/> if the item is not in this list.\r
+    /// </summary>\r
+    /// <param name="item">The item to find.</param>\r
+    /// <returns>The new list view.</returns>\r
+    IList<T> ViewOf(T item);\r
+\r
+    /// <summary>\r
+    /// Create a list view on this list containing the last occurrence of a particular item. \r
+    /// <exception cref="NoSuchItemException"/> if the item is not in this list.\r
+    /// </summary>\r
+    /// <param name="item">The item to find.</param>\r
+    /// <returns>The new list view.</returns>\r
+    IList<T> LastViewOf(T item);\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
+    /// <summary>\r
+    /// </summary>\r
+    /// <value>Offset for this list view or 0 for an underlying list.</value>\r
+    int Offset { get;}\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    bool IsValid { get;}\r
+\r
+    /// <summary>\r
+    /// Slide this list view along the underlying list.\r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation\r
+    /// would bring either end of the view outside the underlying list.</exception>\r
+    /// <param name="offset">The signed amount to slide: positive to slide\r
+    /// towards the end.</param>\r
+    IList<T> Slide(int offset);\r
+\r
+    /// <summary>\r
+    /// Slide this list view along the underlying list, changing its size.\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation\r
+    /// would bring either end of the view outside the underlying list.</exception>\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
+    IList<T> Slide(int offset, int size);\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <returns></returns>\r
+    bool TrySlide(int offset);\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <param name="size"></param>\r
+    /// <returns></returns>\r
+    bool TrySlide(int offset, int size);\r
+\r
+    /// <summary>\r
+    /// \r
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>\r
+    /// </summary>\r
+    /// <param name="otherView"></param>\r
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>\r
+    /// <exception cref="ArgumentOutOfRangeException">If <code>otherView</code> is strictly to the left of this view</exception>\r
+    /// <returns></returns>\r
+    IList<T> Span(IList<T> otherView);\r
+\r
+    /// <summary>\r
+    /// Reverse the list so the items are in the opposite sequence order.\r
+    /// </summary>\r
+    void Reverse();\r
+\r
+    /// <summary>\r
+    /// Check if this list is sorted according to the default sorting order\r
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class \r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">if T is not comparable</exception>\r
+    /// <returns>True if the list is sorted, else false.</returns>\r
+    bool IsSorted();\r
+\r
+    /// <summary>\r
+    /// Check if this list is sorted according to a specific sorting order.\r
+    /// </summary>\r
+    /// <param name="comparer">The comparer defining the sorting order.</param>\r
+    /// <returns>True if the list is sorted, else false.</returns>\r
+    bool IsSorted(SCG.IComparer<T> comparer);\r
+\r
+    /// <summary>\r
+    /// Sort the items of the list according to the default sorting order\r
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class \r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">if T is not comparable</exception>\r
+    void Sort();\r
+\r
+    /// <summary>\r
+    /// Sort the items of the list according to a specified sorting order.\r
+    /// <para>The sorting does not perform duplicate elimination or identify items\r
+    /// according to the comparer or itemequalityComparer. I.e. the list as an \r
+    /// unsequenced collection with binary equality, will not change.\r
+    /// </para>\r
+    /// </summary>\r
+    /// <param name="comparer">The comparer defining the sorting order.</param>\r
+    void Sort(SCG.IComparer<T> comparer);\r
+\r
+\r
+    /// <summary>\r
+    /// Randomly 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
+  /// The base type of a priority queue handle\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public interface IPriorityQueueHandle<T>\r
+  {\r
+    //TODO: make abstract and prepare for double dispatch:\r
+    //public virtual bool Delete(IPriorityQueue<T> q) { throw new InvalidFooException();}\r
+    //bool Replace(T item);\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
+  /// <para>\r
+  /// \r
+  /// </para>\r
+  /// When adding an item, the user may choose to have a handle allocated for this item in the queue. \r
+  /// The resulting handle may be used for deleting the item even if not extremal, and for replacing the item.\r
+  /// A priority queue typically only holds numeric priorities associated with some objects\r
+  /// maintained separately in other collection objects.\r
+  /// </summary>\r
+  public interface IPriorityQueue<T> : IExtensible<T>\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
+    SCG.IComparer<T> Comparer { get;}\r
+    /// <summary>\r
+    /// Get or set the item corresponding to a handle. Throws exceptions on \r
+    /// invalid handles.\r
+    /// </summary>\r
+    /// <param name="handle"></param>\r
+    /// <returns></returns>\r
+    T this[IPriorityQueueHandle<T> handle] { get; set;}\r
+\r
+    /// <summary>\r
+    /// Check if the entry corresponding to a handle is in the priority queue.\r
+    /// </summary>\r
+    /// <param name="handle"></param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    bool Find(IPriorityQueueHandle<T> handle, out T item);\r
+\r
+    /// <summary>\r
+    /// Add an item to the priority queue, receiving a \r
+    /// handle for the item in the queue, \r
+    /// or reusing an existing unused handle.\r
+    /// </summary>\r
+    /// <param name="handle">On output: a handle for the added item. \r
+    /// On input: null for allocating a new handle, or a currently unused handle for reuse. \r
+    /// A handle for reuse must be compatible with this priority queue, \r
+    /// by being created by a priority queue of the same runtime type, but not \r
+    /// necessarily the same priority queue object.</param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    bool Add(ref IPriorityQueueHandle<T> handle, T item);\r
+\r
+    /// <summary>\r
+    /// Delete an item with a handle from a priority queue\r
+    /// </summary>\r
+    /// <param name="handle">The handle for the item. The handle will be invalidated, but reusable.</param>\r
+    /// <returns>The deleted item</returns>\r
+    T Delete(IPriorityQueueHandle<T> handle);\r
+\r
+    /// <summary>\r
+    /// Replace an item with a handle in a priority queue with a new item. \r
+    /// Typically used for changing the priority of some queued object.\r
+    /// </summary>\r
+    /// <param name="handle">The handle for the old item</param>\r
+    /// <param name="item">The new item</param>\r
+    /// <returns>The old item</returns>\r
+    T Replace(IPriorityQueueHandle<T> handle, T item);\r
+\r
+    /// <summary>\r
+    /// Find the current least item of this priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the item.</param>\r
+    /// <returns>The least item.</returns>\r
+    T FindMin(out IPriorityQueueHandle<T> handle);\r
+\r
+    /// <summary>\r
+    /// Find the current largest item of this priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the item.</param>\r
+    /// <returns>The largest item.</returns>\r
+\r
+    T FindMax(out IPriorityQueueHandle<T> handle);\r
+\r
+    /// <summary>\r
+    /// Remove the least item from this  priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the removed item.</param>\r
+    /// <returns>The removed item.</returns>\r
+\r
+    T DeleteMin(out IPriorityQueueHandle<T> handle);\r
+\r
+    /// <summary>\r
+    /// Remove the largest item from this  priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the removed item.</param>\r
+    /// <returns>The removed item.</returns>\r
+    T DeleteMax(out IPriorityQueueHandle<T> handle);\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A sorted collection, i.e. a collection where items are maintained and can be searched for in sorted order.\r
+  /// Thus the sequence order is given as a sorting order.\r
+  /// \r
+  /// <para>The sorting order is defined by a comparer, an object of type IComparer&lt;T&gt; \r
+  /// (<see cref="T:C5.IComparer`1"/>). Implementors of this interface will normally let the user \r
+  /// define the comparer as an argument to a constructor. \r
+  /// Usually there will also be constructors without a comparer argument, in which case the \r
+  /// comparer should be the defalt comparer for the item type, <see cref="P:C5.Comparer`1.Default"/>.</para>\r
+  /// \r
+  /// <para>The comparer of the sorted collection is available as the <code>Comparer</code> property \r
+  /// (<see cref="P:C5.ISorted`1.Comparer"/>).</para>\r
+  /// \r
+  /// <para>The methods are grouped according to\r
+  /// <list>\r
+  /// <item>Extrema: report or report and delete an extremal item. This is reminiscent of simplified priority queues.</item>\r
+  /// <item>Nearest neighbor: report predecessor or successor in the collection of an item. Cut belongs to this group.</item>\r
+  /// <item>Range: report a view of a range of elements or remove all elements in a range.</item>\r
+  /// <item>AddSorted: add a collection of items known to be sorted in the same order (should be faster) (to be removed?)</item>\r
+  /// </list>\r
+  /// </para>\r
+  /// \r
+  /// <para>Since this interface extends ISequenced&lt;T&gt;, sorted collections will also have an \r
+  /// item equalityComparer (<see cref="P:C5.IExtensible`1.EqualityComparer"/>). This equalityComparer will not be used in connection with \r
+  /// the inner workings of the sorted collection, but will be used if the sorted collection is used as \r
+  /// an item in a collection of unsequenced or sequenced collections, \r
+  /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)</para>\r
+  /// \r
+  /// <para>Note that code may check if two sorted collections has the same sorting order \r
+  /// by checking if the Comparer properties are equal. This is done a few places in this library\r
+  /// for optimization purposes.</para>\r
+  /// </summary>\r
+  public interface ISorted<T> : ISequenced<T>\r
+  {\r
+    /// <summary>\r
+    /// Find the current least item of this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The least item.</returns>\r
+    T FindMin();\r
+\r
+\r
+    /// <summary>\r
+    /// Remove the least item from this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The removed item.</returns>\r
+    T DeleteMin();\r
+\r
+\r
+    /// <summary>\r
+    /// Find the current largest item of this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The largest item.</returns>\r
+    T FindMax();\r
+\r
+\r
+    /// <summary>\r
+    /// Remove the largest item from this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The removed item.</returns>\r
+    T DeleteMax();\r
+\r
+    /// <summary>\r
+    /// The comparer object supplied at creation time for this sorted collection.\r
+    /// </summary>\r
+    /// <value>The comparer</value>\r
+    SCG.IComparer<T> Comparer { get;}\r
+\r
+    /// <summary>\r
+    /// Find the strict predecessor in the sorted collection of a particular value,\r
+    /// that is, the largest item in the collection less than the supplied value.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is less than or equal to the minimum of this collection.)</exception>\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
+    /// that is, the least item in the collection greater than the supplied value.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is greater than or equal to the maximum of this collection.)</exception>\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
+    /// that is, the largest item in the collection less than or equal to the supplied value.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is less than the minimum of this collection.)</exception>\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
+    /// that is, the least item in the collection greater than or equal to the supplied value.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is greater than the maximum of this collection.)</exception>\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
+    /// Given a "cut" function from the items of the sorted collection to <code>int</code>\r
+    /// whose only sign changes when going through items in increasing order\r
+    /// can be \r
+    /// <list>\r
+    /// <item>from positive to zero</item>\r
+    /// <item>from positive to negative</item>\r
+    /// <item>from zero to negative</item>\r
+    /// </list>\r
+    /// The "cut" function is supplied as the <code>CompareTo</code> method \r
+    /// of an object <code>c</code> implementing \r
+    /// <code>IComparable&lt;T&gt;</code>. \r
+    /// A typical example is the case where <code>T</code> is comparable and \r
+    /// <code>cutFunction</code> is itself of type <code>T</code>.\r
+    /// <para>This method performs a search in the sorted collection for the ranges in which the\r
+    /// "cut" function is negative, zero respectively positive. If <code>T</code> is comparable\r
+    /// and <code>c</code> is of type <code>T</code>, this is a safe way (no exceptions thrown) \r
+    /// to find predecessor and successor of <code>c</code>.\r
+    /// </para>\r
+    /// <para> If the supplied cut function does not satisfy the sign-change condition, \r
+    /// the result of this call is undefined.\r
+    /// </para>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="cutFunction">The cut function <code>T</code> to <code>int</code>, given\r
+    /// by the <code>CompareTo</code> method of an object implementing \r
+    /// <code>IComparable&lt;T&gt;</code>.</param>\r
+    /// <param name="low">Returns the largest item in the collection, where the\r
+    /// cut function is positive (if any).</param>\r
+    /// <param name="lowIsValid">Returns true if the cut function is positive somewhere\r
+    /// on this collection.</param>\r
+    /// <param name="high">Returns the least item in the collection, where the\r
+    /// cut function is negative (if any).</param>\r
+    /// <param name="highIsValid">Returns true if the cut function is negative somewhere\r
+    /// on this collection.</param>\r
+    /// <returns>True if the cut function is zero somewhere\r
+    /// on this collection.</returns>\r
+    bool Cut(IComparable<T> cutFunction, 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
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\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
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\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
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\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
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\r
+    /// </summary>\r
+    /// <returns>The result directed collection.</returns>\r
+    IDirectedCollectionValue<T> RangeAll();\r
+\r
+\r
+    //TODO: remove now that we assume that we can check the sorting order?\r
+    /// <summary>\r
+    /// Add all the items from another collection with an enumeration order that \r
+    /// is increasing in the items.\r
+    /// </summary>\r
+    /// <exception cref="ArgumentException"> if the enumerated items turns out\r
+    /// not to be in increasing order.</exception>\r
+    /// <param name="items">The collection to add.</param>\r
+    /// <typeparam name="U"></typeparam>\r
+    void AddSorted<U>(SCG.IEnumerable<U> items) where U : T;\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="predicate">The filter delegate defining the predicate.</param>\r
+    /// <returns>The new indexed sorted collection.</returns>\r
+    IIndexedSorted<T> FindAll(Fun<T, bool> predicate);\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="comparer">The comparion relation to use for the result.</param>\r
+    /// <returns>The new sorted collection.</returns>\r
+    IIndexedSorted<V> Map<V>(Fun<T, V> mapper, SCG.IComparer<V> comparer);\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> : ICollectionValue<KeyValuePair<K, V>>, ICloneable\r
+  {\r
+    /// <summary>\r
+    /// The key equalityComparer.\r
+    /// </summary>\r
+    /// <value></value>\r
+    SCG.IEqualityComparer<K> EqualityComparer { get;}\r
+\r
+    /// <summary>\r
+    /// Indexer for dictionary.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no entry is found. </exception>\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>True if dictionary is read-only</value>\r
+    bool IsReadOnly { 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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>A delegate of type <see cref="T:C5.Fun`2"/> defining the partial function from K to V give by the dictionary.</value>\r
+    Fun<K, V> Fun { get; }\r
+\r
+\r
+    //TODO: resolve inconsistency: Add thows exception if key already there, AddAll ignores keys already There?\r
+    /// <summary>\r
+    /// Add a new (key, value) pair (a mapping) to the dictionary.\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException"> if there already is an entry with the same key. </exception>>\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
+    /// <summary>\r
+    /// Add the entries from a collection of <see cref="T:C5.KeyValuePair`2"/> pairs to this dictionary.\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException"> \r
+    /// If the input contains duplicate keys or a key already present in this dictionary.</exception>\r
+    /// <param name="entries"></param>\r
+    void AddAll<U, W>(SCG.IEnumerable<KeyValuePair<U, W>> entries)\r
+        where U : K\r
+        where W : V\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
+    /// <para>See <see cref="T:C5.Speed"/> for the set of symbols.</para>\r
+    /// </summary>\r
+    /// <value>A characterization of the speed of lookup operations\r
+    /// (<code>Contains()</code> etc.) of the implementation of this dictionary.</value>\r
+    Speed ContainsSpeed { get;}\r
+\r
+    /// <summary>\r
+    /// Check whether this collection contains all the values in another collection.\r
+    /// If this collection has bag semantics (<code>AllowsDuplicates==true</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<H>(SCG.IEnumerable<H> items) where H : K;\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
+    /// <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(ref 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 and if found replace the value with a new one.\r
+    /// This can be seen as a non-adding version of "this[key] = val" reporting the old value.\r
+    /// </summary>\r
+    /// <param name="key">The key to look for</param>\r
+    /// <param name="val">The new value</param>\r
+    /// <param name="oldval">The old value if any</param>\r
+    /// <returns>True if key was found</returns>\r
+    bool Update(K key, V val, out V oldval);          //no-adding                                      \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
+    /// 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
+    /// <param name="oldval">The old value if any</param>\r
+    /// <returns>True if key was found and value updated.</returns>\r
+    bool UpdateOrAdd(K key, V val, out V oldval);\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
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    new ISorted<K> Keys { get;}\r
+\r
+    /// <summary>\r
+    /// Find the current least item of this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The least item.</returns>\r
+    KeyValuePair<K, V> FindMin();\r
+\r
+\r
+    /// <summary>\r
+    /// Remove the least item from this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The removed item.</returns>\r
+    KeyValuePair<K, V> DeleteMin();\r
+\r
+\r
+    /// <summary>\r
+    /// Find the current largest item of this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The largest item.</returns>\r
+    KeyValuePair<K, V> FindMax();\r
+\r
+\r
+    /// <summary>\r
+    /// Remove the largest item from this sorted collection.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>\r
+    /// <returns>The removed item.</returns>\r
+    KeyValuePair<K, V> DeleteMax();\r
+\r
+    /// <summary>\r
+    /// The key comparer used by this dictionary.\r
+    /// </summary>\r
+    /// <value></value>\r
+    SCG.IComparer<K> Comparer { get;}\r
+\r
+    /// <summary>\r
+    /// Find the entry with the largest key less than a given key.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>\r
+    /// <param name="key">The key to compare to</param>\r
+    /// <returns>The entry</returns>\r
+    KeyValuePair<K, V> WeakSuccessor(K key);\r
+\r
+    /// <summary>\r
+    /// Given a "cut" function from the items of the sorted collection to <code>int</code>\r
+    /// whose only sign changes when going through items in increasing order\r
+    /// can be \r
+    /// <list>\r
+    /// <item>from positive to zero</item>\r
+    /// <item>from positive to negative</item>\r
+    /// <item>from zero to negative</item>\r
+    /// </list>\r
+    /// The "cut" function is supplied as the <code>CompareTo</code> method \r
+    /// of an object <code>c</code> implementing \r
+    /// <code>IComparable&lt;K&gt;</code>. \r
+    /// A typical example is the case where <code>K</code> is comparable and \r
+    /// <code>c</code> is itself of type <code>K</code>.\r
+    /// <para>This method performs a search in the sorted collection for the ranges in which the\r
+    /// "cut" function is negative, zero respectively positive. If <code>K</code> is comparable\r
+    /// and <code>c</code> is of type <code>K</code>, this is a safe way (no exceptions thrown) \r
+    /// to find predecessor and successor of <code>c</code>.\r
+    /// </para>\r
+    /// <para> If the supplied cut function does not satisfy the sign-change condition, \r
+    /// the result of this call is undefined.\r
+    /// </para>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="cutFunction">The cut function <code>K</code> to <code>int</code>, given\r
+    /// by the <code>CompareTo</code> method of an object implementing \r
+    /// <code>IComparable&lt;K&gt;</code>.</param>\r
+    /// <param name="lowEntry">Returns the largest item in the collection, where the\r
+    /// cut function is positive (if any).</param>\r
+    /// <param name="lowIsValid">Returns true if the cut function is positive somewhere\r
+    /// on this collection.</param>\r
+    /// <param name="highEntry">Returns the least item in the collection, where the\r
+    /// cut function is negative (if any).</param>\r
+    /// <param name="highIsValid">Returns true if the cut function is negative somewhere\r
+    /// on this collection.</param>\r
+    /// <returns>True if the cut function is zero somewhere\r
+    /// on this collection.</returns>\r
+    bool Cut(IComparable<K> cutFunction, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid);\r
+\r
+    /// <summary>\r
+    /// Query this sorted collection for items greater than or equal to a supplied value.\r
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\r
+    /// </summary>\r
+    /// <param name="bot">The lower bound (inclusive).</param>\r
+    /// <returns>The result directed collection.</returns>\r
+    IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot);\r
+\r
+\r
+    /// <summary>\r
+    /// Query this sorted collection for items between two supplied values.\r
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\r
+    /// </summary>\r
+    /// <param name="lowerBound">The lower bound (inclusive).</param>\r
+    /// <param name="upperBound">The upper bound (exclusive).</param>\r
+    /// <returns>The result directed collection.</returns>\r
+    IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K lowerBound, K upperBound);\r
+\r
+\r
+    /// <summary>\r
+    /// Query this sorted collection for items less than a supplied value.\r
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\r
+    /// </summary>\r
+    /// <param name="top">The upper bound (exclusive).</param>\r
+    /// <returns>The result directed collection.</returns>\r
+    IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top);\r
+\r
+\r
+    /// <summary>\r
+    /// Create a directed collection with the same items as this collection.\r
+    /// <para>The returned collection is not a copy but a view into the collection.</para>\r
+    /// <para>The view is fragile in the sense that changes to the underlying collection will \r
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>\r
+    /// </summary>\r
+    /// <returns>The result directed collection.</returns>\r
+    IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll();\r
+\r
+\r
+    //TODO: remove now that we assume that we can check the sorting order?\r
+    /// <summary>\r
+    /// Add all the items from another collection with an enumeration order that \r
+    /// is increasing in the items.\r
+    /// </summary>\r
+    /// <exception cref="ArgumentException"> if the enumerated items turns out\r
+    /// not to be in increasing order.</exception>\r
+    /// <param name="items">The collection to add.</param>\r
+    void AddSorted(SCG.IEnumerable<KeyValuePair<K, V>> 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(K 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(K low, K 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(K hi);\r
+  }\r
+\r
+\r
+\r
+  /*******************************************************************/\r
+  /*/// <summary>\r
+  /// The type of an item comparer\r
+  /// <i>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.</i>\r
+  /// <i>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.</i>\r
+  /// <i>Implementations of this interface must always return values from the method\r
+  /// and never throw exceptions.</i>\r
+  /// <i>This interface is identical to System.Collections.Generic.IComparer&lt;T&gt;</i>\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="item1">First item</param>\r
+    /// <param name="item2">Second item</param>\r
+    /// <returns>Positive if item1 is greater than item2, 0 if they are equal, negative if item1 is less than item2</returns>\r
+    int Compare(T item1, T item2);\r
+  }\r
+\r
+  /// <summary>\r
+  /// The type of an item equalityComparer. \r
+  /// <i>Implementations of this interface <b>must</b> assure that the methods are \r
+  /// consistent, that is, that whenever two items i1 and i2 satisfies that Equals(i1,i2)\r
+  /// returns true, then GetHashCode returns the same value for i1 and i2.</i>\r
+  /// <i>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.</i>\r
+  /// <i>Implementations of this interface must always return values from the methods\r
+  /// and never throw exceptions.</i>\r
+  /// <i>This interface is similar in function to System.IKeyComparer&lt;T&gt;</i>\r
+  /// </summary>\r
+  public interface SCG.IEqualityComparer<T>\r
+  {\r
+    /// <summary>\r
+    /// Get the hash code with respect to this item equalityComparer\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 equalityComparer\r
+    /// </summary>\r
+    /// <param name="item1">first item</param>\r
+    /// <param name="item2">second item</param>\r
+    /// <returns>True if equal</returns>\r
+    bool Equals(T item1, T item2);\r
+  }*/\r
+}\r
diff --git a/mcs/class/Mono.C5/C5/MappedEnumerators.cs b/mcs/class/Mono.C5/C5/MappedEnumerators.cs
new file mode 100644 (file)
index 0000000..580a34d
--- /dev/null
@@ -0,0 +1,145 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  abstract class MappedDirectedCollectionValue<T, V> : DirectedCollectionValueBase<V>, IDirectedCollectionValue<V>\r
+  {\r
+    IDirectedCollectionValue<T> directedcollectionvalue;\r
+\r
+    abstract public V Map(T item);\r
+\r
+    public MappedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollectionvalue)\r
+    {\r
+      this.directedcollectionvalue = directedcollectionvalue;\r
+    }\r
+\r
+    public override V Choose() { return Map(directedcollectionvalue.Choose()); }\r
+\r
+    public override bool IsEmpty { get { return directedcollectionvalue.IsEmpty; } }\r
+\r
+    public override int Count { get { return directedcollectionvalue.Count; } }\r
+\r
+    public override Speed CountSpeed { get { return directedcollectionvalue.CountSpeed; } }\r
+\r
+    public override IDirectedCollectionValue<V> Backwards()\r
+    {\r
+      MappedDirectedCollectionValue<T, V> retval = (MappedDirectedCollectionValue<T, V>)MemberwiseClone();\r
+      retval.directedcollectionvalue = directedcollectionvalue.Backwards();\r
+      return retval;\r
+      //If we made this classs non-abstract we could do\r
+      //return new MappedDirectedCollectionValue<T,V>(directedcollectionvalue.Backwards());;\r
+    }\r
+\r
+\r
+    public override SCG.IEnumerator<V> GetEnumerator()\r
+    {\r
+      foreach (T item in directedcollectionvalue)\r
+        yield return Map(item);\r
+    }\r
+\r
+    public override EnumerationDirection Direction\r
+    {\r
+      get { return directedcollectionvalue.Direction; }\r
+    }\r
+\r
+    IDirectedEnumerable<V> IDirectedEnumerable<V>.Backwards()\r
+    {\r
+      return Backwards();\r
+    }\r
+\r
+\r
+  }\r
+\r
+  abstract class MappedCollectionValue<T, V> : CollectionValueBase<V>, ICollectionValue<V>\r
+  {\r
+    ICollectionValue<T> collectionvalue;\r
+\r
+    abstract public V Map(T item);\r
+\r
+    public MappedCollectionValue(ICollectionValue<T> collectionvalue)\r
+    {\r
+      this.collectionvalue = collectionvalue;\r
+    }\r
+\r
+    public override V Choose() { return Map(collectionvalue.Choose()); }\r
+\r
+    public override bool IsEmpty { get { return collectionvalue.IsEmpty; } }\r
+\r
+    public override int Count { get { return collectionvalue.Count; } }\r
+\r
+    public override Speed CountSpeed { get { return collectionvalue.CountSpeed; } }\r
+\r
+    public override SCG.IEnumerator<V> GetEnumerator()\r
+    {\r
+      foreach (T item in collectionvalue)\r
+        yield return Map(item);\r
+    }\r
+  }\r
+  \r
+  class MultiplicityOne<K> : MappedCollectionValue<K, KeyValuePair<K, int>>\r
+  {\r
+    public MultiplicityOne(ICollectionValue<K> coll):base(coll) { }\r
+    public override KeyValuePair<K, int> Map(K k) { return new KeyValuePair<K, int>(k, 1); }\r
+  }\r
+\r
+  class DropMultiplicity<K> : MappedCollectionValue<KeyValuePair<K, int>, K>\r
+  {\r
+    public DropMultiplicity(ICollectionValue<KeyValuePair<K, int>> coll):base(coll) { }\r
+    public override K Map(KeyValuePair<K, int> kvp) { return kvp.Key; }\r
+  }\r
+  \r
+  abstract class MappedDirectedEnumerable<T, V> : EnumerableBase<V>, IDirectedEnumerable<V>\r
+  {\r
+    IDirectedEnumerable<T> directedenumerable;\r
+\r
+    abstract public V Map(T item);\r
+\r
+    public MappedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)\r
+    {\r
+      this.directedenumerable = directedenumerable;\r
+    }\r
+\r
+    public IDirectedEnumerable<V> Backwards()\r
+    {\r
+      MappedDirectedEnumerable<T, V> retval = (MappedDirectedEnumerable<T, V>)MemberwiseClone();\r
+      retval.directedenumerable = directedenumerable.Backwards();\r
+      return retval;\r
+      //If we made this classs non-abstract we could do\r
+      //return new MappedDirectedCollectionValue<T,V>(directedcollectionvalue.Backwards());;\r
+    }\r
+\r
+\r
+    public override SCG.IEnumerator<V> GetEnumerator()\r
+    {\r
+      foreach (T item in directedenumerable)\r
+        yield return Map(item);\r
+    }\r
+\r
+    public EnumerationDirection Direction\r
+    {\r
+      get { return directedenumerable.Direction; }\r
+    }\r
+  }\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Random.cs b/mcs/class/Mono.C5/C5/Random.cs
new file mode 100644 (file)
index 0000000..28df260
--- /dev/null
@@ -0,0 +1,172 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+using System;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// A modern random number generator based on G. Marsaglia: \r
+  /// Seeds for Random Number Generators, Communications of the\r
+  /// ACM 46, 5 (May 2003) 90-93; and a posting by Marsaglia to \r
+  /// comp.lang.c on 2003-04-03.\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
+    /// <exception cref="ArgumentException">If max is negative</exception>\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 ArgumentException("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
+    /// <exception cref="ArgumentException">If max is less than min</exception>\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 ArgumentException("min must be less than or equal to max");\r
+\r
+      return min + (int)(Cmwc() / 4294967296.0 * (max - min));\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
+    /// <exception cref="ArgumentException">If seed is zero</exception>\r
+    /// <param name="seed">The seed</param>\r
+    public C5Random(long seed)\r
+    {\r
+      if (seed == 0)\r
+        throw new ArgumentException("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
+    /// <summary>\r
+    /// Create a random number generator with a specified internal start state.\r
+    /// </summary>\r
+    /// <exception cref="ArgumentException">If Q is not of length exactly 16</exception>\r
+    /// <param name="Q">The start state. Must be a collection of random bits given by an array of exactly 16 uints.</param>\r
+    public C5Random(uint[] Q)\r
+    {\r
+      if (Q.Length != 16)\r
+        throw new ArgumentException("Q must have length 16, was " + Q.Length);\r
+      Array.Copy(Q, this.Q, 16);\r
+    }\r
+  }\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/Records.cs b/mcs/class/Mono.C5/C5/Records.cs
new file mode 100644 (file)
index 0000000..47adaa9
--- /dev/null
@@ -0,0 +1,510 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+\r
+namespace C5\r
+{\r
+  struct RecConst\r
+  {\r
+    public const int HASHFACTOR = 387281;\r
+  }\r
+  /// <summary>\r
+  /// A generic record type with two fields. \r
+  /// <para>\r
+  /// Equality is defined field by field, using the <code>Equals</code> method \r
+  /// inherited from <code>System.Object</code> (i.e. using <see cref="T:C5.NaturalEqualityComparer`1"/>).\r
+  /// </para>\r
+  /// <para>\r
+  /// This type is similar to <see cref="T:C5.KeyValuePair`2"/>, but the latter\r
+  /// uses <see cref="P:C5.EqualityComparer`1.Default"/> to define field equality instead of <see cref="T:C5.NaturalEqualityComparer`1"/>.\r
+  /// </para>\r
+  /// </summary>\r
+  /// <typeparam name="T1"></typeparam>\r
+  /// <typeparam name="T2"></typeparam>\r
+  public struct Rec<T1, T2> : IEquatable<Rec<T1, T2>>, IShowable\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T1 X1;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T2 X2;\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="x1"></param>\r
+    /// <param name="x2"></param>\r
+    [Tested]\r
+    public Rec(T1 x1, T2 x2)\r
+    {\r
+      this.X1 = x1; this.X2 = x2;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="other"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public bool Equals(Rec<T1, T2> other)\r
+    {\r
+      return\r
+        (X1 == null ? other.X1 == null : X1.Equals(other.X1)) &&\r
+        (X2 == null ? other.X2 == null : X2.Equals(other.X2))\r
+        ;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="obj"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override bool Equals(object obj)\r
+    {\r
+      return obj is Rec<T1, T2> ? Equals((Rec<T1, T2>)obj) : false;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="record1"></param>\r
+    /// <param name="record2"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public static bool operator ==(Rec<T1, T2> record1, Rec<T1, T2> record2)\r
+    {\r
+      return record1.Equals(record2);\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="record1"></param>\r
+    /// <param name="record2"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public static bool operator !=(Rec<T1, T2> record1, Rec<T1, T2> record2)\r
+    {\r
+      return !record1.Equals(record2);\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override int GetHashCode()\r
+    {\r
+      //TODO: don't use 0 as hashcode for null, but something else!\r
+      int hashcode = X1 == null ? 0 : X1.GetHashCode();\r
+      hashcode = hashcode * RecConst.HASHFACTOR + (X2 == null ? 0 : X2.GetHashCode());\r
+      return hashcode;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return String.Format("({0}, {1})", X1, X2);\r
+    }\r
+\r
+    #region IShowable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      bool incomplete = true;\r
+      stringbuilder.Append("(");\r
+      rest -= 2;\r
+      try\r
+      {\r
+        if (incomplete = !Showing.Show(X1, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+        stringbuilder.Append(", ");\r
+        rest -= 2;\r
+        if (incomplete = !Showing.Show(X2, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+      }\r
+      finally\r
+      {\r
+        if (incomplete)\r
+        {\r
+          stringbuilder.Append("...");\r
+          rest -= 3;\r
+        }\r
+        stringbuilder.Append(")");\r
+      }\r
+      return true;\r
+    }\r
+    #endregion\r
+\r
+    #region IFormattable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public string ToString(string format, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowString(this, format, formatProvider);\r
+    }\r
+\r
+    #endregion\r
+  }\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="T1"></typeparam>\r
+  /// <typeparam name="T2"></typeparam>\r
+  /// <typeparam name="T3"></typeparam>\r
+  public struct Rec<T1, T2, T3> : IEquatable<Rec<T1, T2, T3>>, IShowable\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T1 X1;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T2 X2;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T3 X3;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="x1"></param>\r
+    /// <param name="x2"></param>\r
+    /// <param name="x3"></param>\r
+    [Tested]\r
+    public Rec(T1 x1, T2 x2, T3 x3)\r
+    {\r
+      this.X1 = x1; this.X2 = x2; this.X3 = x3;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="other"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public bool Equals(Rec<T1, T2, T3> other)\r
+    {\r
+      return\r
+        (X1 == null ? other.X1 == null : X1.Equals(other.X1)) &&\r
+        (X2 == null ? other.X2 == null : X2.Equals(other.X2)) &&\r
+        (X3 == null ? other.X3 == null : X3.Equals(other.X3))\r
+        ;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="obj"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override bool Equals(object obj)\r
+    {\r
+      return obj is Rec<T1, T2, T3> ? Equals((Rec<T1, T2, T3>)obj) : false;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="record1"></param>\r
+    /// <param name="record2"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public static bool operator ==(Rec<T1, T2, T3> record1, Rec<T1, T2, T3> record2)\r
+    {\r
+      return record1.Equals(record2);\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="record1"></param>\r
+    /// <param name="record2"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public static bool operator !=(Rec<T1, T2, T3> record1, Rec<T1, T2, T3> record2)\r
+    {\r
+      return !record1.Equals(record2);\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override int GetHashCode()\r
+    {\r
+      //TODO: don't use 0 as hashcode for null, but something else!\r
+      int hashcode = X1 == null ? 0 : X1.GetHashCode();\r
+      hashcode = hashcode * RecConst.HASHFACTOR + (X2 == null ? 0 : X2.GetHashCode());\r
+      hashcode = hashcode * RecConst.HASHFACTOR + (X3 == null ? 0 : X3.GetHashCode());\r
+      return hashcode;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return String.Format("({0}, {1}, {2})", X1, X2, X3);\r
+    }\r
+    #region IShowable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      bool incomplete = true;\r
+      stringbuilder.Append("(");\r
+      rest -= 2;\r
+      try\r
+      {\r
+        if (incomplete = !Showing.Show(X1, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+        stringbuilder.Append(", ");\r
+        rest -= 2;\r
+        if (incomplete = !Showing.Show(X2, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+        stringbuilder.Append(", ");\r
+        rest -= 2;\r
+        if (incomplete = !Showing.Show(X3, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+      }\r
+      finally\r
+      {\r
+        if (incomplete)\r
+        {\r
+          stringbuilder.Append("...");\r
+          rest -= 3;\r
+        }\r
+        stringbuilder.Append(")");\r
+      }\r
+      return true;\r
+    }\r
+    #endregion\r
+\r
+    #region IFormattable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public string ToString(string format, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowString(this, format, formatProvider);\r
+    }\r
+\r
+    #endregion\r
+  }\r
+\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="T1"></typeparam>\r
+  /// <typeparam name="T2"></typeparam>\r
+  /// <typeparam name="T3"></typeparam>\r
+  /// <typeparam name="T4"></typeparam>\r
+  public struct Rec<T1, T2, T3, T4> : IEquatable<Rec<T1, T2, T3, T4>>, IShowable\r
+  {\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T1 X1;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T2 X2;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T3 X3;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public readonly T4 X4;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="x1"></param>\r
+    /// <param name="x2"></param>\r
+    /// <param name="x3"></param>\r
+    /// <param name="x4"></param>\r
+    [Tested]\r
+    public Rec(T1 x1, T2 x2, T3 x3, T4 x4)\r
+    {\r
+      this.X1 = x1; this.X2 = x2; this.X3 = x3; this.X4 = x4;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="other"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public bool Equals(Rec<T1, T2, T3, T4> other)\r
+    {\r
+      return\r
+        (X1 == null ? other.X1 == null : X1.Equals(other.X1)) &&\r
+        (X2 == null ? other.X2 == null : X2.Equals(other.X2)) &&\r
+        (X3 == null ? other.X3 == null : X3.Equals(other.X3)) &&\r
+        (X4 == null ? other.X4 == null : X4.Equals(other.X4))\r
+        ;\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="obj"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override bool Equals(object obj)\r
+    {\r
+      return obj is Rec<T1, T2, T3, T4> ? Equals((Rec<T1, T2, T3, T4>)obj) : false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="record1"></param>\r
+    /// <param name="record2"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public static bool operator ==(Rec<T1, T2, T3, T4> record1, Rec<T1, T2, T3, T4> record2)\r
+    {\r
+      return record1.Equals(record2);\r
+    }\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="record1"></param>\r
+    /// <param name="record2"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public static bool operator !=(Rec<T1, T2, T3, T4> record1, Rec<T1, T2, T3, T4> record2)\r
+    {\r
+      return !record1.Equals(record2);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override int GetHashCode()\r
+    {\r
+      //TODO: don't use 0 as hashcode for null, but something else!\r
+      int hashcode = X1 == null ? 0 : X1.GetHashCode();\r
+      hashcode = hashcode * RecConst.HASHFACTOR + (X2 == null ? 0 : X2.GetHashCode());\r
+      hashcode = hashcode * RecConst.HASHFACTOR + (X3 == null ? 0 : X3.GetHashCode());\r
+      hashcode = hashcode * RecConst.HASHFACTOR + (X4 == null ? 0 : X4.GetHashCode());\r
+      return hashcode;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString()\r
+    {\r
+      return String.Format("({0}, {1}, {2}, {3})", X1, X2, X3, X4);\r
+    }\r
+    #region IShowable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      bool incomplete = true;\r
+      stringbuilder.Append("(");\r
+      rest -= 2;\r
+      try\r
+      {\r
+        if (incomplete = !Showing.Show(X1, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+        stringbuilder.Append(", ");\r
+        rest -= 2;\r
+        if (incomplete = !Showing.Show(X2, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+        stringbuilder.Append(", ");\r
+        rest -= 2;\r
+        if (incomplete = !Showing.Show(X3, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+        stringbuilder.Append(", ");\r
+        rest -= 2;\r
+        if (incomplete = !Showing.Show(X4, stringbuilder, ref rest, formatProvider))\r
+          return false;\r
+      }\r
+      finally\r
+      {\r
+        if (incomplete)\r
+        {\r
+          stringbuilder.Append("...");\r
+          rest -= 3;\r
+        }\r
+        stringbuilder.Append(")");\r
+      }\r
+      return true;\r
+    }\r
+    #endregion\r
+\r
+    #region IFormattable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public string ToString(string format, IFormatProvider formatProvider)\r
+    {\r
+      return Showing.ShowString(this, format, formatProvider);\r
+    }\r
+\r
+    #endregion\r
+  }\r
+}\r
diff --git a/mcs/class/Mono.C5/C5/Sorting.cs b/mcs/class/Mono.C5/C5/Sorting.cs
new file mode 100644 (file)
index 0000000..d40003d
--- /dev/null
@@ -0,0 +1,239 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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
+using System;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+namespace C5\r
+{\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
+    Sorting() { }\r
+\r
+    /// <summary>\r
+    /// Sort part of array in place using IntroSort\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>\r
+    /// and <code>count</code> arguments does not describe a valid range.</exception>\r
+    /// <param name="array">Array to sort</param>\r
+    /// <param name="start">Index of first position to sort</param>\r
+    /// <param name="count">Number of elements to sort</param>\r
+    /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>\r
+    [Tested]\r
+    public static void IntroSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)\r
+    {\r
+      if (start < 0 || count < 0 || start + count > array.Length)\r
+        throw new ArgumentOutOfRangeException();\r
+      new Sorter<T>(array, comparer).IntroSort(start, start + count);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Sort an array in place using IntroSort and default comparer\r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">If T is not comparable</exception>\r
+    /// <param name="array">Array to sort</param>\r
+    [Tested]\r
+    public static void IntroSort<T>(T[] array)\r
+    {\r
+      new Sorter<T>(array, Comparer<T>.Default).IntroSort(0, array.Length);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Sort part of array in place using Insertion Sort\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>\r
+    /// and <code>count</code> arguments does not describe a valid range.</exception>\r
+    /// <param name="array">Array to sort</param>\r
+    /// <param name="start">Index of first position to sort</param>\r
+    /// <param name="count">Number of elements to sort</param>\r
+    /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>\r
+    [Tested]\r
+    public static void InsertionSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)\r
+    {\r
+      if (start < 0 || count < 0 || start + count > array.Length)\r
+        throw new ArgumentOutOfRangeException();\r
+      new Sorter<T>(array, comparer).InsertionSort(start, start + count);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Sort part of array in place using Heap Sort\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>\r
+    /// and <code>count</code> arguments does not describe a valid range.</exception>\r
+    /// <param name="array">Array to sort</param>\r
+    /// <param name="start">Index of first position to sort</param>\r
+    /// <param name="count">Number of elements to sort</param>\r
+    /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>\r
+    [Tested]\r
+    public static void HeapSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)\r
+    {\r
+      if (start < 0 || count < 0 || start + count > array.Length)\r
+        throw new ArgumentOutOfRangeException();\r
+      new Sorter<T>(array, comparer).HeapSort(start, start + count);\r
+    }\r
+\r
+\r
+    class Sorter<T>\r
+    {\r
+      T[] a;\r
+\r
+      SCG.IComparer<T> c;\r
+\r
+\r
+      internal Sorter(T[] a, SCG.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
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/ViewSupport.cs b/mcs/class/Mono.C5/C5/ViewSupport.cs
new file mode 100644 (file)
index 0000000..ca2a6d7
--- /dev/null
@@ -0,0 +1,101 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// Characterize the mutual position of some view B (other) relative to view A (this)\r
+  /// </summary>\r
+  enum MutualViewPosition\r
+  {\r
+    /// <summary>\r
+    /// B contains A(this)\r
+    /// </summary>\r
+    Contains,\r
+    /// <summary>\r
+    /// B is containd in A(this), but not vice versa\r
+    /// </summary>\r
+    ContainedIn,\r
+    /// <summary>\r
+    /// A and B does not overlap\r
+    /// </summary>\r
+    NonOverlapping,\r
+    /// <summary>\r
+    /// A and B overlap, but neither is contained in the other\r
+    /// </summary>\r
+    Overlapping\r
+  }\r
+\r
+  #region View List Nested class\r
+  /// <summary>\r
+  /// This class is shared between the linked list and array list implementations.\r
+  /// </summary>\r
+  /// <typeparam name="V"></typeparam>\r
+  [Serializable]\r
+  class WeakViewList<V> where V : class\r
+  {\r
+    Node start;\r
+    [Serializable]\r
+    internal class Node\r
+    {\r
+      internal WeakReference weakview; internal Node prev, next;\r
+      internal Node(V view) { weakview = new WeakReference(view); }\r
+    }\r
+    internal Node Add(V view)\r
+    {\r
+      Node newNode = new Node(view);\r
+      if (start != null) { start.prev = newNode; newNode.next = start; }\r
+      start = newNode;\r
+      return newNode;\r
+    }\r
+    internal void Remove(Node n)\r
+    {\r
+      if (n == start) { start = start.next; if (start != null) start.prev = null; }\r
+      else { n.prev.next = n.next; if (n.next != null) n.next.prev = n.prev; }\r
+    }\r
+    /// <summary>\r
+    /// Note that it is safe to call views.Remove(view.myWeakReference) if view\r
+    /// is the currently yielded object\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public SCG.IEnumerator<V> GetEnumerator()\r
+    {\r
+      Node n = start;\r
+      while (n != null)\r
+      {\r
+        //V view = n.weakview.Target as V; //This provokes a bug in the beta1 verifyer\r
+        object o = n.weakview.Target;\r
+        V view = o is V ? (V)o : null;\r
+        if (view == null)\r
+          Remove(n);\r
+        else\r
+          yield return view;\r
+        n = n.next;\r
+      }\r
+    }\r
+  }\r
+\r
+  #endregion\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/WrappedArray.cs b/mcs/class/Mono.C5/C5/WrappedArray.cs
new file mode 100644 (file)
index 0000000..b0aac9e
--- /dev/null
@@ -0,0 +1,871 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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.Text;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// An advanced interface to operations on an array. The array is viewed as an \r
+  /// <see cref="T:C5.IList`1"/> of fixed size, and so all operations that would change the\r
+  /// size of the array will be invalid (and throw <see cref="T:C5.FixedSizeCollectionException"/>\r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class WrappedArray<T> : IList<T>\r
+  {\r
+    class InnerList : ArrayList<T>\r
+    {\r
+      internal InnerList(T[] array) { this.array = array; size = array.Length; }\r
+    }\r
+    ArrayList<T> innerlist;\r
+    //TODO: remember a ref to the wrapped array in WrappedArray to save a little on indexing?\r
+    WrappedArray<T> underlying;\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="wrappedarray"></param>\r
+    public WrappedArray(T[] wrappedarray) { innerlist = new InnerList(wrappedarray); }\r
+\r
+    //for views\r
+    WrappedArray(ArrayList<T> arraylist, WrappedArray<T> underlying) { innerlist = arraylist; this.underlying = underlying; }\r
+\r
+    #region IList<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public T First { get { return innerlist.First; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public T Last { get { return innerlist.Last; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="index"></param>\r
+    /// <returns></returns>\r
+    public T this[int index]\r
+    {\r
+      get { return innerlist[index]; }\r
+      set { innerlist[index] = value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="filter"></param>\r
+    /// <returns></returns>\r
+    public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="V"></typeparam>\r
+    /// <param name="mapper"></param>\r
+    /// <returns></returns>\r
+    public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map<V>(mapper); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="V"></typeparam>\r
+    /// <param name="mapper"></param>\r
+    /// <param name="equalityComparer"></param>\r
+    /// <returns></returns>\r
+    public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer) { return innerlist.Map<V>(mapper, equalityComparer); }\r
+\r
+    /// <summary>\r
+    /// ???? should we throw NotRelevantException\r
+    /// </summary>\r
+    /// <value></value>\r
+    public bool FIFO\r
+    {\r
+      get { throw new FixedSizeCollectionException(); }\r
+      set { throw new FixedSizeCollectionException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public virtual bool IsFixedSize\r
+    {\r
+      get { return true; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="index"></param>\r
+    /// <param name="item"></param>\r
+    public void Insert(int index, T item)\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="pointer"></param>\r
+    /// <param name="item"></param>\r
+    public void Insert(IList<T> pointer, T item)\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    public void InsertFirst(T item)\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    public void InsertLast(T item)\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="i"></param>\r
+    /// <param name="items"></param>\r
+    public void InsertAll<U>(int i, System.Collections.Generic.IEnumerable<U> items) where U : T\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public T Remove()\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public T RemoveFirst()\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public T RemoveLast()\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="start"></param>\r
+    /// <param name="count"></param>\r
+    /// <returns></returns>\r
+    public IList<T> View(int start, int count)\r
+    {\r
+      return new WrappedArray<T>((ArrayList<T>)innerlist.View(start, count), underlying ?? this);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public IList<T> ViewOf(T item)\r
+    {\r
+      return new WrappedArray<T>((ArrayList<T>)innerlist.ViewOf(item), underlying ?? this);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public IList<T> LastViewOf(T item)\r
+    {\r
+      return new WrappedArray<T>((ArrayList<T>)innerlist.LastViewOf(item), underlying ?? this);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public IList<T> Underlying { get { return underlying; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public int Offset { get { return innerlist.Offset; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public bool IsValid { get { return innerlist.IsValid; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <returns></returns>\r
+    public IList<T> Slide(int offset) { return innerlist.Slide(offset); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <param name="size"></param>\r
+    /// <returns></returns>\r
+    public IList<T> Slide(int offset, int size) { return innerlist.Slide(offset, size); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <returns></returns>\r
+    public bool TrySlide(int offset) { return innerlist.TrySlide(offset); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <param name="size"></param>\r
+    /// <returns></returns>\r
+    public bool TrySlide(int offset, int size) { return innerlist.TrySlide(offset, size); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="otherView"></param>\r
+    /// <returns></returns>\r
+    public IList<T> Span(IList<T> otherView) { return innerlist.Span(((WrappedArray<T>)otherView).innerlist); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public void Reverse() { innerlist.Reverse(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public bool IsSorted() { return innerlist.IsSorted(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="comparer"></param>\r
+    /// <returns></returns>\r
+    public bool IsSorted(SCG.IComparer<T> comparer) { return innerlist.IsSorted(comparer); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public void Sort() { innerlist.Sort(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="comparer"></param>\r
+    public void Sort(SCG.IComparer<T> comparer) { innerlist.Sort(comparer); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public void Shuffle() { innerlist.Shuffle(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="rnd"></param>\r
+    public void Shuffle(Random rnd) { innerlist.Shuffle(rnd); }\r
+\r
+    #endregion\r
+\r
+    #region IIndexed<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public Speed IndexingSpeed { get { return Speed.Constant; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="start"></param>\r
+    /// <param name="count"></param>\r
+    /// <returns></returns>\r
+    public IDirectedCollectionValue<T> this[int start, int count] { get { return innerlist[start, count]; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int IndexOf(T item) { return innerlist.IndexOf(item); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <returns></returns>\r
+    public int FindIndex(Fun<T, bool> predicate) { return innerlist.FindIndex(predicate); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <returns></returns>\r
+    public int FindLastIndex(Fun<T, bool> predicate) { return innerlist.FindLastIndex(predicate); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="i"></param>\r
+    /// <returns></returns>\r
+    public T RemoveAt(int i) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="start"></param>\r
+    /// <param name="count"></param>\r
+    public void RemoveInterval(int start, int count) { throw new FixedSizeCollectionException(); }\r
+\r
+    #endregion\r
+\r
+    #region ISequenced<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public int GetSequencedHashCode() { return innerlist.GetSequencedHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="that"></param>\r
+    /// <returns></returns>\r
+    public bool SequencedEquals(ISequenced<T> that) { return innerlist.SequencedEquals(that); }\r
+\r
+    #endregion\r
+\r
+    #region ICollection<T> Members\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public Speed ContainsSpeed { get { return Speed.Linear; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public int GetUnsequencedHashCode() { return innerlist.GetUnsequencedHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="that"></param>\r
+    /// <returns></returns>\r
+    public bool UnsequencedEquals(ICollection<T> that) { return innerlist.UnsequencedEquals(that); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool Contains(T item) { return innerlist.Contains(item); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int ContainsCount(T item) { return innerlist.ContainsCount(item); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public ICollectionValue<T> UniqueItems() { return innerlist.UniqueItems(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return innerlist.ItemMultiplicities(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    /// <returns></returns>\r
+    public bool ContainsAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T\r
+    { return innerlist.ContainsAll(items); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool Find(ref T item) { return innerlist.Find(ref item); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool FindOrAdd(ref T item) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool Update(T item) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public bool Update(T item, out T olditem) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool UpdateOrAdd(T item) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public bool UpdateOrAdd(T item, out T olditem) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool Remove(T item) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="removeditem"></param>\r
+    /// <returns></returns>\r
+    public bool Remove(T item, out T removeditem) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    public void RemoveAllCopies(T item) { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    public void RemoveAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public void Clear() { throw new FixedSizeCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    public void RetainAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }\r
+\r
+    #endregion\r
+\r
+    #region IExtensible<T> Members\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public object SyncRoot { get { return innerlist.SyncRoot; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public bool IsReadOnly { get { return true; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public bool AllowsDuplicates\r
+    {\r
+      get { return true; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public SCG.IEqualityComparer<T> EqualityComparer { get { return innerlist.EqualityComparer; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public bool DuplicatesByCounting\r
+    {\r
+      get { return false; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool Add(T item)\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    public void AddAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T\r
+    {\r
+      throw new FixedSizeCollectionException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public bool Check()\r
+    {\r
+      return innerlist.Check() && (underlying == null || underlying.innerlist == innerlist.Underlying);\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICollectionValue<T> Members\r
+    /// <summary>\r
+    /// No listeners may be installed\r
+    /// </summary>\r
+    /// <value>0</value>\r
+    public virtual EventTypeEnum ListenableEvents { get { return 0; } }\r
+\r
+    /// <summary>\r
+    /// No listeners ever installed\r
+    /// </summary>\r
+    /// <value>0</value>\r
+    public virtual EventTypeEnum ActiveEvents { get { return 0; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public event CollectionChangedHandler<T> CollectionChanged\r
+    {\r
+      add { throw new UnlistenableEventException(); }\r
+      remove { throw new UnlistenableEventException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public event CollectionClearedHandler<T> CollectionCleared\r
+    {\r
+      add { throw new UnlistenableEventException(); }\r
+      remove { throw new UnlistenableEventException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public event ItemsAddedHandler<T> ItemsAdded\r
+    {\r
+      add { throw new UnlistenableEventException(); }\r
+      remove { throw new UnlistenableEventException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public event ItemInsertedHandler<T> ItemInserted\r
+    {\r
+      add { throw new UnlistenableEventException(); }\r
+      remove { throw new UnlistenableEventException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public event ItemsRemovedHandler<T> ItemsRemoved\r
+    {\r
+      add { throw new UnlistenableEventException(); }\r
+      remove { throw new UnlistenableEventException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public event ItemRemovedAtHandler<T> ItemRemovedAt\r
+    {\r
+      add { throw new UnlistenableEventException(); }\r
+      remove { throw new UnlistenableEventException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public bool IsEmpty { get { return innerlist.IsEmpty; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public int Count { get { return innerlist.Count; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public Speed CountSpeed { get { return innerlist.CountSpeed; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="array"></param>\r
+    /// <param name="index"></param>\r
+    public void CopyTo(T[] array, int index) { innerlist.CopyTo(array, index); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public T[] ToArray() { return innerlist.ToArray(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="action"></param>\r
+    public void Apply(Act<T> action) { innerlist.Apply(action); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <returns></returns>\r
+    public bool Exists(Fun<T, bool> predicate) { return innerlist.Exists(predicate); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool Find(Fun<T, bool> predicate, out T item) { return innerlist.Find(predicate, out item); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <returns></returns>\r
+    public bool All(Fun<T, bool> predicate) { return innerlist.All(predicate); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public T Choose() { return innerlist.Choose(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="filter"></param>\r
+    /// <returns></returns>\r
+    public SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return innerlist.Filter(filter); }\r
+\r
+    #endregion\r
+\r
+    #region IEnumerable<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public SCG.IEnumerator<T> GetEnumerator() { return innerlist.GetEnumerator(); }\r
+    #endregion\r
+\r
+    #region IShowable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="rest"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    { return innerlist.Show(stringbuilder, ref  rest, formatProvider); }\r
+\r
+    #endregion\r
+\r
+    #region IFormattable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override string ToString() { return innerlist.ToString(); }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public virtual string ToString(string format, IFormatProvider formatProvider) { return innerlist.ToString(format, formatProvider); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedCollectionValue<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public IDirectedCollectionValue<T> Backwards() { return innerlist.Backwards(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public bool FindLast(Fun<T, bool> predicate, out T item) { return innerlist.FindLast(predicate, out item); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public EnumerationDirection Direction { get { return EnumerationDirection.Forwards; } }\r
+\r
+    #endregion\r
+\r
+    #region IDisposable Members\r
+\r
+    /// <summary>\r
+    /// Dispose this if a view else operation is illegal \r
+    /// </summary>\r
+    /// <exception cref="FixedSizeCollectionException">If not a view</exception>\r
+    public void Dispose()\r
+    {\r
+      if (underlying == null)\r
+        throw new FixedSizeCollectionException();\r
+      else\r
+        innerlist.Dispose();\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this WrappedArray.\r
+    /// \r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      return new WrappedArray<T>(innerlist.ToArray());\r
+    }\r
+\r
+    #endregion\r
+\r
+\r
+\r
+    #region IEnumerable Members\r
+\r
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
+    {\r
+      throw new Exception("The method or operation is not implemented.");\r
+    }\r
+\r
+    #endregion\r
+  }\r
+}
\ No newline at end of file
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..9d594e0
--- /dev/null
@@ -0,0 +1,2233 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// A read-only wrapper class for a generic enumerator\r
+  /// </summary>\r
+  public class GuardedEnumerator<T> : SCG.IEnumerator<T>\r
+  {\r
+    #region Fields\r
+\r
+    SCG.IEnumerator<T> enumerator;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Create a wrapper around a generic enumerator\r
+    /// </summary>\r
+    /// <param name="enumerator">The enumerator to wrap</param>\r
+    public GuardedEnumerator(SCG.IEnumerator<T> enumerator)\r
+    { this.enumerator = enumerator; }\r
+\r
+    #endregion\r
+\r
+    #region IEnumerator<T> Members\r
+\r
+    /// <summary>\r
+    /// Move wrapped enumerator to next item, or the first item if\r
+    /// this is the first call to MoveNext. \r
+    /// </summary>\r
+    /// <returns>True if enumerator is valid now</returns>\r
+    public bool MoveNext() { return enumerator.MoveNext(); }\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 wrapped enumerator.</value>\r
+    public T Current { get { return enumerator.Current; } }\r
+\r
+    #endregion\r
+\r
+    #region IDisposable Members\r
+\r
+    //TODO: consider possible danger of calling through to Dispose. \r
+    /// <summary>\r
+    /// Dispose wrapped enumerator.\r
+    /// </summary>\r
+    public void Dispose() { enumerator.Dispose(); }\r
+\r
+    #endregion\r
+\r
+\r
+    #region IEnumerator Members\r
+\r
+    object System.Collections.IEnumerator.Current\r
+    {\r
+      get { return enumerator.Current; }\r
+    }\r
+\r
+    void System.Collections.IEnumerator.Reset()\r
+    {\r
+      enumerator.Reset();\r
+    }\r
+\r
+    #endregion\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper class for a generic enumerable\r
+  ///\r
+  /// <i>This is mainly interesting as a base of other guard classes</i>\r
+  /// </summary>\r
+  public class GuardedEnumerable<T> : SCG.IEnumerable<T>\r
+  {\r
+    #region Fields\r
+\r
+    SCG.IEnumerable<T> enumerable;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap an enumerable in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="enumerable">The enumerable to wrap</param>\r
+    public GuardedEnumerable(SCG.IEnumerable<T> enumerable)\r
+    { this.enumerable = enumerable; }\r
+\r
+    #endregion\r
+\r
+    #region SCG.IEnumerable<T> Members\r
+\r
+    /// <summary>\r
+    /// Get an enumerator from the wrapped enumerable\r
+    /// </summary>\r
+    /// <returns>The enumerator (itself wrapped)</returns>\r
+    public SCG.IEnumerator<T> GetEnumerator()\r
+    { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }\r
+\r
+    #endregion\r
+\r
+    #region IEnumerable Members\r
+\r
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
+    {\r
+      return GetEnumerator();\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a generic directed enumerable\r
+  ///\r
+  /// <i>This is mainly interesting as a base of other guard classes</i>\r
+  /// </summary>\r
+  public class GuardedDirectedEnumerable<T> : GuardedEnumerable<T>, IDirectedEnumerable<T>\r
+  {\r
+    #region Fields\r
+\r
+    IDirectedEnumerable<T> directedenumerable;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a directed enumerable in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="directedenumerable">the collection to wrap</param>\r
+    public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)\r
+      : base(directedenumerable)\r
+    { this.directedenumerable = directedenumerable; }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    /// <summary>\r
+    /// Get a enumerable that enumerates the wrapped collection in the opposite direction\r
+    /// </summary>\r
+    /// <returns>The mirrored enumerable</returns>\r
+    public IDirectedEnumerable<T> Backwards()\r
+    { return new GuardedDirectedEnumerable<T>(directedenumerable.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
+    public EnumerationDirection Direction\r
+    { get { return directedenumerable.Direction; } }\r
+\r
+    #endregion\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for an ICollectionValue&lt;T&gt;\r
+  ///\r
+  /// <i>This is mainly interesting as a base of other guard classes</i>\r
+  /// </summary>\r
+  public class GuardedCollectionValue<T> : GuardedEnumerable<T>, ICollectionValue<T>\r
+  {\r
+    #region Events\r
+    /// <summary>\r
+    /// The ListenableEvents value of the wrapped collection\r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual EventTypeEnum ListenableEvents { get { return collectionvalue.ListenableEvents; } }\r
+\r
+    /// <summary>\r
+    /// The ActiveEvents value of the wrapped collection\r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual EventTypeEnum ActiveEvents { get { return collectionvalue.ActiveEvents; } }\r
+\r
+    ProxyEventBlock<T> eventBlock;\r
+    /// <summary>\r
+    /// The change event. Will be raised for every change operation on the collection.\r
+    /// </summary>\r
+    public event CollectionChangedHandler<T> CollectionChanged\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionChanged += value; }\r
+      remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The change event. Will be raised for every change operation on the collection.\r
+    /// </summary>\r
+    public event CollectionClearedHandler<T> CollectionCleared\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionCleared += value; }\r
+      remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The item added  event. Will be raised for every individual addition to the collection.\r
+    /// </summary>\r
+    public event ItemsAddedHandler<T> ItemsAdded\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsAdded += value; }\r
+      remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The item added  event. Will be raised for every individual addition to the collection.\r
+    /// </summary>\r
+    public event ItemInsertedHandler<T> ItemInserted\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemInserted += value; }\r
+      remove { if (eventBlock != null) eventBlock.ItemInserted -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The item removed event. Will be raised for every individual removal from the collection.\r
+    /// </summary>\r
+    public event ItemsRemovedHandler<T> ItemsRemoved\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsRemoved += value; }\r
+      remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// The item removed event. Will be raised for every individual removal from the collection.\r
+    /// </summary>\r
+    public event ItemRemovedAtHandler<T> ItemRemovedAt\r
+    {\r
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemRemovedAt += value; }\r
+      remove { if (eventBlock != null) eventBlock.ItemRemovedAt -= value; }\r
+    }\r
+    #endregion\r
+\r
+    #region Fields\r
+\r
+    ICollectionValue<T> collectionvalue;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="collectionvalue">the collection to wrap</param>\r
+    public GuardedCollectionValue(ICollectionValue<T> collectionvalue)\r
+      : base(collectionvalue)\r
+    { this.collectionvalue = collectionvalue; }\r
+\r
+    #endregion\r
+\r
+    #region ICollection<T> Members\r
+\r
+    /// <summary>\r
+    /// Get the size of the wrapped collection\r
+    /// </summary>\r
+    /// <value>The size</value>\r
+    public virtual bool IsEmpty { get { return collectionvalue.IsEmpty; } }\r
+\r
+    /// <summary>\r
+    /// Get the size of the wrapped collection\r
+    /// </summary>\r
+    /// <value>The size</value>\r
+    public virtual int Count { get { return collectionvalue.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 virtual Speed CountSpeed { get { return collectionvalue.CountSpeed; } }\r
+\r
+    /// <summary>\r
+    /// Copy the items of the wrapped collection to an array\r
+    /// </summary>\r
+    /// <param name="a">The array</param>\r
+    /// <param name="i">Starting offset</param>\r
+    public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); }\r
+\r
+    /// <summary>\r
+    /// Create an array from the items of the wrapped collection\r
+    /// </summary>\r
+    /// <returns>The array</returns>\r
+    public virtual T[] ToArray() { return collectionvalue.ToArray(); }\r
+\r
+    /// <summary>\r
+    /// Apply a delegate to all items of the wrapped enumerable.\r
+    /// </summary>\r
+    /// <param name="a">The delegate to apply</param>\r
+    //TODO: change this to throw an exception?\r
+    public virtual void Apply(Act<T> a) { collectionvalue.Apply(a); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in the wrapped enumerable.\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
+    public virtual bool Exists(Fun<T, bool> filter) { return collectionvalue.Exists(filter); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="filter"></param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Find(Fun<T, bool> filter, out T item) { return collectionvalue.Find(filter, out item); }\r
+\r
+    /// <summary>\r
+    /// Check if all items in the wrapped enumerable 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
+    public virtual bool All(Fun<T, bool> filter) { return collectionvalue.All(filter); }\r
+\r
+    /// <summary>\r
+    /// Create an enumerable, enumerating the items of this collection that satisfies \r
+    /// a certain condition.\r
+    /// </summary>\r
+    /// <param name="filter">The T->bool filter delegate defining the condition</param>\r
+    /// <returns>The filtered enumerable</returns>\r
+    public virtual SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return collectionvalue.Filter(filter); }\r
+\r
+    /// <summary>\r
+    /// Choose some item of this collection. \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    public virtual T Choose() { return collectionvalue.Choose(); }\r
+\r
+    #endregion\r
+\r
+    #region IShowable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="stringbuilder"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <param name="rest"></param>\r
+    /// <returns></returns>\r
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)\r
+    {\r
+      return collectionvalue.Show(stringbuilder, ref rest, formatProvider);\r
+    }\r
+    #endregion\r
+\r
+    #region IFormattable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="format"></param>\r
+    /// <param name="formatProvider"></param>\r
+    /// <returns></returns>\r
+    public string ToString(string format, IFormatProvider formatProvider)\r
+    {\r
+      return collectionvalue.ToString(format, formatProvider);\r
+    }\r
+\r
+    #endregion\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a directed collection\r
+  ///\r
+  /// <i>This is mainly interesting as a base of other guard classes</i>\r
+  /// </summary>\r
+  public class GuardedDirectedCollectionValue<T> : GuardedCollectionValue<T>, IDirectedCollectionValue<T>\r
+  {\r
+    #region Fields\r
+\r
+    IDirectedCollectionValue<T> directedcollection;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a directed collection in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="directedcollection">the collection to wrap</param>\r
+    public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection)\r
+      :\r
+      base(directedcollection)\r
+    { this.directedcollection = directedcollection; }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedCollection<T> Members\r
+\r
+    /// <summary>\r
+    /// Get a collection that enumerates the wrapped collection in the opposite direction\r
+    /// </summary>\r
+    /// <returns>The mirrored collection</returns>\r
+    public virtual IDirectedCollectionValue<T> Backwards()\r
+    { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return directedcollection.FindLast(predicate, out item); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\r
+    { return 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
+    public EnumerationDirection Direction\r
+    { get { return directedcollection.Direction; } }\r
+\r
+    #endregion\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for an <see cref="T:C5.ICollection`1"/>,\r
+  /// <para>\r
+  /// <i>Suitable for wrapping hash tables, <see cref="T:C5.HashSet`1"/>\r
+  /// and <see cref="T:C5.HashBag`1"/>  </i></para>\r
+  /// </summary>\r
+  public class GuardedCollection<T> : GuardedCollectionValue<T>, ICollection<T>\r
+  {\r
+    #region Fields\r
+\r
+    ICollection<T> collection;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap an ICollection&lt;T&gt; in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="collection">the collection to wrap</param>\r
+    public GuardedCollection(ICollection<T> collection)\r
+      : base(collection)\r
+    {\r
+      this.collection = collection;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICollection<T> Members\r
+\r
+    /// <summary>\r
+    /// (This is a read-only wrapper)\r
+    /// </summary>\r
+    /// <value>True</value>\r
+    public virtual bool IsReadOnly { get { return true; } }\r
+\r
+\r
+    /// <summary> </summary>\r
+    /// <value>Speed of wrapped collection</value>\r
+    public virtual Speed ContainsSpeed { get { return collection.ContainsSpeed; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual int GetUnsequencedHashCode()\r
+    { return collection.GetUnsequencedHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="that"></param>\r
+    /// <returns></returns>\r
+    public virtual bool UnsequencedEquals(ICollection<T> that)\r
+    { return collection.UnsequencedEquals(that); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if an item is in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="item">The item</param>\r
+    /// <returns>True if found</returns>\r
+    public virtual bool Contains(T item) { return collection.Contains(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Count the number of times an item appears in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="item">The item</param>\r
+    /// <returns>The number of copies</returns>\r
+    public virtual int ContainsCount(T item) { return collection.ContainsCount(item); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<T> UniqueItems() { return new GuardedCollectionValue<T>(collection.UniqueItems()); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return new GuardedCollectionValue<KeyValuePair<T, int>>(collection.ItemMultiplicities()); }\r
+\r
+    /// <summary>\r
+    /// Check if all items in the argument is in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="items">The items</param>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if so</returns>\r
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T { return collection.ContainsAll(items); }\r
+\r
+    /// <summary> \r
+    /// Search for an item in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>\r
+    /// <returns></returns>\r
+    public virtual bool Find(ref T item) { return collection.Find(ref item); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool FindOrAdd(ref T item)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Update(T item)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Update(T item, out T olditem)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool UpdateOrAdd(T item)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool UpdateOrAdd(T item, out T olditem)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Remove(T item)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item">The value to remove.</param>\r
+    /// <param name="removeditem">The removed value.</param>\r
+    /// <returns></returns>\r
+    public virtual bool Remove(T item, out T removeditem)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    public virtual void RemoveAllCopies(T item)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    public virtual void Clear()\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    /// <summary>\r
+    /// Check  wrapped collection for internal consistency\r
+    /// </summary>\r
+    /// <returns>True if check passed</returns>\r
+    public virtual bool Check() { return collection.Check(); }\r
+\r
+    #endregion\r
+\r
+    #region IExtensible<T> Members\r
+\r
+    /// <summary> </summary>\r
+    /// <value>False if wrapped collection has set semantics</value>\r
+    public virtual bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }\r
+\r
+    //TODO: the equalityComparer should be guarded\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return collection.EqualityComparer; } }\r
+\r
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting { get { return collection.DuplicatesByCounting; } }\r
+\r
+\r
+    /// <summary> </summary>\r
+    /// <value>True if wrapped collection is empty</value>\r
+    public override bool IsEmpty { get { return collection.IsEmpty; } }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Add(T item)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      return new GuardedCollection<T>((ICollection<T>)(collection.Clone()));\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a sequenced collection\r
+  ///\r
+  /// <i>This is mainly interesting as a base of other guard classes</i>\r
+  /// </summary>\r
+  public class GuardedSequenced<T> : GuardedCollection<T>, ISequenced<T>\r
+  {\r
+    #region Fields\r
+\r
+    ISequenced<T> sequenced;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a sequenced collection in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="sorted"></param>\r
+    public GuardedSequenced(ISequenced<T> sorted) : base(sorted) { this.sequenced = sorted; }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the index of the first one.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>the index, if found, a negative value else</returns>\r
+    public int FindIndex(Fun<T, bool> predicate)\r
+    {\r
+      IIndexed<T> indexed = sequenced as IIndexed<T>;\r
+      if (indexed != null)\r
+        return indexed.FindIndex(predicate);\r
+      int index = 0;\r
+      foreach (T item in this)\r
+      {\r
+        if (predicate(item))\r
+          return index;\r
+        index++;\r
+      }\r
+      return -1;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if there exists an item  that satisfies a\r
+    /// specific predicate in this collection and return the index of the last one.\r
+    /// </summary>\r
+    /// <param name="predicate">A delegate \r
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>\r
+    /// <returns>the index, if found, a negative value else</returns>\r
+    public int FindLastIndex(Fun<T, bool> predicate)\r
+    {\r
+      IIndexed<T> indexed = sequenced as IIndexed<T>;\r
+      if (indexed != null)\r
+        return indexed.FindLastIndex(predicate);\r
+      int index = Count - 1;\r
+      foreach (T item in Backwards())\r
+      {\r
+        if (predicate(item))\r
+          return index;\r
+        index--;\r
+      }\r
+      return -1;\r
+    }\r
+\r
+\r
+\r
+    #region ISequenced<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public int GetSequencedHashCode()\r
+    { return sequenced.GetSequencedHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="that"></param>\r
+    /// <returns></returns>\r
+    public bool SequencedEquals(ISequenced<T> that)\r
+    { return sequenced.SequencedEquals(that); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedCollection<T> Members\r
+\r
+    /// <summary>\r
+    /// Get a collection that enumerates the wrapped collection in the opposite direction\r
+    /// </summary>\r
+    /// <returns>The mirrored collection</returns>\r
+    public virtual IDirectedCollectionValue<T> Backwards()\r
+    { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return sequenced.FindLast(predicate, out item); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\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
+    public EnumerationDirection Direction\r
+    { get { return EnumerationDirection.Forwards; } }\r
+\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override object Clone()\r
+    {\r
+      return new GuardedCollection<T>((ISequenced<T>)(sequenced.Clone()));\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a sorted collection\r
+  ///\r
+  /// <i>This is mainly interesting as a base of other guard classes</i>\r
+  /// </summary>\r
+  public class GuardedSorted<T> : GuardedSequenced<T>, ISorted<T>\r
+  {\r
+    #region Fields\r
+\r
+    ISorted<T> sorted;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a sorted collection in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="sorted"></param>\r
+    public GuardedSorted(ISorted<T> sorted) : base(sorted) { this.sorted = sorted; }\r
+\r
+    #endregion\r
+\r
+    #region ISorted<T> Members\r
+\r
+    /// <summary>\r
+    /// Find the predecessor of the item in the wrapped sorted collection\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    \r
+    /// <param name="item">The item</param>\r
+    /// <returns>The predecessor</returns>\r
+    public T Predecessor(T item) { return sorted.Predecessor(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the Successor of the item in the wrapped sorted collection\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    \r
+    /// <param name="item">The item</param>\r
+    /// <returns>The Successor</returns>\r
+    public T Successor(T item) { return sorted.Successor(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the weak predecessor of the item in the wrapped sorted collection\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    \r
+    /// <param name="item">The item</param>\r
+    /// <returns>The weak predecessor</returns>\r
+    public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the weak Successor of the item in the wrapped sorted collection\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    \r
+    /// <param name="item">The item</param>\r
+    /// <returns>The weak Successor</returns>\r
+    public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Run Cut on the wrapped sorted collection\r
+    /// </summary>\r
+    /// <param name="c"></param>\r
+    /// <param name="low"></param>\r
+    /// <param name="lval"></param>\r
+    /// <param name="high"></param>\r
+    /// <param name="hval"></param>\r
+    /// <returns></returns>\r
+    public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)\r
+    { return sorted.Cut(c, out low, out lval, out high, out hval); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the specified range from the wrapped collection. \r
+    /// (The current implementation erroneously does not wrap the result.)\r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the specified range from the wrapped collection. \r
+    /// (The current implementation erroneously does not wrap the result.)\r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<T> RangeFromTo(T bot, T top)\r
+    { return sorted.RangeFromTo(bot, top); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the specified range from the wrapped collection. \r
+    /// (The current implementation erroneously does not wrap the result.)\r
+    /// </summary>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the specified range from the wrapped collection. \r
+    /// (The current implementation erroneously does not wrap the result.)\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="items"></param>\r
+    /// <typeparam name="U"></typeparam>\r
+    public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="low"></param>\r
+    public void RemoveRangeFrom(T low)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="low"></param>\r
+    /// <param name="hi"></param>\r
+    public void RemoveRangeFromTo(T low, T hi)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="hi"></param>\r
+    public void RemoveRangeTo(T hi)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    #endregion\r
+\r
+    #region IPriorityQueue<T> Members\r
+\r
+    /// <summary>\r
+    /// Find the minimum of the wrapped collection\r
+    /// </summary>\r
+    /// <returns>The minimum</returns>\r
+    public T FindMin() { return sorted.FindMin(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns></returns>\r
+    public T DeleteMin()\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the maximum of the wrapped collection\r
+    /// </summary>\r
+    /// <returns>The maximum</returns>\r
+    public T FindMax() { return sorted.FindMax(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns></returns>\r
+    public T DeleteMax()\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    //TODO: we should guard the comparer!\r
+    /// <summary>\r
+    /// The comparer object supplied at creation time for the underlying collection\r
+    /// </summary>\r
+    /// <value>The comparer</value>\r
+    public SCG.IComparer<T> Comparer { get { return sorted.Comparer; } }\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\r
+    { return Backwards(); }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override object Clone()\r
+    {\r
+      return new GuardedSorted<T>((ISorted<T>)(sorted.Clone()));\r
+    }\r
+\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// Read-only wrapper for indexed sorted collections\r
+  ///\r
+  /// <i>Suitable for wrapping TreeSet, TreeBag and SortedArray</i>\r
+  /// </summary>\r
+  public class GuardedIndexedSorted<T> : GuardedSorted<T>, IIndexedSorted<T>\r
+  {\r
+    #region Fields\r
+\r
+    IIndexedSorted<T> indexedsorted;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap an indexed sorted collection in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="list">the indexed sorted collection</param>\r
+    public GuardedIndexedSorted(IIndexedSorted<T> list)\r
+      : base(list)\r
+    { this.indexedsorted = list; }\r
+\r
+    #endregion\r
+\r
+    #region IIndexedSorted<T> Members\r
+\r
+    /// <summary>\r
+    /// Get the specified range from the wrapped collection. \r
+    /// (The current implementation erroneously does not wrap the result.)\r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <returns></returns>\r
+    public new IDirectedCollectionValue<T> RangeFrom(T bot)\r
+    { return indexedsorted.RangeFrom(bot); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the specified range from the wrapped collection. \r
+    /// (The current implementation erroneously does not wrap the result.)\r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)\r
+    { return indexedsorted.RangeFromTo(bot, top); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the specified range from the wrapped collection. \r
+    /// (The current implementation erroneously does not wrap the result.)\r
+    /// </summary>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public new IDirectedCollectionValue<T> RangeTo(T top)\r
+    { return indexedsorted.RangeTo(top); }\r
+\r
+\r
+    /// <summary>\r
+    /// Report the number of items in the specified range of the wrapped collection\r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <returns></returns>\r
+    public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }\r
+\r
+\r
+    /// <summary>\r
+    /// Report the number of items in the specified range of the wrapped collection\r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }\r
+\r
+\r
+    /// <summary>\r
+    /// Report the number of items in the specified range of the wrapped collection\r
+    /// </summary>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public int CountTo(T top) { return indexedsorted.CountTo(top); }\r
+\r
+\r
+    /// <summary>\r
+    /// Run FindAll on the wrapped collection with the indicated filter.\r
+    /// The result will <b>not</b> be read-only.\r
+    /// </summary>\r
+    /// <param name="f"></param>\r
+    /// <returns></returns>\r
+    public IIndexedSorted<T> FindAll(Fun<T, bool> f)\r
+    { return indexedsorted.FindAll(f); }\r
+\r
+\r
+    /// <summary>\r
+    /// Run Map on the wrapped collection with the indicated mapper.\r
+    /// The result will <b>not</b> be read-only.\r
+    /// </summary>\r
+    /// <param name="m"></param>\r
+    /// <param name="c">The comparer to use in the result</param>\r
+    /// <returns></returns>\r
+    public IIndexedSorted<V> Map<V>(Fun<T, V> m, SCG.IComparer<V> c)\r
+    { return indexedsorted.Map(m, c); }\r
+\r
+    #endregion\r
+\r
+    #region IIndexed<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The i'th item of the wrapped sorted collection</value>\r
+    public T this[int i] { get { return indexedsorted[i]; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual Speed IndexingSpeed { get { return indexedsorted.IndexingSpeed; } }\r
+\r
+    /// <summary> </summary>\r
+    /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>\r
+    public IDirectedCollectionValue<T> this[int start, int end]\r
+    { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the (first) index of an item in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int IndexOf(T item) { return indexedsorted.IndexOf(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the last index of an item in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="i"></param>\r
+    /// <returns></returns>\r
+    public T RemoveAt(int i)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="start"></param>\r
+    /// <param name="count"></param>\r
+    public void RemoveInterval(int start, int count)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\r
+    { return Backwards(); }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override object Clone()\r
+    {\r
+      return new GuardedIndexedSorted<T>((IIndexedSorted<T>)(indexedsorted.Clone()));\r
+    }\r
+\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a generic list collection\r
+  /// <i>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.\r
+  /// <see cref="T:C5.LinkedList`1"/>, \r
+  /// <see cref="T:C5.HashedLinkedList`1"/>, \r
+  /// <see cref="T:C5.ArrayList`1"/> or\r
+  /// <see cref="T:C5.HashedArray`1"/>.\r
+  /// </i>\r
+  /// </summary>\r
+  public class GuardedList<T> : GuardedSequenced<T>, IList<T>\r
+  {\r
+    #region Fields\r
+\r
+    IList<T> innerlist;\r
+    GuardedList<T> underlying;\r
+    bool slidableView = false;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a list in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="list">The list</param>\r
+    public GuardedList(IList<T> list)\r
+      : base(list)\r
+    {\r
+      this.innerlist = list;\r
+      if (list.Underlying != null)\r
+        underlying = new GuardedList<T>(list.Underlying, null, false);\r
+    }\r
+\r
+    GuardedList(IList<T> list, GuardedList<T> underlying, bool slidableView)\r
+      : base(list)\r
+    {\r
+      this.innerlist = list; this.underlying = underlying; this.slidableView = slidableView;\r
+    }\r
+    #endregion\r
+\r
+    #region IList<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The first item of the wrapped list</value>\r
+    public T First { get { return innerlist.First; } }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The last item of the wrapped list</value>\r
+    public T Last { get { return innerlist.Last; } }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>\r
+    /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>\r
+    public bool FIFO\r
+    {\r
+      get { return innerlist.FIFO; }\r
+      set { throw new ReadOnlyCollectionException("List is read only"); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public virtual bool IsFixedSize\r
+    {\r
+      get { return true; }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>\r
+    /// <value>The i'th item of the wrapped list</value>\r
+    public T this[int i]\r
+    {\r
+      get { return innerlist[i]; }\r
+      set { throw new ReadOnlyCollectionException("List is read only"); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual Speed IndexingSpeed { get { return innerlist.IndexingSpeed; } }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="i"></param>\r
+    /// <param name="item"></param>\r
+    public void Insert(int i, T item)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="pointer"></param>\r
+    /// <param name="item"></param>\r
+    public void Insert(IList<T> pointer, T item)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    public void InsertFirst(T item)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    public void InsertLast(T item)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <param name="target"></param>\r
+    public void InsertBefore(T item, T target)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="item"></param>\r
+    /// <param name="target"></param>\r
+    public void InsertAfter(T item, T target)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="i"></param>\r
+    /// <param name="items"></param>\r
+    public void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.\r
+    /// </summary>\r
+    /// <param name="filter">The filter to use</param>\r
+    /// <returns></returns>\r
+    public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }\r
+\r
+\r
+    /// <summary>\r
+    /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.\r
+    /// </summary>\r
+    /// <typeparam name="V">The type of items of the new list</typeparam>\r
+    /// <param name="mapper">The mapper to use.</param>\r
+    /// <returns>The mapped list</returns>\r
+    public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map(mapper); }\r
+\r
+    /// <summary>\r
+    /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.\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="itemequalityComparer">The itemequalityComparer to use for the new list</param>\r
+    /// <returns>The new list.</returns>\r
+    public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns></returns>\r
+    public T Remove() { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns></returns>\r
+    public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns></returns>\r
+    public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// Create the indicated view on the wrapped list and wrap it read-only.\r
+    /// </summary>\r
+    /// <param name="start"></param>\r
+    /// <param name="count"></param>\r
+    /// <returns></returns>\r
+    public IList<T> View(int start, int count)\r
+    {\r
+      IList<T> view = innerlist.View(start, count);\r
+      return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create the indicated view on the wrapped list and wrap it read-only.\r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public IList<T> ViewOf(T item)\r
+    {\r
+      IList<T> view = innerlist.ViewOf(item);\r
+      return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create the indicated view on the wrapped list and wrap it read-only.\r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public IList<T> LastViewOf(T item)\r
+    {\r
+      IList<T> view = innerlist.LastViewOf(item);\r
+      return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <value>The wrapped underlying list of the wrapped view </value>\r
+    public IList<T> Underlying { get { return underlying; } }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The offset of the wrapped list as a view.</value>\r
+    public int Offset { get { return innerlist.Offset; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual bool IsValid { get { return innerlist.IsValid; } }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> if this is a wrapped view and not a view that was made on a wrapper</exception>\r
+    /// <param name="offset"></param>\r
+    public IList<T> Slide(int offset)\r
+    {\r
+      if (slidableView)\r
+      {\r
+        innerlist.Slide(offset);\r
+        return this;\r
+      }\r
+      else\r
+        throw new ReadOnlyCollectionException("List is read only");\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="offset"></param>\r
+    /// <param name="size"></param>\r
+    public IList<T> Slide(int offset, int size)\r
+    {\r
+      if (slidableView)\r
+      {\r
+        innerlist.Slide(offset, size);\r
+        return this;\r
+      }\r
+      else\r
+        throw new ReadOnlyCollectionException("List is read only");\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="offset"></param>\r
+    /// <returns></returns>\r
+    public bool TrySlide(int offset)\r
+    {\r
+      if (slidableView)\r
+        return innerlist.TrySlide(offset);\r
+      else\r
+        throw new ReadOnlyCollectionException("List is read only");\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="offset"></param>\r
+    /// <param name="size"></param>\r
+    /// <returns></returns>\r
+    public bool TrySlide(int offset, int size)\r
+    {\r
+      if (slidableView)\r
+        return innerlist.TrySlide(offset, size);\r
+      else\r
+        throw new ReadOnlyCollectionException("List is read only");\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="otherView"></param>\r
+    /// <returns></returns>\r
+    public IList<T> Span(IList<T> otherView)\r
+    {\r
+      GuardedList<T> otherGuardedList = otherView as GuardedList<T>;\r
+      if (otherGuardedList == null)\r
+        throw new IncompatibleViewException();\r
+      IList<T> span = innerlist.Span(otherGuardedList.innerlist);\r
+      if (span == null)\r
+        return null;\r
+      return new GuardedList<T>(span, underlying ?? otherGuardedList.underlying ?? this, true);\r
+    }\r
+\r
+    /// <summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// </summary>\r
+    public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="start"></param>\r
+    /// <param name="count"></param>\r
+    public void Reverse(int start, int count)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if wrapped list is sorted according to the default sorting order\r
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class \r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">if T is not comparable</exception>\r
+    /// <returns>True if the list is sorted, else false.</returns>\r
+    public bool IsSorted() { return innerlist.IsSorted(Comparer<T>.Default); }\r
+\r
+    /// <summary>\r
+    /// Check if wrapped list is sorted\r
+    /// </summary>\r
+    /// <param name="c">The sorting order to use</param>\r
+    /// <returns>True if sorted</returns>\r
+    public bool IsSorted(SCG.IComparer<T> c) { return innerlist.IsSorted(c); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    public void Sort()\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="c"></param>\r
+    public void Sort(SCG.IComparer<T> c)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    public void Shuffle()\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="rnd"></param>\r
+    public void Shuffle(Random rnd)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+    #endregion\r
+\r
+    #region IIndexed<T> Members\r
+\r
+    /// <summary> </summary>\r
+    /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>\r
+    public IDirectedCollectionValue<T> this[int start, int end]\r
+    { get { return new GuardedDirectedCollectionValue<T>(innerlist[start, end]); } }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the (first) index of an item in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int IndexOf(T item) { return innerlist.IndexOf(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the last index of an item in the wrapped collection\r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="i"></param>\r
+    /// <returns></returns>\r
+    public T RemoveAt(int i)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="start"></param>\r
+    /// <param name="count"></param>\r
+    public void RemoveInterval(int start, int count)\r
+    { throw new ReadOnlyCollectionException("List is read only"); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\r
+    { return Backwards(); }\r
+\r
+    #endregion\r
+\r
+    #region IStack<T> Members\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns>-</returns>\r
+    public void Push(T item)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns>-</returns>\r
+    public T Pop()\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    #endregion\r
+\r
+    #region IQueue<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns>-</returns>\r
+    public void Enqueue(T item)\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns>-</returns>\r
+    public T Dequeue()\r
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }\r
+\r
+    #endregion\r
+\r
+    #region IDisposable Members\r
+\r
+    /// <summary>\r
+    /// Ignore: this may be called by a foreach or using statement.\r
+    /// </summary>\r
+    public void Dispose() { }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override object Clone()\r
+    {\r
+      return new GuardedList<T>((IList<T>)(innerlist.Clone()));\r
+    }\r
+\r
+  }\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a generic indexable queue (allows indexing).\r
+  /// \r
+  /// <para>Suitable for wrapping a <see cref="T:C5.CircularQueue`1"/></para>\r
+  /// </summary>\r
+  /// <typeparam name="T">The item type.</typeparam>\r
+  public class GuardedQueue<T> : GuardedDirectedCollectionValue<T>, IQueue<T>\r
+  {\r
+    #region Fields\r
+\r
+    IQueue<T> queue;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a queue in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="queue">The queue</param>\r
+    public GuardedQueue(IQueue<T> queue) : base(queue) { this.queue = queue; }\r
+\r
+    #endregion\r
+\r
+    #region IQueue<T> Members\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public bool AllowsDuplicates { get { return queue.AllowsDuplicates; } }\r
+\r
+    /// <summary>\r
+    /// Index into the wrapped queue\r
+    /// </summary>\r
+    /// <param name="i"></param>\r
+    /// <returns></returns>\r
+    public T this[int i] { get { return queue[i]; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns>-</returns>\r
+    public void Enqueue(T item)\r
+    { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns>-</returns>\r
+    public T Dequeue()\r
+    { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }\r
+\r
+    #endregion\r
+  }\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a dictionary.\r
+  ///\r
+  /// <i>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary`2"/></i>\r
+  /// </summary>\r
+  public class GuardedDictionary<K, V> : GuardedCollectionValue<KeyValuePair<K, V>>, IDictionary<K, V>\r
+  {\r
+    #region Fields\r
+\r
+    IDictionary<K, V> dict;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a dictionary in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="dict">the dictionary</param>\r
+    public GuardedDictionary(IDictionary<K, V> dict) : base(dict) { this.dict = dict; }\r
+\r
+    #endregion\r
+\r
+    #region IDictionary<K,V> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public SCG.IEqualityComparer<K> EqualityComparer { get { return dict.EqualityComparer; } }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a\r
+    /// read-only wrappper if used as a setter</exception>\r
+    /// <value>Get the value corresponding to a key in the wrapped dictionary</value>\r
+    public V this[K key]\r
+    {\r
+      get { return dict[key]; }\r
+      set { throw new ReadOnlyCollectionException(); }\r
+    }\r
+\r
+    /// <summary>\r
+    /// (This is a read-only wrapper)\r
+    /// </summary>\r
+    /// <value>True</value>\r
+    public bool IsReadOnly { get { return true; } }\r
+\r
+\r
+    //TODO: guard with a read-only wrapper? Probably so!\r
+    /// <summary> </summary>\r
+    /// <value>The collection of keys of the wrapped dictionary</value>\r
+    public ICollectionValue<K> Keys\r
+    { get { return dict.Keys; } }\r
+\r
+\r
+    /// <summary> </summary>\r
+    /// <value>The collection of values of the wrapped dictionary</value>\r
+    public ICollectionValue<V> Values { get { return dict.Values; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public virtual Fun<K, V> Fun { get { return delegate(K k) { return this[k]; }; } }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <param name="val"></param>\r
+    public void Add(K key, V val)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="items"></param>\r
+    public void AddAll<L, W>(SCG.IEnumerable<KeyValuePair<L, W>> items)\r
+      where L : K\r
+      where W : V\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <returns></returns>\r
+    public bool Remove(K key)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <param name="val"></param>\r
+    /// <returns></returns>\r
+    public bool Remove(K key, out V val)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    public void Clear()\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public Speed ContainsSpeed { get { return dict.ContainsSpeed; } }\r
+\r
+    /// <summary>\r
+    /// Check if the wrapped dictionary contains a specific key\r
+    /// </summary>\r
+    /// <param name="key">The key</param>\r
+    /// <returns>True if it does</returns>\r
+    public bool Contains(K key) { return dict.Contains(key); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="keys"></param>\r
+    /// <returns></returns>\r
+    public bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K { return dict.ContainsAll(keys); }\r
+\r
+    /// <summary>\r
+    /// Search for a key in the wrapped dictionary, reporting the value if found\r
+    /// </summary>\r
+    /// <param name="key">The key</param>\r
+    /// <param name="val">On exit: the value if found</param>\r
+    /// <returns>True if found</returns>\r
+    public bool Find(K key, out V val) { return dict.Find(key, out val); }\r
+\r
+    /// <summary>\r
+    /// Search for a key in the wrapped dictionary, reporting the value if found\r
+    /// </summary>\r
+    /// <param name="key">The key</param>\r
+    /// <param name="val">On exit: the value if found</param>\r
+    /// <returns>True if found</returns>\r
+    public bool Find(ref K key, out V val) { return dict.Find(ref key, out val); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <param name="val"></param>\r
+    /// <returns></returns>\r
+    public bool Update(K key, V val)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <param name="val"></param>\r
+    /// <param name="oldval"></param>\r
+    /// <returns></returns>\r
+    public bool Update(K key, V val, out V oldval)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <param name="val"></param>\r
+    /// <returns></returns>\r
+    public bool FindOrAdd(K key, ref V val)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <param name="val"></param>\r
+    /// <returns></returns>\r
+    public bool UpdateOrAdd(K key, V val)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="key"></param>\r
+    /// <param name="val"></param>\r
+    /// <param name="oldval"></param>\r
+    /// <returns></returns>\r
+    public bool UpdateOrAdd(K key, V val, out V oldval)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+\r
+    /// <summary>\r
+    /// Check the internal consistency of the wrapped dictionary\r
+    /// </summary>\r
+    /// <returns>True if check passed</returns>\r
+    public bool Check() { return dict.Check(); }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      return new GuardedDictionary<K, V>((IDictionary<K, V>)(dict.Clone()));\r
+    }\r
+  }\r
+\r
+\r
+\r
+  /// <summary>\r
+  /// A read-only wrapper for a sorted dictionary.\r
+  ///\r
+  /// <i>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary`2"/></i>\r
+  /// </summary>\r
+  public class GuardedSortedDictionary<K, V> : GuardedDictionary<K, V>, ISortedDictionary<K, V>\r
+  {\r
+    #region Fields\r
+\r
+    ISortedDictionary<K, V> sorteddict;\r
+\r
+    #endregion\r
+\r
+    #region Constructor\r
+\r
+    /// <summary>\r
+    /// Wrap a sorted dictionary in a read-only wrapper\r
+    /// </summary>\r
+    /// <param name="sorteddict">the dictionary</param>\r
+    public GuardedSortedDictionary(ISortedDictionary<K, V> sorteddict)\r
+      : base(sorteddict)\r
+    { this.sorteddict = sorteddict; }\r
+\r
+    #endregion\r
+\r
+    #region ISortedDictionary<K,V> Members\r
+\r
+    /// <summary>\r
+    /// The key comparer used by this dictionary.\r
+    /// </summary>\r
+    /// <value></value>\r
+    public SCG.IComparer<K> Comparer { get { return sorteddict.Comparer; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public new ISorted<K> Keys { get { return null; } }\r
+\r
+    /// <summary>\r
+    /// Get the entry in the wrapped dictionary whose key is the\r
+    /// predecessor of a specified key.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    \r
+    /// <param name="key">The key</param>\r
+    /// <returns>The entry</returns>\r
+    public KeyValuePair<K, V> Predecessor(K key)\r
+    { return sorteddict.Predecessor(key); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the entry in the wrapped dictionary whose key is the\r
+    /// successor of a specified key.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    \r
+    /// <param name="key">The key</param>\r
+    /// <returns>The entry</returns>\r
+    public KeyValuePair<K, V> Successor(K key)\r
+    { return sorteddict.Successor(key); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the entry in the wrapped dictionary whose key is the\r
+    /// weak predecessor of a specified key.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    \r
+    /// <param name="key">The key</param>\r
+    /// <returns>The entry</returns>\r
+    public KeyValuePair<K, V> WeakPredecessor(K key)\r
+    { return sorteddict.WeakPredecessor(key); }\r
+\r
+\r
+    /// <summary>\r
+    /// Get the entry in the wrapped dictionary whose key is the\r
+    /// weak successor of a specified key.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    \r
+    /// <param name="key">The key</param>\r
+    /// <returns>The entry</returns>\r
+    public KeyValuePair<K, V> WeakSuccessor(K key)\r
+    { return sorteddict.WeakSuccessor(key); }\r
+\r
+    #endregion\r
+\r
+    #region ISortedDictionary<K,V> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> FindMin()\r
+    {\r
+      return sorteddict.FindMin();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> DeleteMin()\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> FindMax()\r
+    {\r
+      return sorteddict.FindMax();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <returns></returns>\r
+    public KeyValuePair<K, V> DeleteMax()\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="c"></param>\r
+    /// <param name="lowEntry"></param>\r
+    /// <param name="lowIsValid"></param>\r
+    /// <param name="highEntry"></param>\r
+    /// <param name="highIsValid"></param>\r
+    /// <returns></returns>\r
+    public bool Cut(IComparable<K> c, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)\r
+    {\r
+      return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); ;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)\r
+    {\r
+      return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFrom(bot));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="bot"></param>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)\r
+    {\r
+      return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFromTo(bot, top));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="top"></param>\r
+    /// <returns></returns>\r
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)\r
+    {\r
+      return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeTo(top));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()\r
+    {\r
+      return new GuardedDirectedCollectionValue<KeyValuePair<K, V>>(sorteddict.RangeAll());\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="items"></param>\r
+    public void AddSorted(System.Collections.Generic.IEnumerable<KeyValuePair<K, V>> items)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="low"></param>\r
+    public void RemoveRangeFrom(K low)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="low"></param>\r
+    /// <param name="hi"></param>\r
+    public void RemoveRangeFromTo(K low, K hi)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>\r
+    /// <param name="hi"></param>\r
+    public void RemoveRangeTo(K hi)\r
+    { throw new ReadOnlyCollectionException(); }\r
+\r
+    #endregion\r
+  }\r
+\r
+}
\ No newline at end of file
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..4ff7084
--- /dev/null
@@ -0,0 +1,2536 @@
+\r
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 HASHINDEXnot\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using SCG = 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
+  /// <i>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.</i>\r
+  /// </summary>\r
+  [Serializable]\r
+  public class ArrayList<T> : ArrayBase<T>, IList<T> //, System.Runtime.Serialization.ISerializable\r
+#if HASHINDEX\r
+#else\r
+, IStack<T>, IQueue<T>\r
+#endif\r
+  {\r
+    #region Fields\r
+\r
+    /// <summary>\r
+    /// Has this list or view not been invalidated by some operation (by someone calling Dispose())\r
+    /// </summary>\r
+    bool isValid = true;\r
+\r
+    //TODO: wonder if we should save some memory on none-view situations by \r
+    //      putting these three fields into a single ref field?\r
+    /// <summary>\r
+    /// The underlying list if we are a view, null else.\r
+    /// </summary>\r
+    ArrayList<T> underlying;\r
+    WeakViewList<ArrayList<T>> views;\r
+    WeakViewList<ArrayList<T>>.Node myWeakReference;\r
+\r
+    /// <summary>\r
+    /// The size of the underlying list.\r
+    /// </summary>\r
+    int underlyingsize { get { return (underlying ?? this).size; } }\r
+\r
+    /// <summary>\r
+    /// The underlying field of the FIFO property\r
+    /// </summary>\r
+    bool fIFO = false;\r
+\r
+#if HASHINDEX\r
+    HashSet<KeyValuePair<T, int>> itemIndex;\r
+#endif\r
+    #endregion\r
+    #region Events\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override EventTypeEnum ListenableEvents { get { return underlying == null ? EventTypeEnum.All : EventTypeEnum.None; } }\r
+\r
+/*\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override event CollectionChangedHandler<T> CollectionChanged\r
+    {\r
+      add\r
+      {\r
+        if (underlying == null)\r
+          base.CollectionChanged += value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+      remove\r
+      {\r
+        if (underlying == null)\r
+          base.CollectionChanged -= value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override event CollectionClearedHandler<T> CollectionCleared\r
+    {\r
+      add\r
+      {\r
+        if (underlying == null)\r
+          base.CollectionCleared += value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+      remove\r
+      {\r
+        if (underlying == null)\r
+          base.CollectionCleared -= value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override event ItemsAddedHandler<T> ItemsAdded\r
+    {\r
+      add\r
+      {\r
+        if (underlying == null)\r
+          base.ItemsAdded += value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+      remove\r
+      {\r
+        if (underlying == null)\r
+          base.ItemsAdded -= value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override event ItemInsertedHandler<T> ItemInserted\r
+    {\r
+      add\r
+      {\r
+        if (underlying == null)\r
+          base.ItemInserted += value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+      remove\r
+      {\r
+        if (underlying == null)\r
+          base.ItemInserted -= value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override event ItemsRemovedHandler<T> ItemsRemoved\r
+    {\r
+      add\r
+      {\r
+        if (underlying == null)\r
+          base.ItemsRemoved += value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+      remove\r
+      {\r
+        if (underlying == null)\r
+          base.ItemsRemoved -= value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override event ItemRemovedAtHandler<T> ItemRemovedAt\r
+    {\r
+      add\r
+      {\r
+        if (underlying == null)\r
+          base.ItemRemovedAt += value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+      remove\r
+      {\r
+        if (underlying == null)\r
+          base.ItemRemovedAt -= value;\r
+        else\r
+          throw new UnlistenableEventException("Can't listen to a view");\r
+      }\r
+    }\r
+\r
+      */\r
+\r
+    #endregion\r
+    #region Util\r
+\r
+    bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }\r
+\r
+    /// <summary>\r
+    /// Increment or decrement the private size fields\r
+    /// </summary>\r
+    /// <param name="delta">Increment (with sign)</param>\r
+    void addtosize(int delta)\r
+    {\r
+      size += delta;\r
+      if (underlying != null)\r
+        underlying.size += delta;\r
+    }\r
+\r
+    #region Array handling\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
+    #endregion\r
+\r
+    #region Checks\r
+    /// <summary>\r
+    /// Check if it is valid to perform updates and increment stamp if so.\r
+    /// </summary>\r
+    /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>\r
+    /// <exception cref="ReadOnlyCollectionException"> If check fails by this being a read only list.</exception>\r
+    protected override void updatecheck()\r
+    {\r
+      validitycheck();\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
+    /// <para>This method should be called from enumerators etc to guard against \r
+    /// modification of the base collection.</para>\r
+    /// </summary>\r
+    /// <exception cref="ViewDisposedException"> if check fails.</exception>\r
+    void validitycheck()\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException();\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Check that the list has not been updated since a particular time.\r
+    /// <para>To be used by enumerators and range </para>\r
+    /// </summary>\r
+    /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>\r
+    /// <exception cref="CollectionModifiedException">If the list *has* beeen updated since that  time..</exception>\r
+    /// <param name="stamp">The stamp indicating the time.</param>\r
+    protected override void modifycheck(int stamp)\r
+    {\r
+      validitycheck();\r
+      if (this.stamp != stamp)\r
+        throw new CollectionModifiedException();\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region Searching\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
+    int indexOf(T item)\r
+    {\r
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item);\r
+      if (itemIndex.Find(ref p) && p.Value >= offset && p.Value < offset + size)\r
+        return p.Value - offset;\r
+#else\r
+      for (int i = 0; i < size; i++)\r
+        if (equals(item, array[offset + i]))\r
+          return i;\r
+#endif\r
+      return ~size;\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
+    int lastIndexOf(T item)\r
+    {\r
+#if HASHINDEX\r
+      return indexOf(item);\r
+#else\r
+      for (int i = size - 1; i >= 0; i--)\r
+        if (equals(item, array[offset + i]))\r
+          return i;\r
+      return ~size;\r
+#endif\r
+    }\r
+    #endregion\r
+\r
+    #region Inserting\r
+\r
+#if HASHINDEX\r
+    /// <summary>\r
+    /// Internal version of Insert with no modification checks.\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException"> if item already in list.</exception>\r
+    /// <param name="i">Index to insert at</param>\r
+    /// <param name="item">Item to insert</param>\r
+#else\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
+#endif\r
+    protected override void insert(int i, T item)\r
+    {\r
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, offset + i);\r
+      if (itemIndex.FindOrAdd(ref p))\r
+        throw new DuplicateNotAllowedException("Item already in indexed list: " + item);\r
+#endif\r
+      baseinsert(i, item);\r
+#if HASHINDEX\r
+      reindex(i + offset + 1);\r
+#endif\r
+    }\r
+\r
+    private void baseinsert(int i, T item)\r
+    {\r
+      if (underlyingsize == array.Length)\r
+        expand();\r
+      i += offset;\r
+      if (i < underlyingsize)\r
+        Array.Copy(array, i, array, i + 1, underlyingsize - i);\r
+      array[i] = item;\r
+      addtosize(1);\r
+      fixViewsAfterInsert(1, i);\r
+    }\r
+    #endregion\r
+\r
+    #region Removing\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
+    T removeAt(int i)\r
+    {\r
+      i += offset;\r
+      fixViewsBeforeSingleRemove(i);\r
+      T retval = array[i];\r
+      addtosize(-1);\r
+      if (underlyingsize > i)\r
+        Array.Copy(array, i + 1, array, i, underlyingsize - i);\r
+      array[underlyingsize] = default(T);\r
+#if HASHINDEX\r
+      itemIndex.Remove(new KeyValuePair<T, int>(retval));\r
+      reindex(i);\r
+#endif\r
+      return retval;\r
+    }\r
+    #endregion\r
+\r
+    #region Indexing\r
+\r
+#if HASHINDEX\r
+    private void reindex(int start) { reindex(start, underlyingsize); }\r
+\r
+    private void reindex(int start, int end)\r
+    {\r
+      for (int j = start; j < end; j++)\r
+        itemIndex.UpdateOrAdd(new KeyValuePair<T, int>(array[j], j));\r
+    }\r
+#endif\r
+    #endregion\r
+\r
+    #region fixView utilities\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="added">The actual number of inserted nodes</param>\r
+    /// <param name="realInsertionIndex"></param>\r
+    void fixViewsAfterInsert(int added, int realInsertionIndex)\r
+    {\r
+      if (views != null)\r
+        foreach (ArrayList<T> view in views)\r
+        {\r
+          if (view != this)\r
+          {\r
+            if (view.offset < realInsertionIndex && view.offset + view.size > realInsertionIndex)\r
+              view.size += added;\r
+            if (view.offset > realInsertionIndex || (view.offset == realInsertionIndex && view.size > 0))\r
+              view.offset += added;\r
+          }\r
+        }\r
+    }\r
+\r
+    void fixViewsBeforeSingleRemove(int realRemovalIndex)\r
+    {\r
+      if (views != null)\r
+        foreach (ArrayList<T> view in views)\r
+        {\r
+          if (view != this)\r
+          {\r
+            if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex)\r
+              view.size--;\r
+            if (view.offset > realRemovalIndex)\r
+              view.offset--;\r
+          }\r
+        }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Fix offsets and sizes of other views before removing an interval from this \r
+    /// </summary>\r
+    /// <param name="start">the start of the interval relative to the array/underlying</param>\r
+    /// <param name="count"></param>\r
+    void fixViewsBeforeRemove(int start, int count)\r
+    {\r
+      int clearend = start + count - 1;\r
+      if (views != null)\r
+        foreach (ArrayList<T> view in views)\r
+        {\r
+          if (view == this)\r
+            continue;\r
+          int viewoffset = view.offset, viewend = viewoffset + view.size - 1;\r
+          if (start < viewoffset)\r
+          {\r
+            if (clearend < viewoffset)\r
+              view.offset = viewoffset - count;\r
+            else\r
+            {\r
+              view.offset = start;\r
+              view.size = clearend < viewend ? viewend - clearend : 0;\r
+            }\r
+          }\r
+          else if (start <= viewend)\r
+            view.size = clearend <= viewend ? view.size - count : start - viewoffset;\r
+        }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="otherOffset"></param>\r
+    /// <param name="otherSize"></param>\r
+    /// <returns>The position of View(otherOffset, otherSize) wrt. this view</returns>\r
+    MutualViewPosition viewPosition(int otherOffset, int otherSize)\r
+    {\r
+      int end = offset + size, otherEnd = otherOffset + otherSize;\r
+      if (otherOffset >= end || otherEnd <= offset)\r
+        return MutualViewPosition.NonOverlapping;\r
+      if (size == 0 || (otherOffset <= offset && end <= otherEnd))\r
+        return MutualViewPosition.Contains;\r
+      if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end))\r
+        return MutualViewPosition.ContainedIn;\r
+      return MutualViewPosition.Overlapping;\r
+    }\r
+\r
+    //TODO: make version that fits the new, more forgiving rules for disposing\r
+    void disposeOverlappingViews(bool reverse)\r
+    {\r
+      if (views != null)\r
+        foreach (ArrayList<T> view in views)\r
+        {\r
+          if (view != this)\r
+          {\r
+            switch (viewPosition(view.offset, view.size))\r
+            {\r
+              case MutualViewPosition.ContainedIn:\r
+                if (reverse)\r
+                  view.offset = 2 * offset + size - view.size - view.offset;\r
+                else\r
+                  view.Dispose();\r
+                break;\r
+              case MutualViewPosition.Overlapping:\r
+                view.Dispose();\r
+                break;\r
+              case MutualViewPosition.Contains:\r
+              case MutualViewPosition.NonOverlapping:\r
+                break;\r
+            }\r
+          }\r
+        }\r
+    }\r
+    #endregion\r
+\r
+    #endregion\r
+\r
+    #region Position, PositionComparer and ViewHandler nested types\r
+    class PositionComparer : SCG.IComparer<Position>\r
+    {\r
+      public int Compare(Position a, Position b)\r
+      {\r
+        return a.index.CompareTo(b.index);\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for ArrayList?)\r
+    /// </summary>\r
+    struct Position\r
+    {\r
+      public readonly ArrayList<T> view;\r
+      public readonly int index;\r
+      public Position(ArrayList<T> view, bool left)\r
+      {\r
+        this.view = view;\r
+        index = left ? view.offset : view.offset + view.size - 1;\r
+      }\r
+      public Position(int index) { this.index = index; view = null; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Handle the update of (other) views during a multi-remove operation.\r
+    /// </summary>\r
+    struct ViewHandler\r
+    {\r
+      ArrayList<Position> leftEnds;\r
+      ArrayList<Position> rightEnds;\r
+      int leftEndIndex, rightEndIndex;\r
+      internal readonly int viewCount;\r
+      internal ViewHandler(ArrayList<T> list)\r
+      {\r
+        leftEndIndex = rightEndIndex = viewCount = 0;\r
+        leftEnds = rightEnds = null;\r
+        if (list.views != null)\r
+          foreach (ArrayList<T> v in list.views)\r
+            if (v != list)\r
+            {\r
+              if (leftEnds == null)\r
+              {\r
+                leftEnds = new ArrayList<Position>();\r
+                rightEnds = new ArrayList<Position>();\r
+              }\r
+              leftEnds.Add(new Position(v, true));\r
+              rightEnds.Add(new Position(v, false));\r
+            }\r
+        if (leftEnds == null)\r
+          return;\r
+        viewCount = leftEnds.Count;\r
+        leftEnds.Sort(new PositionComparer());\r
+        rightEnds.Sort(new PositionComparer());\r
+      }\r
+      /// <summary>\r
+      /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed\r
+      /// </summary>\r
+      /// <param name="removed"></param>\r
+      /// <param name="realindex"></param>\r
+      internal void skipEndpoints(int removed, int realindex)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)\r
+          {\r
+            ArrayList<T> view = endpoint.view;\r
+            view.offset = view.offset - removed;\r
+            view.size += removed;\r
+            leftEndIndex++;\r
+          }\r
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)\r
+          {\r
+            endpoint.view.size -= removed;\r
+            rightEndIndex++;\r
+          }\r
+        }\r
+      }\r
+      internal void updateViewSizesAndCounts(int removed, int realindex)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)\r
+          {\r
+            ArrayList<T> view = endpoint.view;\r
+            view.offset = view.Offset - removed;\r
+            view.size += removed;\r
+            leftEndIndex++;\r
+          }\r
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)\r
+          {\r
+            endpoint.view.size -= removed;\r
+            rightEndIndex++;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    #endregion\r
+\r
+    #region Constructors\r
+    /// <summary>\r
+    /// Create an array list with default item equalityComparer and initial capacity 8 items.\r
+    /// </summary>\r
+    public ArrayList() : this(8) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create an array list with external item equalityComparer and initial capacity 8 items.\r
+    /// </summary>\r
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>\r
+    public ArrayList(SCG.IEqualityComparer<T> itemequalityComparer) : this(8,itemequalityComparer) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create an array list with default item equalityComparer and prescribed initial capacity.\r
+    /// </summary>\r
+    /// <param name="capacity">The prescribed capacity</param>\r
+    public ArrayList(int capacity) : this(capacity,EqualityComparer<T>.Default) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create an array list with external item equalityComparer and prescribed initial capacity.\r
+    /// </summary>\r
+    /// <param name="capacity">The prescribed capacity</param>\r
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>\r
+    public ArrayList(int capacity, SCG.IEqualityComparer<T> itemequalityComparer) : base(capacity,itemequalityComparer)\r
+    {\r
+#if HASHINDEX\r
+      itemIndex = new HashSet<KeyValuePair<T, int>>(new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));\r
+#endif\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IList<T> Members\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <value>The first item in this list.</value>\r
+    [Tested]\r
+    public virtual T First\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+        validitycheck();\r
+        if (size == 0)\r
+          throw new NoSuchItemException();\r
+\r
+        return array[offset];\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <value>The last item in this list.</value>\r
+    [Tested]\r
+    public virtual T Last\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+        validitycheck();\r
+        if (size == 0)\r
+          throw new NoSuchItemException();\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. The default for a new array list is false.</value>\r
+    [Tested]\r
+    public virtual bool FIFO\r
+    {\r
+      [Tested]\r
+      get { validitycheck(); return fIFO; }\r
+      [Tested]\r
+      set { updatecheck(); fIFO = value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public virtual bool IsFixedSize\r
+    {\r
+      get { validitycheck(); return false; }\r
+    }\r
+\r
+\r
+#if HASHINDEX\r
+    /// <summary>\r
+    /// On this list, this indexer is read/write.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or\r
+    /// &gt;= the size of the collection.</exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> By the get operation\r
+    /// if the item already is present somewhere else in the list.</exception>\r
+    /// <value>The index'th item of this list.</value>\r
+    /// <param name="index">The index of the item to fetch or store.</param>\r
+#else\r
+    /// <summary>\r
+    /// On this list, this indexer is read/write.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or\r
+    /// &gt;= the size of the collection.</exception>\r
+    /// <value>The index'th item of this list.</value>\r
+    /// <param name="index">The index of the item to fetch or store.</param>\r
+#endif\r
+    [Tested]\r
+    public virtual T this[int index]\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+        validitycheck();\r
+        if (index < 0 || index >= size)\r
+          throw new IndexOutOfRangeException();\r
+\r
+        return array[offset + index];\r
+      }\r
+      [Tested]\r
+      set\r
+      {\r
+        updatecheck();\r
+        if (index < 0 || index >= size)\r
+          throw new IndexOutOfRangeException();\r
+        index += offset;\r
+        T item = array[index];\r
+#if HASHINDEX\r
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(value, index);\r
+        if (itemequalityComparer.Equals(value, item))\r
+        {\r
+          array[index] = value;\r
+          itemIndex.Update(p);\r
+        }\r
+        else if (!itemIndex.FindOrAdd(ref p))\r
+        {\r
+          itemIndex.Remove(new KeyValuePair<T, int>(item));\r
+          array[index] = value;\r
+        }\r
+        else\r
+          throw new DuplicateNotAllowedException("Item already in indexed list");\r
+#else\r
+        array[index] = value;\r
+#endif\r
+        (underlying ?? this).raiseForSetThis(index, value, item);\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual Speed IndexingSpeed { get { return Speed.Constant; } }\r
+\r
+#if HASHINDEX\r
+    /// <summary>\r
+    /// Insert an item at a specific index location in this list. \r
+    ///</summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or\r
+    /// &gt; the size of the collection. </exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> \r
+    /// If the item is already present in the list.</exception>\r
+    /// <param name="index">The index at which to insert.</param>\r
+    /// <param name="item">The item to insert.</param>\r
+#else\r
+    /// <summary>\r
+    /// Insert an item at a specific index location in this list. \r
+    ///</summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if i is negative or\r
+    /// &gt; the size of the collection. </exception>\r
+    /// <param name="index">The index at which to insert.</param>\r
+    /// <param name="item">The item to insert.</param>\r
+#endif\r
+    [Tested]\r
+    public virtual void Insert(int index, T item)\r
+    {\r
+      updatecheck();\r
+      if (index < 0 || index > size)\r
+        throw new IndexOutOfRangeException();\r
+\r
+      insert(index, item);\r
+      (underlying ?? this).raiseForInsert(index + offset, item);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Insert an item at the end of a compatible view, used as a pointer.\r
+    /// <para>The <code>pointer</code> must be a view on the same list as\r
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be\r
+    /// a valid insertion point of <code>this</code></para>\r
+    /// </summary>\r
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> \r
+    /// is not a view on or the same list as <code>this</code></exception>\r
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of \r
+    ///  <code>pointer</code> is not inside <code>this</code></exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> if the list has\r
+    /// <code>AllowsDuplicates==false</code> and the item is \r
+    /// already in the list.</exception>\r
+    /// <param name="pointer"></param>\r
+    /// <param name="item"></param>\r
+    public void Insert(IList<T> pointer, T item)\r
+    {\r
+      if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this)))\r
+        throw new IncompatibleViewException();\r
+      Insert(pointer.Offset + pointer.Count - Offset, item);\r
+    }\r
+\r
+#if HASHINDEX\r
+    /// <summary>\r
+    /// Insert into this list all items from an enumerable collection starting \r
+    /// at a particular index.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or\r
+    /// &gt; the size of the collection.</exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> If <code>items</code> \r
+    /// contains duplicates or some item already  present in the list.</exception>\r
+    /// <param name="index">Index to start inserting at</param>\r
+    /// <param name="items">Items to insert</param>\r
+#else\r
+    /// <summary>\r
+    /// Insert into this list all items from an enumerable collection starting \r
+    /// at a particular index.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or\r
+    /// &gt; the size of the collection.</exception>\r
+    /// <param name="index">Index to start inserting at</param>\r
+    /// <param name="items">Items to insert</param>\r
+    /// <typeparam name="U"></typeparam>\r
+#endif\r
+    [Tested]\r
+    public virtual void InsertAll<U>(int index, SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      if (index < 0 || index > size)\r
+        throw new IndexOutOfRangeException();\r
+      index += offset;\r
+      int toadd = EnumerableBase<U>.countItems(items);\r
+      if (toadd == 0)\r
+        return;\r
+      if (toadd + underlyingsize > array.Length)\r
+        expand(toadd + underlyingsize, underlyingsize);\r
+      if (underlyingsize > index)\r
+        Array.Copy(array, index, array, index + toadd, underlyingsize - index);\r
+      int i = index;\r
+      try\r
+      {\r
+\r
+        foreach (T item in items)\r
+        {\r
+#if HASHINDEX\r
+          KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, i);\r
+          if (itemIndex.FindOrAdd(ref p))\r
+            throw new DuplicateNotAllowedException("Item already in indexed list");\r
+#endif\r
+          array[i++] = item;\r
+        }\r
+      }\r
+      finally\r
+      {\r
+        int added = i - index;\r
+        if (added < toadd)\r
+        {\r
+          Array.Copy(array, index + toadd, array, i, underlyingsize - index);\r
+          Array.Clear(array, underlyingsize + added, toadd - added);\r
+        }\r
+        if (added > 0)\r
+        {\r
+          addtosize(added);\r
+#if HASHINDEX\r
+          reindex(i);\r
+#endif\r
+          fixViewsAfterInsert(added, index);\r
+          (underlying ?? this).raiseForInsertAll(index, added);\r
+        }\r
+      }\r
+    }\r
+    private void raiseForInsertAll(int index, int added)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        if ((ActiveEvents & (EventTypeEnum.Added | EventTypeEnum.Inserted)) != 0)\r
+          for (int j = index; j < index + added; j++)\r
+          {\r
+            raiseItemInserted(array[j], j);\r
+            raiseItemsAdded(array[j], 1);\r
+          }\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+\r
+#if HASHINDEX\r
+    /// <summary>\r
+    /// Insert an item at the front of this list;\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException">If the item is already in the list</exception>\r
+    /// <param name="item">The item to insert.</param>\r
+#else\r
+    /// <summary>\r
+    /// Insert an item at the front of this list;\r
+    /// </summary>\r
+    /// <param name="item">The item to insert.</param>\r
+#endif\r
+    [Tested]\r
+    public virtual void InsertFirst(T item)\r
+    {\r
+      updatecheck();\r
+      insert(0, item);\r
+      (underlying ?? this).raiseForInsert(offset, item);\r
+    }\r
+\r
+\r
+#if HASHINDEX\r
+    /// <summary>\r
+    /// Insert an item at the back of this list.\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException">If the item is already in the list</exception>\r
+    /// <param name="item">The item to insert.</param>\r
+#else\r
+    /// <summary>\r
+    /// Insert an item at the back of this list.\r
+    /// </summary>\r
+    /// <param name="item">The item to insert.</param>\r
+#endif\r
+    [Tested]\r
+    public virtual void InsertLast(T item)\r
+    {\r
+      updatecheck();\r
+      insert(size, item);\r
+      (underlying ?? this).raiseForInsert(size - 1 + offset, item);\r
+    }\r
+\r
+\r
+    //NOTE: if the filter throws an exception, no result will be returned.\r
+    /// <summary>\r
+    /// Create a new list consisting of the items of this list satisfying a \r
+    /// certain predicate.\r
+    /// <para>The new list will be of type ArrayList</para>\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(Fun<T, bool> filter)\r
+    {\r
+      validitycheck();\r
+      int stamp = this.stamp;\r
+      ArrayList<T> res = new ArrayList<T>(itemequalityComparer);\r
+      int j = 0, rescap = res.array.Length;\r
+      for (int i = 0; i < size; i++)\r
+      {\r
+        T a = array[offset + i];\r
+        bool found = filter(a);\r
+        modifycheck(stamp);\r
+        if (found)\r
+        {\r
+          if (j == rescap) res.expand(rescap = 2 * rescap, j);\r
+          res.array[j++] = a;\r
+        }\r
+      }\r
+      res.size = j;\r
+#if HASHINDEX\r
+      res.reindex(0);\r
+#endif\r
+      return res;\r
+    }\r
+\r
+\r
+#if HASHINDEX\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 item equalityComparer for the item type V.\r
+    /// <para>The new list will be of type ArrayList</para>\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException">If <code>mapper</code>\r
+    /// creates duplicates</exception>\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
+#else\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 item equalityComparer for the item type V.\r
+    /// <para>The new list will be of type ArrayList</para>\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
+#endif\r
+    [Tested]\r
+    public virtual IList<V> Map<V>(Fun<T, V> mapper)\r
+    {\r
+      validitycheck();\r
+\r
+      ArrayList<V> res = new ArrayList<V>(size);\r
+\r
+      return map<V>(mapper, res);\r
+    }\r
+\r
+#if HASHINDEX\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 item equalityComparer for the item type.\r
+    /// <para>The new list will be of type ArrayList</para>\r
+    /// </summary>\r
+    /// <exception cref="DuplicateNotAllowedException">If <code>mapper</code>\r
+    /// creates duplicates</exception>\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="itemequalityComparer">The item equalityComparer to use for the new list</param>\r
+    /// <returns>The new list.</returns>\r
+#else\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 item equalityComparer for the item type.\r
+    /// <para>The new list will be of type ArrayList</para>\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="itemequalityComparer">The item equalityComparer to use for the new list</param>\r
+    /// <returns>The new list.</returns>\r
+#endif\r
+    public virtual IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer)\r
+    {\r
+      validitycheck();\r
+\r
+      ArrayList<V> res = new ArrayList<V>(size, itemequalityComparer);\r
+\r
+      return map<V>(mapper, res);\r
+    }\r
+\r
+    private IList<V> map<V>(Fun<T, V> mapper, ArrayList<V> res)\r
+    {\r
+      int stamp = this.stamp;\r
+      if (size > 0)\r
+        for (int i = 0; i < size; i++)\r
+        {\r
+          V mappeditem = mapper(array[offset + i]);\r
+          modifycheck(stamp);\r
+#if HASHINDEX\r
+          KeyValuePair<V, int> p = new KeyValuePair<V, int>(mappeditem, i);\r
+          if (res.itemIndex.FindOrAdd(ref p))\r
+            throw new ArgumentException("Mapped item already in indexed list");\r
+#endif\r
+          res.array[i] = mappeditem;\r
+        }\r
+      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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <returns>The removed item.</returns>\r
+    [Tested]\r
+    public virtual T Remove()\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        throw new NoSuchItemException("List is empty");\r
+\r
+      T item = removeAt(fIFO ? 0 : size - 1);\r
+      (underlying ?? this).raiseForRemove(item);\r
+      return item;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove one item from the fromnt of the list.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <returns>The removed item.</returns>\r
+    [Tested]\r
+    public virtual T RemoveFirst()\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        throw new NoSuchItemException("List is empty");\r
+\r
+      T item = removeAt(0);\r
+      (underlying ?? this).raiseForRemoveAt(offset, item);\r
+      return item;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove one item from the back of the list.\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> 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 NoSuchItemException("List is empty");\r
+\r
+      T item = removeAt(size - 1);\r
+      (underlying ?? this).raiseForRemoveAt(size + offset, item);\r
+      return item;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a list view on this list. \r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative\r
+    /// or the range does not fit within list.</exception>\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
+      validitycheck();\r
+      checkRange(start, count);\r
+      if (views == null)\r
+        views = new WeakViewList<ArrayList<T>>();\r
+      ArrayList<T> retval = (ArrayList<T>)MemberwiseClone();\r
+\r
+\r
+      retval.underlying = underlying != null ? underlying : this;\r
+      retval.offset = start + offset;\r
+      retval.size = count;\r
+      retval.myWeakReference = views.Add(retval);\r
+      return retval;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a list view on this list containing the (first) occurrence of a particular item.\r
+    /// <para>Returns <code>null</code> if the item is not in this list.</para>\r
+    /// </summary>\r
+    /// <param name="item">The item to find.</param>\r
+    /// <returns>The new list view.</returns>\r
+    [Tested]\r
+    public virtual IList<T> ViewOf(T item)\r
+    {\r
+      int index = indexOf(item);\r
+      if (index < 0)\r
+        return null;\r
+      return View(index, 1);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a list view on this list containing the last occurrence of a particular item. \r
+    /// <para>Returns <code>null</code> if the item is not in this list.</para>\r
+    /// </summary>\r
+    /// <param name="item">The item to find.</param>\r
+    /// <returns>The new list view.</returns>\r
+    [Tested]\r
+    public virtual IList<T> LastViewOf(T item)\r
+    {\r
+      int index = lastIndexOf(item);\r
+      if (index < 0)\r
+        return null;\r
+      return View(index, 1);\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 virtual 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 virtual int Offset { [Tested]get { return offset; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual bool IsValid { get { return isValid; } }\r
+\r
+    /// <summary>\r
+    /// Slide this list view along the underlying list.\r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation\r
+    /// would bring either end of the view outside the underlying list.</exception>\r
+    /// <param name="offset">The signed amount to slide: positive to slide\r
+    /// towards the end.</param>\r
+    [Tested]\r
+    public virtual IList<T> Slide(int offset)\r
+    {\r
+      if (!TrySlide(offset, size))\r
+        throw new ArgumentOutOfRangeException();\r
+      return this;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Slide this list view along the underlying list, changing its size.\r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation\r
+    /// would bring either end of the view outside the underlying list.</exception>\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 IList<T> Slide(int offset, int size)\r
+    {\r
+      if (!TrySlide(offset, size))\r
+        throw new ArgumentOutOfRangeException();\r
+      return this;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <param name="offset"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public virtual bool TrySlide(int offset)\r
+    {\r
+      return TrySlide(offset, size);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <param name="offset"></param>\r
+    /// <param name="size"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public virtual bool TrySlide(int offset, int size)\r
+    {\r
+      updatecheck();\r
+      if (underlying == null)\r
+        throw new NotAViewException("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
+        return false;\r
+\r
+      this.offset = newoffset;\r
+      this.size = newsize;\r
+      return true;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>\r
+    /// </summary>\r
+    /// <param name="otherView"></param>\r
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>\r
+    /// <returns></returns>\r
+    public virtual IList<T> Span(IList<T> otherView)\r
+    {\r
+      if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this)))\r
+        throw new IncompatibleViewException();\r
+      if (otherView.Offset + otherView.Count - Offset < 0)\r
+        return null;\r
+      return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset);\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()\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      for (int i = 0, length = size / 2, end = offset + size - 1; i < length; i++)\r
+      {\r
+        T swap = array[offset + i];\r
+\r
+        array[offset + i] = array[end - i];\r
+        array[end - i] = swap;\r
+      }\r
+#if HASHINDEX\r
+      reindex(offset, offset + size);\r
+#endif\r
+      //TODO: be more forgiving wrt. disposing\r
+      disposeOverlappingViews(true);\r
+      (underlying ?? this).raiseCollectionChanged();\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this list is sorted according to the default sorting order\r
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class \r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">if T is not comparable</exception>\r
+    /// <returns>True if the list is sorted, else false.</returns>\r
+    [Tested]\r
+    public bool IsSorted() { return IsSorted(Comparer<T>.Default); }\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(SCG.IComparer<T> c)\r
+    {\r
+      validitycheck();\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
+    /// <summary>\r
+    /// Sort the items of the list according to the default sorting order\r
+    /// for the item type T, as defined by the Comparer[T] class \r
+    /// (<see cref="T:C5.Comparer`1"/>).\r
+    /// </summary>\r
+    /// <exception cref="InvalidOperationException">if T is not comparable</exception>\r
+    public virtual void Sort()\r
+    {\r
+      Sort(Comparer<T>.Default);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Sort the items of the list according to a specific sorting order.\r
+    /// </summary>\r
+    /// <param name="comparer">The comparer defining the sorting order.</param>\r
+    [Tested]\r
+    public virtual void Sort(SCG.IComparer<T> comparer)\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      Sorting.IntroSort<T>(array, offset, size, comparer);\r
+      disposeOverlappingViews(false);\r
+#if HASHINDEX\r
+      reindex(offset, offset + size);\r
+#endif\r
+      (underlying ?? this).raiseCollectionChanged();\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Randomly 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
+      if (size == 0)\r
+        return;\r
+      for (int i = offset, top = offset + size, end = top - 1; i < end; i++)\r
+      {\r
+        int j = rnd.Next(i, top);\r
+        if (j != i)\r
+        {\r
+          T tmp = array[i];\r
+          array[i] = array[j];\r
+          array[j] = tmp;\r
+        }\r
+      }\r
+      disposeOverlappingViews(false);\r
+#if HASHINDEX\r
+      reindex(offset, offset + size);\r
+#endif\r
+      (underlying ?? this).raiseCollectionChanged();\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) { validitycheck(); 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 item from the end.</returns>\r
+    [Tested]\r
+    public virtual int LastIndexOf(T item) { validitycheck(); return lastIndexOf(item); }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove the item at a specific position of the list.\r
+    /// </summary>\r
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or\r
+    /// &gt;= the size of the collection.</exception>\r
+    /// <param name="index">The index of the item to remove.</param>\r
+    /// <returns>The removed item.</returns>\r
+    [Tested]\r
+    public virtual T RemoveAt(int index)\r
+    {\r
+      updatecheck();\r
+      if (index < 0 || index >= size)\r
+        throw new IndexOutOfRangeException("Index out of range for sequenced collection");\r
+\r
+      T item = removeAt(index);\r
+      (underlying ?? this).raiseForRemoveAt(offset + index, item);\r
+      return item;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove all items in an index interval.\r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException">If <code>start</code>\r
+    /// and <code>count</code> does not describe a valid interval in the list</exception> \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
+      if (count == 0)\r
+        return;\r
+      checkRange(start, count);\r
+      start += offset;\r
+      fixViewsBeforeRemove(start, count);\r
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();\r
+      for (int i = start, end = start + count; i < end; i++)\r
+      {\r
+        p.Key = array[i];\r
+        itemIndex.Remove(p);\r
+      }\r
+#endif\r
+      Array.Copy(array, start + count, array, start, underlyingsize - start - count);\r
+      addtosize(-count);\r
+      Array.Clear(array, underlyingsize, count);\r
+#if HASHINDEX\r
+      reindex(start);\r
+#endif\r
+      (underlying ?? this).raiseForRemoveInterval(start, count);\r
+    }\r
+    void raiseForRemoveInterval(int start, int count)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseCollectionCleared(size == 0, count, start);\r
+        raiseCollectionChanged();\r
+      }\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\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+#if HASHINDEX\r
+        return Speed.Constant;\r
+#else\r
+        return Speed.Linear;\r
+#endif\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override int GetUnsequencedHashCode()\r
+    { validitycheck(); return base.GetUnsequencedHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="that"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override bool UnsequencedEquals(ICollection<T> that)\r
+    { validitycheck(); return base.UnsequencedEquals(that); }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains (an item equivalent to according to the\r
+    /// itemequalityComparer) 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
+    { validitycheck(); return indexOf(item) >= 0; }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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
+      validitycheck();\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
+    /// itemequalityComparer 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
+      T olditem;\r
+      return Update(item, out olditem);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Update(T item, out T olditem)\r
+    {\r
+      updatecheck();\r
+      int i;\r
+\r
+      if ((i = indexOf(item)) >= 0)\r
+      {\r
+        olditem = array[offset + i];\r
+        array[offset + i] = item;\r
+#if HASHINDEX\r
+        itemIndex.Update(new KeyValuePair<T, int>(item, offset + i));\r
+#endif\r
+        (underlying ?? this).raiseForUpdate(item, olditem);\r
+        return true;\r
+      }\r
+\r
+      olditem = default(T);\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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
+    /// itemequalityComparer 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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool UpdateOrAdd(T item, out T olditem)\r
+    {\r
+      updatecheck();\r
+      if (Update(item, out olditem))\r
+        return true;\r
+\r
+      Add(item);\r
+      olditem = default(T);\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove a particular item from this list. The item will be searched \r
+    /// for from the end of the list if <code>FIFO == false</code> (the default), \r
+    /// else from the start.\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 = fIFO ? indexOf(item) : lastIndexOf(item);\r
+\r
+      if (i < 0)\r
+        return false;\r
+\r
+      T removeditem = removeAt(i);\r
+      (underlying ?? this).raiseForRemove(removeditem);\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. The item will be searched \r
+    /// for from the end of the list if <code>FIFO == false</code> (the default), \r
+    /// else from the start.\r
+    /// </summary>\r
+    /// <param name="item">The value to remove.</param>\r
+    /// <param name="removeditem">The removed value.</param>\r
+    /// <returns>True if the item was found (and removed).</returns>\r
+    [Tested]\r
+    public virtual bool Remove(T item, out T removeditem)\r
+    {\r
+      updatecheck();\r
+\r
+      int i = fIFO ? indexOf(item) : lastIndexOf(item);\r
+\r
+      if (i < 0)\r
+      {\r
+        removeditem = default(T);\r
+        return false;\r
+      }\r
+\r
+      removeditem = removeAt(i);\r
+      (underlying ?? this).raiseForRemove(removeditem);\r
+      return true;\r
+    }\r
+\r
+\r
+    //TODO: remove from end or according to FIFO?\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to remove.</param>\r
+    [Tested]\r
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      //TODO: reactivate the old code for small sizes\r
+      HashBag<T> toremove = new HashBag<T>(itemequalityComparer);\r
+      toremove.AddAll(items);\r
+      if (toremove.Count == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int j = offset;\r
+      int removed = 0;\r
+      int i = offset, end = offset + size;\r
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();\r
+#endif\r
+      while (i < end)\r
+      {\r
+        T item;\r
+        //pass by a stretch of nodes\r
+        while (i < end && !toremove.Contains(item = array[i]))\r
+        {\r
+#if HASHINDEX\r
+          if (j < i)\r
+          {\r
+            p.Key = item;\r
+            p.Value = j;\r
+            itemIndex.Update(p);\r
+          }\r
+#endif\r
+          //if (j<i)\r
+          array[j] = item;\r
+          i++; j++;\r
+        }\r
+        viewHandler.skipEndpoints(removed, i);\r
+        //Remove a stretch of nodes\r
+        while (i < end && toremove.Remove(item = array[i]))\r
+        {\r
+#if HASHINDEX\r
+          p.Key = item;\r
+          itemIndex.Remove(p);\r
+#endif\r
+          if (mustFire)\r
+            raiseHandler.Remove(item);\r
+          removed++;\r
+          i++;\r
+          viewHandler.updateViewSizesAndCounts(removed, i);\r
+        }\r
+      }\r
+      if (removed == 0)\r
+        return;\r
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);\r
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+      addtosize(-removed);\r
+      Array.Clear(array, underlyingsize, removed);\r
+#if HASHINDEX\r
+      reindex(j);\r
+#endif\r
+      if (mustFire)\r
+        raiseHandler.Raise();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    void RemoveAll(Fun<T,bool> predicate)\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int j = offset;\r
+      int removed = 0;\r
+      int i = offset, end = offset + size;\r
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();\r
+#endif\r
+      while (i < end)\r
+      {\r
+        T item;\r
+        //pass by a stretch of nodes\r
+        while (i < end && !predicate(item = array[i]))\r
+        {\r
+          updatecheck();\r
+#if HASHINDEX\r
+          if (j < i)\r
+          {\r
+            p.Key = item;\r
+            p.Value = j;\r
+            itemIndex.Update(p);\r
+          }\r
+#endif\r
+          //if (j<i)\r
+          array[j] = item;\r
+          i++; j++;\r
+        }\r
+        updatecheck();\r
+        viewHandler.skipEndpoints(removed, i);\r
+        //Remove a stretch of nodes\r
+        while (i < end && predicate(item = array[i]))\r
+        {\r
+          updatecheck();\r
+#if HASHINDEX\r
+          p.Key = item;\r
+          itemIndex.Remove(p);\r
+#endif\r
+          if (mustFire)\r
+            raiseHandler.Remove(item);\r
+          removed++;\r
+          i++;\r
+          viewHandler.updateViewSizesAndCounts(removed, i);\r
+        }\r
+        updatecheck();\r
+      }\r
+      if (removed == 0)\r
+        return;\r
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);\r
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+      addtosize(-removed);\r
+      Array.Clear(array, underlyingsize, removed);\r
+#if HASHINDEX\r
+      reindex(j);\r
+#endif\r
+      if (mustFire)\r
+        raiseHandler.Raise();\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
+      if (underlying == null)\r
+      {\r
+        updatecheck();\r
+        if (size == 0)\r
+          return;\r
+        int oldsize = size;\r
+        fixViewsBeforeRemove(0, size);\r
+#if HASHINDEX\r
+        itemIndex.Clear();\r
+#endif\r
+        array = new T[8];\r
+        size = 0;\r
+        (underlying ?? this).raiseForRemoveInterval(offset, oldsize);\r
+      }\r
+      else\r
+        RemoveInterval(0, size);\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.  \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to retain.</param>\r
+    [Tested]\r
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      HashBag<T> toretain = new HashBag<T>(itemequalityComparer);\r
+      toretain.AddAll(items);\r
+      if (toretain.Count == 0)\r
+      {\r
+        Clear();\r
+        return;\r
+      }\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int j = offset;\r
+      int removed = 0;\r
+      int i = offset, end = offset + size;\r
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();\r
+#endif\r
+      while (i < end)\r
+      {\r
+        T item;\r
+        //pass by a stretch of nodes\r
+        while (i < end && toretain.Remove(item = array[i]))\r
+        {\r
+#if HASHINDEX\r
+          if (j < i)\r
+          {\r
+            p.Key = item;\r
+            p.Value = j;\r
+            itemIndex.Update(p);\r
+          }\r
+#endif\r
+          //if (j<i)\r
+          array[j] = item;\r
+          i++; j++;\r
+        }\r
+        viewHandler.skipEndpoints(removed, i);\r
+        //Remove a stretch of nodes\r
+        while (i < end && !toretain.Contains(item = array[i]))\r
+        {\r
+#if HASHINDEX\r
+          p.Key = item;\r
+          itemIndex.Remove(p);\r
+#endif\r
+          if (mustFire)\r
+            raiseHandler.Remove(item);\r
+          removed++;\r
+          i++;\r
+          viewHandler.updateViewSizesAndCounts(removed, i);\r
+        }\r
+      }\r
+      if (removed == 0)\r
+        return;\r
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);\r
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+      addtosize(-removed);\r
+      Array.Clear(array, underlyingsize, removed);\r
+#if HASHINDEX\r
+      reindex(j);\r
+#endif\r
+      raiseHandler.Raise();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    void RetainAll(Fun<T, bool> predicate)\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int j = offset;\r
+      int removed = 0;\r
+      int i = offset, end = offset + size;\r
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();\r
+#endif\r
+      while (i < end)\r
+      {\r
+        T item;\r
+        //pass by a stretch of nodes\r
+        while (i < end && predicate(item = array[i]))\r
+        {\r
+          updatecheck();\r
+#if HASHINDEX\r
+          if (j < i)\r
+          {\r
+            p.Key = item;\r
+            p.Value = j;\r
+            itemIndex.Update(p);\r
+          }\r
+#endif\r
+          //if (j<i)\r
+          array[j] = item;\r
+          i++; j++;\r
+        }\r
+        updatecheck();\r
+        viewHandler.skipEndpoints(removed, i);\r
+        //Remove a stretch of nodes\r
+        while (i < end && !predicate(item = array[i]))\r
+        {\r
+          updatecheck();\r
+#if HASHINDEX\r
+          p.Key = item;\r
+          itemIndex.Remove(p);\r
+#endif\r
+          if (mustFire)\r
+            raiseHandler.Remove(item);\r
+          removed++;\r
+          i++;\r
+          viewHandler.updateViewSizesAndCounts(removed, i);\r
+        }\r
+        updatecheck();\r
+      }\r
+      if (removed == 0)\r
+        return;\r
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);\r
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+      addtosize(-removed);\r
+      Array.Clear(array, underlyingsize, removed);\r
+#if HASHINDEX\r
+      reindex(j);\r
+#endif\r
+      raiseHandler.Raise();\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+    [Tested]\r
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      validitycheck();\r
+#if HASHINDEX\r
+      foreach (T item in items)\r
+        if (indexOf(item) < 0)\r
+          return false;\r
+\r
+      return true;\r
+#else\r
+      //TODO: use aux hash bag to obtain linear time procedure\r
+      HashBag<T> tomatch = new HashBag<T>(itemequalityComparer);\r
+      tomatch.AddAll(items);\r
+      if (tomatch.Count == 0)\r
+        return true;\r
+      for (int i = offset, end = offset + size; i < end; i++)\r
+      {\r
+        tomatch.Remove(array[i]);\r
+        if (tomatch.Count == 0)\r
+          return true;\r
+      }\r
+      return false;\r
+#endif\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
+      validitycheck();\r
+#if HASHINDEX\r
+      return indexOf(item) >= 0 ? 1 : 0;\r
+#else\r
+      int count = 0;\r
+      for (int i = 0; i < size; i++)\r
+        if (equals(item, array[offset + i]))\r
+          count++;\r
+      return count;\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<T> UniqueItems()\r
+    {\r
+#if HASHINDEX\r
+      return this;\r
+#else\r
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);\r
+      hashbag.AddAll(this);\r
+      return hashbag.UniqueItems();\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()\r
+    {\r
+#if HASHINDEX\r
+      return new MultiplicityOne<T>(this);\r
+#else\r
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);\r
+      hashbag.AddAll(this);\r
+      return hashbag.ItemMultiplicities();\r
+#endif\r
+    }\r
+\r
+\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
+#if HASHINDEX\r
+      Remove(item);\r
+#else\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int j = offset;\r
+      int removed = 0;\r
+      int i = offset, end = offset + size;\r
+      while (i < end)\r
+      {\r
+        //pass by a stretch of nodes\r
+        while (i < end && !equals(item, array[i]))\r
+          array[j++] = array[i++];\r
+        viewHandler.skipEndpoints(removed, i);\r
+        //Remove a stretch of nodes\r
+        while (i < end && equals(item, array[i]))\r
+        {\r
+          if (mustFire)\r
+            raiseHandler.Remove(array[i]);\r
+          removed++;\r
+          i++;\r
+          viewHandler.updateViewSizesAndCounts(removed, i);\r
+        }\r
+      }\r
+      if (removed == 0)\r
+        return;\r
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);\r
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);\r
+      addtosize(-removed);\r
+      Array.Clear(array, underlyingsize, removed);\r
+      raiseHandler.Raise();\r
+#endif\r
+    }\r
+\r
+\r
+    //TODO: check views\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
+#if HASHINDEX\r
+      if (underlyingsize != itemIndex.Count)\r
+      {\r
+        Console.WriteLine("size ({0})!= index.Count ({1})", size, itemIndex.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 (!itemIndex.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
+#endif\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\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+#if HASHINDEX\r
+        return false;\r
+#else\r
+        return true;\r
+#endif\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting\r
+    {\r
+      get\r
+      {\r
+#if HASHINDEX\r
+        return true;\r
+#else\r
+        return false;\r
+#endif\r
+      }\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
+#if HASHINDEX\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, size + offset);\r
+      if (itemIndex.FindOrAdd(ref p))\r
+        return false;\r
+#endif\r
+      baseinsert(size, item);\r
+#if HASHINDEX\r
+      reindex(size + offset);\r
+#endif\r
+      (underlying ?? this).raiseForAdd(item);\r
+      return true;\r
+    }\r
+    \r
+\r
+    /// <summary>\r
+    /// Add the elements from another collection to this collection.\r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items"></param>\r
+    [Tested]\r
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      int toadd = EnumerableBase<U>.countItems(items);\r
+      if (toadd == 0)\r
+        return;\r
+\r
+      if (toadd + underlyingsize > array.Length)\r
+        expand(toadd + underlyingsize, underlyingsize);\r
+\r
+      int i = size + offset;\r
+      if (underlyingsize > i)\r
+        Array.Copy(array, i, array, i + toadd, underlyingsize - i);\r
+      try\r
+      {\r
+        foreach (T item in items)\r
+        {\r
+#if HASHINDEX\r
+          KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, i);\r
+          if (itemIndex.FindOrAdd(ref p))\r
+            continue;\r
+#endif\r
+          array[i++] = item;\r
+        }\r
+      }\r
+      finally\r
+      {\r
+        int added = i - size - offset;\r
+        if (added < toadd)\r
+        {\r
+          Array.Copy(array, size + offset + toadd, array, i, underlyingsize - size - offset);\r
+          Array.Clear(array, underlyingsize + added, toadd - added);\r
+        }\r
+        if (added > 0)\r
+        {\r
+          addtosize(added);\r
+#if HASHINDEX\r
+          reindex(i);\r
+#endif\r
+          fixViewsAfterInsert(added, i - added);\r
+          (underlying ?? this).raiseForAddAll(i - added, added);\r
+        }\r
+      }\r
+    }\r
+    private void raiseForAddAll(int start, int added)\r
+    {\r
+      if ((ActiveEvents & EventTypeEnum.Added) != 0)\r
+        for (int i = start, end = start + added; i < end; i++)\r
+          raiseItemsAdded(array[i], 1);\r
+      raiseCollectionChanged();\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 ICollectionValue<T> Members\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The number of items in this collection</value>\r
+    [Tested]\r
+    public override int Count { [Tested]get { validitycheck(); return size; } }\r
+    #endregion\r
+\r
+    #region IEnumerable<T> Members\r
+    //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException)\r
+    /// <summary>\r
+    /// Create an enumerator for the collection\r
+    /// </summary>\r
+    /// <returns>The enumerator</returns>\r
+    [Tested]\r
+    public override SCG.IEnumerator<T> GetEnumerator()\r
+    {\r
+      validitycheck();\r
+      return base.GetEnumerator();\r
+    }\r
+    #endregion\r
+\r
+#if HASHINDEX\r
+#else\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 virtual void Push(T item)\r
+    {\r
+      InsertLast(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 virtual 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 virtual void Enqueue(T item)\r
+    {\r
+      InsertLast(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 virtual T Dequeue()\r
+    {\r
+      return RemoveFirst();\r
+    }\r
+\r
+    #endregion\r
+#endif\r
+    #region IDisposable Members\r
+\r
+    /// <summary>\r
+    /// Invalidate this list. If a view, just invalidate the view. \r
+    /// If not a view, invalidate the list and all views on it.\r
+    /// </summary>\r
+    public virtual void Dispose()\r
+    {\r
+      Dispose(false);\r
+    }\r
+\r
+    void Dispose(bool disposingUnderlying)\r
+    {\r
+      if (isValid)\r
+      {\r
+        if (underlying != null)\r
+        {\r
+          isValid = false;\r
+          if (!disposingUnderlying)\r
+            views.Remove(myWeakReference);\r
+          underlying = null;\r
+          views = null;\r
+          myWeakReference = null;\r
+        }\r
+        else\r
+        {\r
+          //isValid = false;\r
+          foreach (ArrayList<T> view in views)\r
+            view.Dispose(true);\r
+          Clear();\r
+        }\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this ArrayList.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      ArrayList<T> clone = new ArrayList<T>(size, itemequalityComparer);\r
+      clone.AddAll(this);\r
+      return clone;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ISerializable Members\r
+/*\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="info"></param>\r
+    /// <param name="context"></param>\r
+    public ArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :\r
+      this(info.GetInt32("sz"),(SCG.IEqualityComparer<T>)(info.GetValue("eq",typeof(SCG.IEqualityComparer<T>))))\r
+    {\r
+      size = info.GetInt32("sz");\r
+      for (int i = 0; i < size; i++)\r
+      {\r
+        array[i] = (T)(info.GetValue("elem" + i,typeof(T)));\r
+      }\r
+#if HASHINDEX\r
+      reindex(0);\r
+#endif      \r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="info"></param>\r
+    /// <param name="context"></param>\r
+    public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)\r
+    {\r
+      info.AddValue("sz", size);\r
+      info.AddValue("eq", EqualityComparer);\r
+      for (int i = 0; i < size; i++)\r
+                       {\r
+        info.AddValue("elem" + i, array[i + offset]);\r
+      }\r
+    }\r
+*/\r
+#endregion\r
+  }\r
+}\r
diff --git a/mcs/class/Mono.C5/C5/arrays/CircularQueue.cs b/mcs/class/Mono.C5/C5/arrays/CircularQueue.cs
new file mode 100644 (file)
index 0000000..05fe216
--- /dev/null
@@ -0,0 +1,334 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// \r
+  /// </summary>\r
+  /// <typeparam name="T"></typeparam>\r
+  public class CircularQueue<T> : SequencedBase<T>, IQueue<T>, IStack<T>\r
+  {\r
+    #region Fields\r
+    /*\r
+        Invariant: the itemes in the queue ar the elements from front upwards, \r
+        possibly wrapping around at the end of array, to back.\r
+\r
+        if front<=back then size = back - front + 1;\r
+        else size = array.Length + back - front + 1;\r
+\r
+        */\r
+    int front, back;\r
+    /// <summary>\r
+    /// The internal container array is doubled when necessary, but never shrinked.\r
+    /// </summary>\r
+    T[] array;\r
+    bool forwards = true, original = true;\r
+    #endregion\r
+\r
+    #region Events\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }\r
+\r
+    #endregion\r
+\r
+    #region Util\r
+    void expand()\r
+    {\r
+      int newlength = 2 * array.Length;\r
+      T[] newarray = new T[newlength];\r
+\r
+      if (front <= back)\r
+        Array.Copy(array, front, newarray, 0, size);\r
+      else\r
+      {\r
+        int half = array.Length - front;\r
+        Array.Copy(array, front, newarray, 0, half);\r
+        Array.Copy(array, 0, newarray, half, size - half);\r
+      }\r
+\r
+      front = 0;\r
+      back = size;\r
+      array = newarray;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region Constructors\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public CircularQueue() : this(8) { }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="capacity"></param>\r
+    public CircularQueue(int capacity)\r
+      : base(EqualityComparer<T>.Default)\r
+    {\r
+      int newlength = 8;\r
+      while (newlength < capacity) newlength *= 2;\r
+      array = new T[newlength];\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IQueue<T> Members\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual bool AllowsDuplicates { get { return true; } }\r
+\r
+    /// <summary>\r
+    /// Get the i'th item in the queue. The front of the queue is at index 0.\r
+    /// </summary>\r
+    /// <param name="i"></param>\r
+    /// <returns></returns>\r
+    public virtual T this[int i]\r
+    {\r
+      get\r
+      {\r
+        if (i < 0 || i >= size)\r
+          throw new IndexOutOfRangeException();\r
+        i = i + front;\r
+        return array[i >= size ? i - size : i];\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    [Tested]\r
+    public virtual void Enqueue(T item)\r
+    {\r
+      if (!original)\r
+        throw new ReadOnlyCollectionException();\r
+      stamp++;\r
+      if (size == array.Length - 1) expand();\r
+      size++;\r
+      int oldback = back++;\r
+      if (back == array.Length) back = 0;\r
+      array[oldback] = item;\r
+      if (ActiveEvents != 0)\r
+        raiseForAdd(item);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public virtual T Dequeue()\r
+    {\r
+      if (!original)\r
+        throw new ReadOnlyCollectionException("Object is a non-updatable clone");\r
+      stamp++;\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+      size--;\r
+      int oldfront = front++;\r
+      if (front == array.Length) front = 0;\r
+      T retval = array[oldfront];\r
+      array[oldfront] = default(T);\r
+      if (ActiveEvents != 0)\r
+        raiseForRemove(retval);\r
+      return retval;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    public void Push(T item) //== Enqueue\r
+    {\r
+      if (!original)\r
+        throw new ReadOnlyCollectionException();\r
+      stamp++;\r
+      if (size == array.Length - 1) expand();\r
+      size++;\r
+      int oldback = back++;\r
+      if (back == array.Length) back = 0;\r
+      array[oldback] = item;\r
+      if (ActiveEvents != 0)\r
+        raiseForAdd(item);\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public T Pop()\r
+    {\r
+      if (!original)\r
+        throw new ReadOnlyCollectionException("Object is a non-updatable clone");\r
+      stamp++;\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+      size--;\r
+      back--;\r
+      if (back == -1) back = array.Length - 1;\r
+      T retval = array[back];\r
+      array[back] = default(T);\r
+      if (ActiveEvents != 0)\r
+        raiseForRemove(retval);\r
+      return retval;\r
+    }\r
+    #endregion\r
+\r
+    #region ICollectionValue<T> Members\r
+\r
+    //TODO: implement these with Array.Copy instead of relying on XxxBase:\r
+    /*\r
+        public void CopyTo(T[] a, int i)\r
+        {\r
+        }\r
+\r
+        public T[] ToArray()\r
+        {\r
+        }*/\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override T Choose()\r
+    {\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+      return array[front];\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IEnumerable<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override SCG.IEnumerator<T> GetEnumerator()\r
+    {\r
+      int stamp = this.stamp;\r
+      if (forwards)\r
+      {\r
+        int position = front;\r
+        int end = front <= back ? back : array.Length;\r
+        while (position < end)\r
+        {\r
+          if (stamp != this.stamp)\r
+            throw new CollectionModifiedException();\r
+          yield return array[position++];\r
+        }\r
+        if (front > back)\r
+        {\r
+          position = 0;\r
+          while (position < back)\r
+          {\r
+            if (stamp != this.stamp)\r
+              throw new CollectionModifiedException();\r
+            yield return array[position++];\r
+          }\r
+        }\r
+      }\r
+      else\r
+      {\r
+        int position = back - 1;\r
+        int end = front <= back ? front : 0;\r
+        while (position >= end)\r
+        {\r
+          if (stamp != this.stamp)\r
+            throw new CollectionModifiedException();\r
+          yield return array[position--];\r
+        }\r
+        if (front > back)\r
+        {\r
+          position = array.Length - 1;\r
+          while (position >= front)\r
+          {\r
+            if (stamp != this.stamp)\r
+              throw new CollectionModifiedException();\r
+            yield return array[position--];\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedCollectionValue<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override IDirectedCollectionValue<T> Backwards()\r
+    {\r
+      CircularQueue<T> retval = (CircularQueue<T>)MemberwiseClone();\r
+      retval.original = false;\r
+      retval.forwards = !forwards;\r
+      return retval;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()\r
+    {\r
+      return Backwards();\r
+    }\r
+\r
+    #endregion\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual bool Check()\r
+    {\r
+      if (front < 0 || front >= array.Length || back < 0 || back >= array.Length ||\r
+          (front <= back && size != back - front) || (front > back && size != array.Length + back - front))\r
+      {\r
+        Console.WriteLine("Bad combination of (front,back,size,array.Length): ({0},{1},{2},{3})",\r
+            front, back, size, array.Length);\r
+        return false;\r
+      }\r
+      return true;\r
+    }\r
+  }\r
+}
\ No newline at end of file
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..b7bc753
--- /dev/null
@@ -0,0 +1,1266 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = System.Collections.Generic;\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// A collection class implementing a sorted dynamic array data structure.\r
+  /// </summary>\r
+  [Serializable]\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
+    SCG.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 ~ind;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region Constructors\r
+\r
+    /// <summary>\r
+    /// Create a dynamic sorted array with a natural comparer\r
+    /// (and item equalityComparer,  assumed compatible)\r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">If <code>T</code> is not comparable.\r
+    /// </exception>\r
+    public SortedArray() : this(8) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a dynamic sorted array with a natural comparer \r
+    /// (and item equalityComparer,  assumed compatible)\r
+    /// and prescribed initial capacity.\r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">If <code>T</code> is not comparable.\r
+    /// </exception>\r
+    /// <param name="capacity">The capacity</param>\r
+    public SortedArray(int capacity)\r
+      : this(capacity, Comparer<T>.Default, EqualityComparer<T>.Default) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a dynamic sorted array with an external comparer.\r
+    /// <para>The itemequalityComparer will be compatible \r
+    /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the \r
+    /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)\r
+    /// is unlikely to be compatible with the external comparer. This makes the\r
+    /// array inadequate for use as item in a collection of unsequenced or sequenced sets or bags\r
+    /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)\r
+    /// </para>\r
+    /// </summary>\r
+    /// <param name="comparer">The comparer</param>\r
+    public SortedArray(SCG.IComparer<T> comparer)\r
+      : this(8, comparer) { }\r
+\r
+    /// <summary>\r
+    /// Create a dynamic sorted array with an external comparer\r
+    /// and prescribed initial capacity.\r
+    /// <para>The itemequalityComparer will be a compatible \r
+    /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the \r
+    /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)\r
+    /// is unlikely to be compatible with the external comparer. This makes the\r
+    /// sorted array inadequate for use as item in a collection of unsequenced or sequenced sets or bags\r
+    /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)\r
+    /// </para>\r
+    /// </summary>\r
+    /// <param name="capacity">The capacity</param>\r
+    /// <param name="comparer">The comparer</param>\r
+    public SortedArray(int capacity, SCG.IComparer<T> comparer)\r
+      : this(capacity, comparer, new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }\r
+\r
+    /// <summary>\r
+    /// Create a dynamic sorted array with an external comparer, an external item equalityComparer\r
+    /// and prescribed initial capacity. This is the constructor to use if the collection \r
+    /// will be used as item in a hash table based collection.\r
+    /// </summary>\r
+    /// <param name="capacity">The capacity</param>\r
+    /// <param name="comparer">The item comparer</param>\r
+    /// <param name="equalityComparer">The item equalityComparer (assumed compatible)</param>\r
+    public SortedArray(int capacity, SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> equalityComparer)\r
+      : base(capacity, equalityComparer)\r
+    {\r
+      if (comparer == null)\r
+        throw new NullReferenceException("Comparer cannot be null");\r
+      this.comparer = comparer;\r
+    }\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(Fun<T, bool> 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>(Fun<T, V> m, SCG.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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is less than or equal to the minimum of this collection.)</exception>\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 NoSuchItemException();\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is greater than or equal to the maximum of this collection.)</exception>\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 NoSuchItemException();\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="NoSuchItemException"/> 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 NoSuchItemException();\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is greater than the maximum of this collection.)</exception>\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 NoSuchItemException();\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-increasing (i.e. weakly decrerasing) function from the item type to \r
+    /// <code>int</code> is\r
+    /// negative, zero respectively positive. If the supplied cut function is\r
+    /// not non-increasing, 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 positive (if any).</param>\r
+    /// <param name="lowIsValid">True if the cut function is positive somewhere\r
+    /// on this collection.</param>\r
+    /// <param name="high">Returns the least item in the collection, where the\r
+    /// cut function is negative (if any).</param>\r
+    /// <param name="highIsValid">True if the cut function is negative 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
+    /// <typeparam name="U"></typeparam>\r
+    [Tested]\r
+    public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T\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<U>.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 ICollection<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
+    /// <summary>\r
+    /// Check if this collection contains (an item equivalent to according to the\r
+    /// itemequalityComparer) 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
+    /// itemequalityComparer 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
+    /// itemequalityComparer 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
+    /// itemequalityComparer 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
+    { T olditem; return Update(item, out olditem); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public bool Update(T item, out T olditem)\r
+    {\r
+      updatecheck();\r
+\r
+      int ind;\r
+\r
+      if (binarySearch(item, out ind))\r
+      {\r
+        olditem = array[ind];\r
+        array[ind] = item;\r
+        return true;\r
+      }\r
+\r
+      olditem = default(T);\r
+      return false;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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
+    { T olditem; return UpdateOrAdd(item, out olditem); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public bool UpdateOrAdd(T item, out T olditem)\r
+    {\r
+      updatecheck();\r
+\r
+      int ind;\r
+\r
+      if (binarySearch(item, out ind))\r
+      {\r
+        olditem = array[ind];\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
+      olditem = default(T);\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.</param>\r
+    /// <param name="removeditem">The removed value.</param>\r
+    /// <returns>True if the item was found (and removed).</returns>\r
+    [Tested]\r
+    public bool Remove(T item, out T removeditem)\r
+    {\r
+      int ind;\r
+\r
+      updatecheck();\r
+      if (binarySearch(item, out ind))\r
+      {\r
+        removeditem = array[ind];\r
+        Array.Copy(array, ind + 1, array, ind, size - ind - 1);\r
+        array[--size] = default(T);\r
+        return true;\r
+      }\r
+\r
+      removeditem = default(T);\r
+      return false;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove all items in another collection from this one. \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to remove.</param>\r
+    [Tested]\r
+    public void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T\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
+    /// <summary>\r
+    /// Remove all items not in some other collection from this one. \r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to retain.</param>\r
+    [Tested]\r
+    public void RetainAll<U>(SCG.IEnumerable<U> items) where U : T\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
+    /// <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
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+    [Tested]\r
+    public bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T\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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<T> UniqueItems() { return this; }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()\r
+    {\r
+      return new MultiplicityOne<T>(this);\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 IExtensible<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
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting { get { return true; } }\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
+    /// <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
+    [Tested]\r
+    public void AddAll<U>(SCG.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, 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 NoSuchItemException();\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 NoSuchItemException();\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 NoSuchItemException();\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 NoSuchItemException();\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 SCG.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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual Speed IndexingSpeed { get { return Speed.Constant; } }\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 collectionvalue");\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
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this SortedArray.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      SortedArray<T> clone = new SortedArray<T>(size, comparer, itemequalityComparer);\r
+      clone.AddSorted(this);\r
+      return clone;\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+}
\ No newline at end of file
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..e8ad80a
--- /dev/null
@@ -0,0 +1,678 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = 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
+  [Serializable]\r
+  public class HashBag<T> : CollectionBase<T>, ICollection<T>\r
+  {\r
+    #region Fields\r
+    HashSet<KeyValuePair<T, int>> dict;\r
+    #endregion\r
+\r
+    #region Events\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }\r
+\r
+    #endregion\r
+\r
+    #region Constructors\r
+    /// <summary>\r
+    /// Create a hash bag with the deafult item equalityComparer.\r
+    /// </summary>\r
+    public HashBag() : this(EqualityComparer<T>.Default) { }\r
+\r
+    /// <summary>\r
+    /// Create a hash bag with an external item equalityComparer.\r
+    /// </summary>\r
+    /// <param name="itemequalityComparer">The external item equalityComparer.</param>\r
+    public HashBag(SCG.IEqualityComparer<T> itemequalityComparer)\r
+      : base(itemequalityComparer)\r
+    {\r
+      dict = new HashSet<KeyValuePair<T, int>>(new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a hash bag with external item equalityComparer, prescribed initial table size 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="itemequalityComparer">The external item equalityComparer</param>\r
+    public HashBag(int capacity, SCG.IEqualityComparer<T> itemequalityComparer)\r
+      : base(itemequalityComparer)\r
+    {\r
+      dict = new HashSet<KeyValuePair<T, int>>(capacity, new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a hash bag with external item equalityComparer, prescribed initial table size and fill threshold.\r
+    /// </summary>\r
+    /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>\r
+    /// <param name="fill">Fill threshold (valid range 10% to 90%)</param>\r
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>\r
+    public HashBag(int capacity, double fill, SCG.IEqualityComparer<T> itemequalityComparer)\r
+      : base(itemequalityComparer)\r
+    {\r
+      dict = new HashSet<KeyValuePair<T, int>>(capacity, fill, new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));\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
+    /// <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
+    { T olditem = default(T); return Update(item, out olditem); }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Update(T item, out T olditem)\r
+    {\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);\r
+\r
+      updatecheck();\r
+\r
+      //Note: we cannot just do dict.Update: we have to lookup the count before we \r
+      //know what to update with. There is of course a way around if we use the \r
+      //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
+        olditem = p.Key;\r
+        p.Key = item;\r
+        dict.Update(p);\r
+        if (ActiveEvents != 0)\r
+          raiseForUpdate(item, olditem, p.Value);\r
+        return true;\r
+      }\r
+\r
+      olditem = default(T);\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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool UpdateOrAdd(T item, out T olditem)\r
+    {\r
+      updatecheck();\r
+      if (Update(item, out olditem))\r
+        return true;\r
+\r
+      Add(item);\r
+      return false;\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
+        if (ActiveEvents != 0)\r
+          raiseForRemove(p.Key);\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">The value to remove.</param>\r
+    /// <param name="removeditem">The removed value.</param>\r
+    /// <returns>True if item was found.</returns>\r
+    [Tested]\r
+    public virtual bool Remove(T item, out T removeditem)\r
+    {\r
+      updatecheck();\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);\r
+      if (dict.Find(ref p))\r
+      {\r
+        removeditem = 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
+        if (ActiveEvents != 0)\r
+          raiseForRemove(removeditem);\r
+\r
+        return true;\r
+      }\r
+\r
+      removeditem = default(T);\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove all items in a supplied collection from this bag, counting multiplicities.\r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to remove.</param>\r
+    [Tested]\r
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+#warning Improve if items is a counting bag\r
+      updatecheck();\r
+      bool mustRaise = (ActiveEvents & (EventTypeEnum.Changed | EventTypeEnum.Removed)) != 0;\r
+      RaiseForRemoveAllHandler raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null;\r
+      foreach (U item in items)\r
+      {\r
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);\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
+          if (mustRaise)\r
+            raiseHandler.Remove(p.Key);\r
+        }\r
+      }\r
+      if (mustRaise)\r
+        raiseHandler.Raise();\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
+      if (size == 0)\r
+        return;\r
+      dict.Clear();\r
+      int oldsize = size;\r
+      size = 0;\r
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)\r
+        raiseCollectionCleared(true, oldsize);\r
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove all items *not* in a supplied collection from this bag,\r
+    /// counting multiplicities.\r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to retain</param>\r
+    [Tested]\r
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+\r
+      HashBag<T> res = new HashBag<T>(itemequalityComparer);\r
+\r
+      foreach (U item in items)\r
+      {\r
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(item);\r
+        if (dict.Find(ref p))\r
+        {\r
+          KeyValuePair<T, int> q = p;\r
+          if (res.dict.Find(ref q))\r
+          {\r
+            if (q.Value < p.Value)\r
+            {\r
+              q.Value++;\r
+              res.dict.Update(q);\r
+              res.size++;\r
+            }\r
+          }\r
+          else\r
+          {\r
+            q.Value = 1;\r
+            res.dict.Add(q);\r
+            res.size++;\r
+          }\r
+        }\r
+      }\r
+\r
+      if (size == res.size)\r
+        return;\r
+\r
+      CircularQueue<T> wasRemoved = null;\r
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)\r
+      {\r
+        wasRemoved = new CircularQueue<T>();\r
+        foreach (KeyValuePair<T, int> p in dict)\r
+        {\r
+          int removed = p.Value - res.ContainsCount(p.Key);\r
+          if (removed > 0)\r
+#warning We could send bag events here easily using a CircularQueue of (should?)\r
+            for (int i = 0; i < removed; i++)\r
+              wasRemoved.Enqueue(p.Key);\r
+        }\r
+      }\r
+      dict = res.dict;\r
+      size = res.size;\r
+\r
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)\r
+        raiseForRemoveAll(wasRemoved);\r
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if all items are found.</returns>\r
+    [Tested]\r
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      HashBag<T> res = new HashBag<T>(itemequalityComparer);\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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<T> UniqueItems() { return new DropMultiplicity<T>(dict); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()\r
+    {\r
+      return new GuardedCollectionValue<KeyValuePair<T, int>>(dict);\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
+        if ((ActiveEvents & EventTypeEnum.Removed) != 0)\r
+          raiseItemsRemoved(p.Key, p.Value);\r
+        if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+          raiseCollectionChanged();\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="array">The array to copy to</param>\r
+    /// <param name="index">The starting index.</param>\r
+    [Tested]\r
+    public override void CopyTo(T[] array, int index)\r
+    {\r
+      if (index < 0 || index >= array.Length || index + Count > array.Length)\r
+        throw new ArgumentOutOfRangeException();\r
+\r
+      foreach (KeyValuePair<T, int> p in dict)\r
+        for (int j = 0; j < p.Value; j++)\r
+          array[index++] = p.Key;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IExtensible<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
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting { get { return true; } }\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
+      updatecheck();\r
+      add(ref item);\r
+      if (ActiveEvents != 0)\r
+        raiseForAdd(item);\r
+      return true;\r
+    }\r
+\r
+    private void add(ref T item)\r
+    {\r
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 1);\r
+      if (dict.Find(ref p))\r
+      {\r
+        p.Value++;\r
+        dict.Update(p);\r
+        item = p.Key;\r
+      }\r
+      else\r
+        dict.Add(p);\r
+      size++;\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>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+#warning We could easily raise bag events\r
+      bool mustRaiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;\r
+      CircularQueue<T> wasAdded = mustRaiseAdded ? new CircularQueue<T>() : null;\r
+      bool wasChanged = false;\r
+      foreach (T item in items)\r
+      {\r
+        T jtem = item;\r
+        add(ref jtem);\r
+        wasChanged = true;\r
+        if (mustRaiseAdded)\r
+          wasAdded.Enqueue(jtem);\r
+      }\r
+      if (!wasChanged)\r
+        return;\r
+      if (mustRaiseAdded)\r
+        foreach (T item in wasAdded)\r
+          raiseItemsAdded(item, 1);\r
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IEnumerable<T> Members\r
+\r
+\r
+    /// <summary>\r
+    /// Choose some item of this collection. \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    public override T Choose()\r
+    {\r
+      return dict.Choose().Key;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create an enumerator for this bag.\r
+    /// </summary>\r
+    /// <returns>The enumerator</returns>\r
+    [Tested]\r
+    public override SCG.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 CollectionModifiedException();\r
+\r
+          left--;\r
+          yield return p.Key;\r
+        }\r
+      }\r
+    }\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this HashBag.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      //TODO: make sure this \r
+      HashBag<T> clone = new HashBag<T>(dict.Count > 0 ? dict.Count : 1, itemequalityComparer);\r
+      //TODO: make sure this really adds in the counting bag way!\r
+      clone.AddAll(this);\r
+      return clone;\r
+    }\r
+\r
+    #endregion\r
+\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
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..84adde2
--- /dev/null
@@ -0,0 +1,77 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = 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
+  [Serializable]\r
+  public class HashDictionary<K, V> : DictionaryBase<K, V>, IDictionary<K, V>\r
+  {\r
+    /// <summary>\r
+    /// Create a hash dictionary using a default equalityComparer 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() : this(EqualityComparer<K>.Default) { }\r
+\r
+    /// <summary>\r
+    /// Create a hash dictionary using a custom equalityComparer 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="keyequalityComparer">The external key equalityComparer</param>\r
+    public HashDictionary(SCG.IEqualityComparer<K> keyequalityComparer) : base(keyequalityComparer)\r
+    {\r
+      pairs = new HashSet<KeyValuePair<K, V>>(new KeyValuePairEqualityComparer<K, V>(keyequalityComparer));\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a hash dictionary using a custom equalityComparer 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="keyequalityComparer">The external key equalityComparer</param>\r
+    public HashDictionary(int capacity, double fill, SCG.IEqualityComparer<K> keyequalityComparer): base(keyequalityComparer)\r
+    {\r
+      pairs = new HashSet<KeyValuePair<K, V>>(capacity, fill, new KeyValuePairEqualityComparer<K, V>(keyequalityComparer));\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override object Clone()\r
+    {\r
+      HashDictionary<K, V> clone = new HashDictionary<K, V>(EqualityComparer);\r
+      clone.pairs.AddAll(pairs);\r
+      return clone;\r
+    }\r
+\r
+  }\r
+}
\ No newline at end of file
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..0db8f66
--- /dev/null
@@ -0,0 +1,1600 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 LINEARPROBINGnot\r
+#define REFBUCKET\r
+#define SHRINKnot\r
+#define INTERHASHINGnot\r
+#define RANDOMINTERHASHING\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// A set collection class based on linear hashing\r
+  /// </summary>\r
+  [Serializable]\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
+      InterHashing = 32,\r
+      /// <summary>\r
+      /// Use a universal family of hash functions on item hash code\r
+      /// </summary>\r
+      RandomInterHashing = 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 INTERHASHING\r
+               | Feature.InterHashing\r
+#elif RANDOMINTERHASHING\r
+ | Feature.RandomInterHashing\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, lastchosen; //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 RANDOMINTERHASHING\r
+#if DEBUG\r
+    const uint randomhashfactor = 1529784659;\r
+#else\r
+    uint randomhashfactor = (2 * (uint)(new Random()).Next() + 1) * 1529784659;\r
+#endif\r
+#endif\r
+\r
+    #endregion\r
+\r
+    #region Events\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }\r
+\r
+    #endregion\r
+\r
+    #region Bucket nested class(es)\r
+#if REFBUCKET\r
+    [Serializable]\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 = default(OverflowBucket);\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 itemequalityComparer.Equals(i1, i2); }\r
+\r
+#if !REFBUCKET\r
+    bool isnull(T item) { return itemequalityComparer.Equals(item, default(T)); }\r
+#endif\r
+\r
+    int gethashcode(T item) { return itemequalityComparer.GetHashCode(item); }\r
+\r
+\r
+    int hv2i(int hashval)\r
+    {\r
+#if INTERHASHING\r
+                       //Note: *inverse  mod 2^32 is -1503427877\r
+                       return (int)(((uint)hashval * 1529784659) >>bitsc); \r
+#elif RANDOMINTERHASHING\r
+      return (int)(((uint)hashval * randomhashfactor) >> 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
+    /// <summary>\r
+    /// Search for an item equal (according to itemequalityComparer) to the supplied item.  \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="add">If true, add item to table if not found.</param>\r
+    /// <param name="update">If true, update table entry if item found.</param>\r
+    /// <param name="raise">If true raise events</param>\r
+    /// <returns>True if found</returns>\r
+    private bool searchoradd(ref T item, bool add, bool update, bool raise)\r
+    {\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
+        T olditem = b.item;\r
+        if (equals(olditem, item))\r
+        {\r
+          if (update)\r
+            b.item = item;\r
+          else\r
+            item = olditem;\r
+\r
+          if (raise && update)\r
+            raiseForUpdate(item, olditem);\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
+          T olditem = defaultitem;\r
+          if (update)\r
+            defaultitem = item;\r
+          else\r
+            item = defaultitem;\r
+\r
+          if (raise && update)\r
+            raiseForUpdate(item, olditem);\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
+            if (raise && update)\r
+              raiseForUpdate(item, t);\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
+          T olditem = b.item;\r
+          if (equals(olditem, item))\r
+          {\r
+            if (update)\r
+            {\r
+              b.item = item;\r
+            }\r
+            item = b.item;\r
+\r
+            if (raise && update)\r
+              raiseForUpdate(item, olditem);\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
+          T olditem = defaultitem;\r
+          if (update)\r
+            defaultitem = item;\r
+          else\r
+            item = defaultitem;\r
+\r
+          if (raise && update)\r
+            raiseForUpdate(item, olditem);\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
+            if (raise && update)\r
+              raiseForUpdate(item, b.item);\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
+            T olditem = ob.item;\r
+                                               while (ob.overflow != null)\r
+                                               {\r
+              if (equals(item, olditem))\r
+              {\r
+                if (update)\r
+                  ob.item = item;\r
+                else\r
+                  item = olditem;\r
+\r
+                if (raise && update)\r
+                  raiseForUpdate(item, olditem);\r
+                return true;\r
+              }\r
+\r
+                                                       ob = ob.overflow;\r
+              olditem = ob.item;\r
+                                               }\r
+\r
+            if (equals(item, olditem))\r
+            {\r
+              if (update)\r
+                ob.item = item;\r
+              else\r
+                item = olditem;\r
+\r
+              if (raise && update)\r
+                raiseForUpdate(item, olditem);\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
+      if (raise && add)\r
+        raiseForAdd(item);\r
+      return false;\r
+    }\r
+\r
+\r
+    private bool remove(ref T item)\r
+    {\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].item;\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
+      {\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 equalityComparer and default fill threshold (66%)\r
+    /// and initial table size (16).\r
+    /// </summary>\r
+    public HashSet() \r
+                       : this(EqualityComparer<T>.Default) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a hash set with external item equalityComparer and default fill threshold (66%)\r
+    /// and initial table size (16).\r
+    /// </summary>\r
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>\r
+    public HashSet(SCG.IEqualityComparer<T> itemequalityComparer) \r
+                       : this(16, itemequalityComparer) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a hash set with external item equalityComparer 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="itemequalityComparer">The external item equalityComparer</param>\r
+    public HashSet(int capacity, SCG.IEqualityComparer<T> itemequalityComparer) \r
+                       : this(capacity, 0.66, itemequalityComparer) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a hash set with external item equalityComparer.\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="itemequalityComparer">The external item equalityComparer</param>\r
+    public HashSet(int capacity, double fill, SCG.IEqualityComparer<T> itemequalityComparer) : base(itemequalityComparer)\r
+    {\r
+      if (fill < 0.1 || fill > 0.9)\r
+        throw new ArgumentException("Fill outside valid range [0.1, 0.9]");\r
+      if (capacity <= 0)\r
+        throw new ArgumentException("Capacity must be non-negative");\r
+      //this.itemequalityComparer = itemequalityComparer;\r
+      origbits = 4;\r
+      while (capacity - 1 >> origbits > 0) origbits++;\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
+    /// <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, 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, 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, true); }\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
+    /// <param name="olditem"></param>\r
+    /// <returns>True if item was found (and updated)</returns>\r
+    public virtual bool Update(T item, out T olditem)\r
+    { updatecheck(); olditem = item; return searchoradd(ref olditem, false, true, 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, true); }\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, true); }\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
+    /// <param name="olditem"></param>\r
+    /// <returns>True if item was updated</returns>\r
+    public virtual bool UpdateOrAdd(T item, out T olditem)\r
+    { updatecheck(); olditem = item; return searchoradd(ref olditem, true, 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
+        raiseForRemove(item);\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">The value to remove.</param>\r
+    /// <param name="removeditem">The removed value.</param>\r
+    /// <returns>True if item was found.</returns>\r
+    [Tested]\r
+    public virtual bool Remove(T item, out T removeditem)\r
+    {\r
+      updatecheck();\r
+      removeditem = item;\r
+      if (remove(ref removeditem))\r
+      {\r
+#if SHRINK\r
+                               if (size<resizethreshhold/2 && resizethreshhold>8)\r
+                                       shrink();\r
+#endif\r
+        raiseForRemove(removeditem);\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to remove.</param>\r
+    [Tested]\r
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(this);\r
+      bool raise = raiseHandler.MustFire;\r
+      T jtem;\r
+      foreach (U item in items)\r
+      { jtem = item; if (remove(ref jtem) && raise) raiseHandler.Remove(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
+      if (raise) raiseHandler.Raise();\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
+      int oldsize = size;\r
+      clear();\r
+      if (ActiveEvents != 0 && oldsize > 0)\r
+      {\r
+        raiseCollectionCleared(true, oldsize);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove all items *not* in a supplied collection from this set.\r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to retain</param>\r
+    [Tested]\r
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+\r
+      HashSet<T> aux = new HashSet<T>(EqualityComparer);\r
+\r
+      //This only works for sets:\r
+      foreach (U item in items)\r
+        if (Contains(item))\r
+        {\r
+          T jtem = item;\r
+\r
+          aux.searchoradd(ref jtem, true, false, false);\r
+        }\r
+\r
+      if (size == aux.size)\r
+        return;\r
+\r
+      CircularQueue<T> wasRemoved = null;\r
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)\r
+      {\r
+        wasRemoved = new CircularQueue<T>();\r
+        foreach (T item in this)\r
+          if (!aux.Contains(item))\r
+            wasRemoved.Enqueue(item);\r
+      }\r
+\r
+      table = aux.table;\r
+      size = aux.size;\r
+#if !REFBUCKET\r
+      defaultvalid = aux.defaultvalid;\r
+      defaultitem = aux.defaultitem;\r
+#endif\r
+      indexmask = aux.indexmask;\r
+      resizethreshhold = aux.resizethreshhold;\r
+\r
+\r
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)\r
+        raiseForRemoveAll(wasRemoved);\r
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if all items are found.</returns>\r
+    [Tested]\r
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      foreach (U item in items)\r
+        if (!Contains(item))\r
+          return false;\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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<T> UniqueItems() { return this; }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()\r
+    {\r
+      return new MultiplicityOne<T>(this);\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
+\r
+    /// <summary>\r
+    /// Choose some item of this collection. \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override T Choose()\r
+    {\r
+      int len = table.Length;\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+#if REFBUCKET\r
+      do { if (++lastchosen >= len) lastchosen = 0; } while (table[lastchosen] == null);\r
+#else\r
+      if (defaultvalid) return defaultitem;\r
+      do { if (++lastchosen >= len) lastchosen = 0; } while (isnull(table[lastchosen].item));\r
+#endif\r
+      return table[lastchosen].item;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create an enumerator for this set.\r
+    /// </summary>\r
+    /// <returns>The enumerator</returns>\r
+    [Tested]\r
+    public override SCG.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 CollectionModifiedException();\r
+\r
+        if (table[index] != null) yield return 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 CollectionModifiedException();\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 return defaultitem;\r
+#endif\r
+      while (true)\r
+      {\r
+        if (mystamp != stamp)\r
+          throw new CollectionModifiedException();\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 return b.item;\r
+        }\r
+        else\r
+        {\r
+          b = b.overflow;\r
+          yield return b.item;\r
+        }\r
+#else\r
+                               if (ob != null && ob.overflow != null)\r
+                               {\r
+                                       ob = ob.overflow;\r
+                                       yield return ob.item;\r
+                               }\r
+                               else if (index >= 0 && ob == null && (ob = table[index].overflow) != null)\r
+                               {\r
+                                       yield return  ob.item;\r
+                               }\r
+                               else\r
+                               {\r
+                                       do\r
+                                       {\r
+                                               if (++index >= len) yield break;\r
+                                       } while (isnull(table[index].item));\r
+\r
+          yield return 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
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting { get { return true; } }\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, true);\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
+    [Tested]\r
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      bool wasChanged = false;\r
+      bool raiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;\r
+      CircularQueue<T> wasAdded = raiseAdded ? new CircularQueue<T>() : null;\r
+      foreach (T item in items)\r
+      {\r
+        T jtem = item;\r
+\r
+        if (!searchoradd(ref jtem, true, false, false))\r
+        {\r
+          wasChanged = true;\r
+          if (raiseAdded)\r
+            wasAdded.Enqueue(item);\r
+        }\r
+      }\r
+      //TODO: implement a RaiseForAddAll() method\r
+      if (raiseAdded & wasChanged)\r
+        foreach (T item in wasAdded)\r
+          raiseItemsAdded(item, 1);\r
+      if (((ActiveEvents & EventTypeEnum.Changed) != 0 && wasChanged))\r
+        raiseCollectionChanged();\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> BucketCostDistribution()\r
+    {\r
+      TreeDictionary<int, int> res = new TreeDictionary<int, int>();\r
+#if LINEARPROBING\r
+      int count = 0;\r
+#if REFBUCKET\r
+      while (table[count] != null)\r
+#else\r
+      while (!isnull(table[count].item))\r
+#endif\r
+        count++;\r
+      for (int i = table.Length - 1; i >= 0; i--)\r
+      {\r
+#if REFBUCKET\r
+        if (table[i] != null)\r
+#else\r
+        if (!isnull(table[i].item))\r
+#endif\r
+          count++;\r
+        else\r
+          count = 0;\r
+        if (res.Contains(count))\r
+          res[count]++;\r
+        else\r
+          res[count] = 1;\r
+      }\r
+\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
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this HashSet.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      HashSet<T> clone = new HashSet<T>(size > 0 ? size : 1, itemequalityComparer);\r
+      //TODO: make sure this really adds in the counting bag way!\r
+      clone.AddAll(this);\r
+      return clone;\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+}\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..bf5f0d9
--- /dev/null
@@ -0,0 +1,1100 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = 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
+  /// <typeparam name="T">The item type</typeparam>\r
+  [Serializable]\r
+  public class IntervalHeap<T> : CollectionValueBase<T>, IPriorityQueue<T>\r
+  {\r
+    #region Events\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }\r
+\r
+    #endregion\r
+\r
+    #region Fields\r
+    [Serializable]\r
+    struct Interval\r
+    {\r
+      internal T first, last; internal Handle firsthandle, lasthandle;\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
+    SCG.IComparer<T> comparer;\r
+    SCG.IEqualityComparer<T> itemequalityComparer;\r
+\r
+    Interval[] heap;\r
+\r
+    int size;\r
+    #endregion\r
+\r
+    #region Util\r
+    bool heapifyMin(int i)\r
+    {\r
+      bool swappedroot = false;\r
+      int cell = i, currentmin = cell;\r
+      T currentitem = heap[cell].first;\r
+      Handle currenthandle = heap[cell].firsthandle;\r
+\r
+      if (i > 0)\r
+      {\r
+        T other = heap[cell].last;\r
+        if (2 * cell + 1 < size && comparer.Compare(currentitem, other) > 0)\r
+        {\r
+          swappedroot = true;\r
+          Handle otherhandle = heap[cell].lasthandle;\r
+          updateLast(cell, currentitem, currenthandle);\r
+          currentitem = other;\r
+          currenthandle = otherhandle;\r
+        }\r
+      }\r
+\r
+      T minitem = currentitem;\r
+      Handle minhandle = currenthandle;\r
+\r
+      while (true)\r
+      {\r
+        int l = 2 * cell + 1, r = l + 1;\r
+        T lv, rv;\r
+\r
+        if (2 * l < size && comparer.Compare(lv = heap[l].first, minitem) < 0)\r
+        { currentmin = l; minitem = lv; }\r
+\r
+        if (2 * r < size && comparer.Compare(rv = heap[r].first, minitem) < 0)\r
+        { currentmin = r; minitem = rv; }\r
+\r
+        if (currentmin == cell)\r
+          break;\r
+\r
+        minhandle = heap[currentmin].firsthandle;\r
+        updateFirst(cell, minitem, minhandle);\r
+        cell = currentmin;\r
+\r
+        //Maybe swap first and last\r
+        T other = heap[cell].last;\r
+        if (2 * currentmin + 1 < size && comparer.Compare(currentitem, other) > 0)\r
+        {\r
+          Handle otherhandle = heap[cell].lasthandle;\r
+          updateLast(cell, currentitem, currenthandle);\r
+          currentitem = other;\r
+          currenthandle = otherhandle;\r
+        }\r
+\r
+\r
+        minitem = currentitem;\r
+        minhandle = currenthandle;\r
+      }\r
+\r
+      if (cell != i || swappedroot)\r
+        updateFirst(cell, minitem, minhandle);\r
+      return swappedroot;\r
+    }\r
+\r
+\r
+    bool heapifyMax(int i)\r
+    {\r
+      bool swappedroot = false;\r
+      int cell = i, currentmax = cell;\r
+      T currentitem = heap[cell].last;\r
+      Handle currenthandle = heap[cell].lasthandle;\r
+\r
+      if (i > 0)\r
+      {\r
+        T other = heap[cell].first;\r
+        if (comparer.Compare(currentitem, other) < 0)\r
+        {\r
+          swappedroot = true;\r
+          Handle otherhandle = heap[cell].firsthandle;\r
+          updateFirst(cell, currentitem, currenthandle);\r
+          currentitem = other;\r
+          currenthandle = otherhandle;\r
+        }\r
+      }\r
+\r
+      T maxitem = currentitem;\r
+      Handle maxhandle = currenthandle;\r
+\r
+      while (true)\r
+      {\r
+        int l = 2 * cell + 1, r = l + 1;\r
+        T lv, rv;\r
+\r
+        if (2 * l + 1 < size && comparer.Compare(lv = heap[l].last, maxitem) > 0)\r
+        { currentmax = l; maxitem = lv; }\r
+\r
+        if (2 * r + 1 < size && comparer.Compare(rv = heap[r].last, maxitem) > 0)\r
+        { currentmax = r; maxitem = rv; }\r
+\r
+        if (currentmax == cell)\r
+          break;\r
+\r
+        maxhandle = heap[currentmax].lasthandle;\r
+        updateLast(cell, maxitem, maxhandle);\r
+        cell = currentmax;\r
+\r
+        //Maybe swap first and last\r
+        T other = heap[cell].first;\r
+        if (comparer.Compare(currentitem, other) < 0)\r
+        {\r
+          Handle otherhandle = heap[cell].firsthandle;\r
+          updateFirst(cell, currentitem, currenthandle);\r
+          currentitem = other;\r
+          currenthandle = otherhandle;\r
+        }\r
+\r
+        maxitem = currentitem;\r
+        maxhandle = currenthandle;\r
+      }\r
+\r
+      if (cell != i || swappedroot) //Check could be better?\r
+        updateLast(cell, maxitem, maxhandle);\r
+      return swappedroot;\r
+    }\r
+\r
+\r
+    void bubbleUpMin(int i)\r
+    {\r
+      if (i > 0)\r
+      {\r
+        T min = heap[i].first, iv = min;\r
+        Handle minhandle = heap[i].firsthandle;\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
+            updateFirst(i, min, heap[p].firsthandle);\r
+            min = iv;\r
+            i = p;\r
+          }\r
+          else\r
+            break;\r
+        }\r
+\r
+        updateFirst(i, iv, minhandle);\r
+      }\r
+    }\r
+\r
+\r
+    void bubbleUpMax(int i)\r
+    {\r
+      if (i > 0)\r
+      {\r
+        T max = heap[i].last, iv = max;\r
+        Handle maxhandle = heap[i].lasthandle;\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
+            updateLast(i, max, heap[p].lasthandle);\r
+            max = iv;\r
+            i = p;\r
+          }\r
+          else\r
+            break;\r
+        }\r
+\r
+        updateLast(i, iv, maxhandle);\r
+\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="comparer">The external comparer</param>\r
+    public IntervalHeap(SCG.IComparer<T> comparer) : this(16,comparer) { }\r
+\r
+\r
+    //TODO: maybe remove\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(capacity, Comparer<T>.Default, EqualityComparer<T>.Default) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create an interval heap with external item comparer and prescribed initial capacity\r
+    /// </summary>\r
+    /// <param name="comparer">The external comparer</param>\r
+    /// <param name="capacity">The initial capacity</param>\r
+    public IntervalHeap(int capacity, SCG.IComparer<T> comparer) : this(capacity,comparer,new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }\r
+\r
+    IntervalHeap(int capacity, SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> itemequalityComparer)\r
+    {\r
+      if (comparer == null)\r
+        throw new NullReferenceException("Item comparer cannot be null");\r
+      if (itemequalityComparer == null)\r
+        throw new NullReferenceException("Item equality comparer cannot be null");\r
+      this.comparer = comparer;\r
+      this.itemequalityComparer = itemequalityComparer;\r
+      int length = 1;\r
+      while (length < capacity) length <<= 1;\r
+      heap = new Interval[length];\r
+    }\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="NoSuchItemException"/> 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 NoSuchItemException();\r
+\r
+      return heap[0].first;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove the least item from this  priority queue.\r
+    /// <exception cref="NoSuchItemException"/> if queue is empty\r
+    /// </summary>\r
+    /// <returns>The removed item.</returns>\r
+    [Tested]\r
+    public T DeleteMin()\r
+    {\r
+      IPriorityQueueHandle<T> handle = null;\r
+      return DeleteMin(out handle);\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Find the current largest item of this priority queue.\r
+    /// <exception cref="NoSuchItemException"/> 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 NoSuchItemException("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="NoSuchItemException"/> if queue is empty\r
+    /// </summary>\r
+    /// <returns>The removed item.</returns>\r
+    [Tested]\r
+    public T DeleteMax()\r
+    {\r
+      IPriorityQueueHandle<T> handle = null;\r
+      return DeleteMax(out handle);\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 SCG.IComparer<T> Comparer { get { return comparer; } }\r
+\r
+    #endregion\r
+\r
+    #region IExtensible<T> Members\r
+\r
+    /// <summary>\r
+    /// If true any call of an updating operation will throw an\r
+    /// <code>ReadOnlyCollectionException</code>\r
+    /// </summary>\r
+    /// <value>True if this collection is read-only.</value>\r
+    public bool IsReadOnly { get { return false; } }\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
+    /// <summary>\r
+    /// Value is null since this collection has no equality concept for its items. \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return itemequalityComparer; } }\r
+\r
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting { get { return false; } }\r
+\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
+    /// 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 (add(null, item))\r
+      {\r
+        raiseItemsAdded(item, 1);\r
+        raiseCollectionChanged();\r
+        return true;\r
+      }\r
+      return false;\r
+    }\r
+\r
+    private bool add(Handle itemhandle, T item)\r
+    {\r
+      if (size == 0)\r
+      {\r
+        size = 1;\r
+        updateFirst(0, item, itemhandle);\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 = heap[p].last;\r
+\r
+        if (comparer.Compare(item, tmp) > 0)\r
+        {\r
+          updateFirst(i, tmp, heap[p].lasthandle);\r
+          updateLast(p, item, itemhandle);\r
+          bubbleUpMax(p);\r
+        }\r
+        else\r
+        {\r
+          updateFirst(i, item, itemhandle);\r
+\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
+        if (comparer.Compare(item, other) < 0)\r
+        {\r
+          updateLast(i, other, heap[i].firsthandle);\r
+          updateFirst(i, item, itemhandle);\r
+          bubbleUpMin(i);\r
+        }\r
+        else\r
+        {\r
+          updateLast(i, item, itemhandle);\r
+          bubbleUpMax(i);\r
+        }\r
+      }\r
+      size++;\r
+\r
+      return true;\r
+    }\r
+\r
+    private void updateLast(int cell, T item, Handle handle)\r
+    {\r
+      heap[cell].last = item;\r
+      if (handle != null)\r
+        handle.index = 2 * cell + 1;\r
+      heap[cell].lasthandle = handle;\r
+    }\r
+\r
+    private void updateFirst(int cell, T item, Handle handle)\r
+    {\r
+      heap[cell].first = item;\r
+      if (handle != null)\r
+        handle.index = 2 * cell;\r
+      heap[cell].firsthandle = handle;\r
+    }\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
+    [Tested]\r
+    public void AddAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      stamp++;\r
+      int oldsize = size;\r
+      foreach (T item in items)\r
+        add(null, item);\r
+      if (size != oldsize)\r
+      {\r
+        if ((ActiveEvents & EventTypeEnum.Added) != 0)\r
+          foreach (T item in items)\r
+            raiseItemsAdded(item, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICollection<T> members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>True if this collection is empty.</value>\r
+    [Tested]\r
+    public override bool IsEmpty { [Tested]get { return size == 0; } }\r
+\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
+    /// Choose some item of this collection. \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    public override T Choose()\r
+    {\r
+      if (size == 0)\r
+        throw new NoSuchItemException("Collection is empty");\r
+      return heap[0].first;\r
+    }\r
+\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 SCG.IEnumerator<T> GetEnumerator()\r
+    {\r
+      int mystamp = stamp;\r
+      for (int i = 0; i < size; i++)\r
+      {\r
+        if (mystamp != stamp) throw new CollectionModifiedException();\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
+    #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
+        if (interval.firsthandle != null && interval.firsthandle.index != 2 * i)\r
+        {\r
+          Console.WriteLine("Cell {0}: firsthandle.index({1}) != 2*cell({2})  [size={3}]", i, interval.firsthandle.index, 2 * i, 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
+        if (interval.firsthandle != null && interval.firsthandle.index != 2 * i)\r
+        {\r
+          Console.WriteLine("Cell {0}: firsthandle.index({1}) != 2*cell({2})  [size={3}]", i, interval.firsthandle.index, 2 * i, size);\r
+          retval = false;\r
+        }\r
+        if (interval.lasthandle != null && interval.lasthandle.index != 2 * i + 1)\r
+        {\r
+          Console.WriteLine("Cell {0}: lasthandle.index({1}) != 2*cell+1({2})  [size={3}]", i, interval.lasthandle.index, 2 * i + 1, 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
+    #region IPriorityQueue<T> Members\r
+\r
+    [Serializable]\r
+    class Handle : IPriorityQueueHandle<T>\r
+    {\r
+      /// <summary>\r
+      /// To save space, the index is 2*cell for heap[cell].first, and 2*cell+1 for heap[cell].last\r
+      /// </summary>\r
+      internal int index = -1;\r
+\r
+      public override string ToString()\r
+      {\r
+        return String.Format("[{0}]", index);\r
+      }\r
+\r
+    }\r
+\r
+    /// <summary>\r
+    /// Get or set the item corresponding to a handle. \r
+    /// </summary>\r
+    /// <exception cref="InvalidPriorityQueueHandleException">if the handle is invalid for this queue</exception>\r
+    /// <param name="handle">The reference into the heap</param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public T this[IPriorityQueueHandle<T> handle]\r
+    {\r
+      get\r
+      {\r
+        int cell;\r
+        bool isfirst;\r
+        Handle myhandle = checkHandle(handle, out cell, out isfirst);\r
+\r
+        return isfirst ? heap[cell].first : heap[cell].last;\r
+      }\r
+      set\r
+      {\r
+        Replace(handle, value);\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Check safely if a handle is valid for this queue and if so, report the corresponding queue item.\r
+    /// </summary>\r
+    /// <param name="handle">The handle to check</param>\r
+    /// <param name="item">If the handle is valid this will contain the corresponding item on output.</param>\r
+    /// <returns>True if the handle is valid.</returns>\r
+    public bool Find(IPriorityQueueHandle<T> handle, out T item)\r
+    {\r
+      Handle myhandle = handle as Handle;\r
+      if (myhandle == null)\r
+      {\r
+        item = default(T);\r
+        return false;\r
+      }\r
+      int toremove = myhandle.index;\r
+      int cell = toremove / 2;\r
+      bool isfirst = toremove % 2 == 0;\r
+      {\r
+        if (toremove == -1 || toremove >= size)\r
+        {\r
+          item = default(T);\r
+          return false;\r
+        }\r
+        Handle actualhandle = isfirst ? heap[cell].firsthandle : heap[cell].lasthandle;\r
+        if (actualhandle != myhandle)\r
+        {\r
+          item = default(T);\r
+          return false;\r
+        }\r
+      }\r
+      item = isfirst ? heap[cell].first : heap[cell].last;\r
+      return true;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Add an item to the priority queue, receiving a \r
+    /// handle for the item in the queue, \r
+    /// or reusing an already existing handle.\r
+    /// </summary>\r
+    /// <param name="handle">On output: a handle for the added item. \r
+    /// On input: null for allocating a new handle, an invalid handle for reuse. \r
+    /// A handle for reuse must be compatible with this priority queue, \r
+    /// by being created by a priority queue of the same runtime type, but not \r
+    /// necessarily the same priority queue object.</param>\r
+    /// <param name="item">The item to add.</param>\r
+    /// <returns>True since item will always be added unless the call throws an exception.</returns>\r
+    [Tested]\r
+    public bool Add(ref IPriorityQueueHandle<T> handle, T item)\r
+    {\r
+      stamp++;\r
+      Handle myhandle = (Handle)handle;\r
+      if (myhandle == null)\r
+        handle = myhandle = new Handle();\r
+      else\r
+          if (myhandle.index != -1)\r
+        throw new InvalidPriorityQueueHandleException("Handle not valid for reuse");\r
+      if (add(myhandle, item))\r
+      {\r
+        raiseItemsAdded(item, 1);\r
+        raiseCollectionChanged();\r
+        return true;\r
+      }\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Delete an item with a handle from a priority queue.\r
+    /// </summary>\r
+    /// <exception cref="InvalidPriorityQueueHandleException">if the handle is invalid</exception>\r
+    /// <param name="handle">The handle for the item. The handle will be invalidated, but reusable.</param>\r
+    /// <returns>The deleted item</returns>\r
+    [Tested]\r
+    public T Delete(IPriorityQueueHandle<T> handle)\r
+    {\r
+      stamp++;\r
+      int cell;\r
+      bool isfirst;\r
+      Handle myhandle = checkHandle(handle, out cell, out isfirst);\r
+\r
+      T retval;\r
+      myhandle.index = -1;\r
+      int lastcell = (size - 1) / 2;\r
+\r
+      if (cell == lastcell)\r
+      {\r
+        if (isfirst)\r
+        {\r
+          retval = heap[cell].first;\r
+          if (size % 2 == 0)\r
+          {\r
+            updateFirst(cell, heap[cell].last, heap[cell].lasthandle);\r
+            heap[cell].last = default(T);\r
+            heap[cell].lasthandle = null;\r
+          }\r
+          else\r
+          {\r
+            heap[cell].first = default(T);\r
+            heap[cell].firsthandle = null;\r
+          }\r
+        }\r
+        else\r
+        {\r
+          retval = heap[cell].last;\r
+          heap[cell].last = default(T);\r
+          heap[cell].lasthandle = null;\r
+        }\r
+        size--;\r
+      }\r
+      else if (isfirst)\r
+      {\r
+        retval = heap[cell].first;\r
+\r
+        if (size % 2 == 0)\r
+        {\r
+          updateFirst(cell, heap[lastcell].last, heap[lastcell].lasthandle);\r
+          heap[lastcell].last = default(T);\r
+          heap[lastcell].lasthandle = null;\r
+        }\r
+        else\r
+        {\r
+          updateFirst(cell, heap[lastcell].first, heap[lastcell].firsthandle);\r
+          heap[lastcell].first = default(T);\r
+          heap[lastcell].firsthandle = null;\r
+        }\r
+\r
+        size--;\r
+        if (heapifyMin(cell))\r
+          bubbleUpMax(cell);\r
+        else\r
+          bubbleUpMin(cell);\r
+      }\r
+      else\r
+      {\r
+        retval = heap[cell].last;\r
+\r
+        if (size % 2 == 0)\r
+        {\r
+          updateLast(cell, heap[lastcell].last, heap[lastcell].lasthandle);\r
+          heap[lastcell].last = default(T);\r
+          heap[lastcell].lasthandle = null;\r
+        }\r
+        else\r
+        {\r
+          updateLast(cell, heap[lastcell].first, heap[lastcell].firsthandle);\r
+          heap[lastcell].first = default(T);\r
+          heap[lastcell].firsthandle = null;\r
+        }\r
+\r
+        size--;\r
+        if (heapifyMax(cell))\r
+          bubbleUpMin(cell);\r
+        else\r
+          bubbleUpMax(cell);\r
+      }\r
+\r
+      raiseItemsRemoved(retval, 1);\r
+      raiseCollectionChanged();\r
+\r
+      return retval;\r
+    }\r
+\r
+    private Handle checkHandle(IPriorityQueueHandle<T> handle, out int cell, out bool isfirst)\r
+    {\r
+      Handle myhandle = (Handle)handle;\r
+      int toremove = myhandle.index;\r
+      cell = toremove / 2;\r
+      isfirst = toremove % 2 == 0;\r
+      {\r
+        if (toremove == -1 || toremove >= size)\r
+          throw new InvalidPriorityQueueHandleException("Invalid handle, index out of range");\r
+        Handle actualhandle = isfirst ? heap[cell].firsthandle : heap[cell].lasthandle;\r
+        if (actualhandle != myhandle)\r
+          throw new InvalidPriorityQueueHandleException("Invalid handle, doesn't match queue");\r
+      }\r
+      return myhandle;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Replace an item with a handle in a priority queue with a new item. \r
+    /// Typically used for changing the priority of some queued object.\r
+    /// </summary>\r
+    /// <param name="handle">The handle for the old item</param>\r
+    /// <param name="item">The new item</param>\r
+    /// <returns>The old item</returns>\r
+    [Tested]\r
+    public T Replace(IPriorityQueueHandle<T> handle, T item)\r
+    {\r
+      stamp++;\r
+      int cell;\r
+      bool isfirst;\r
+      checkHandle(handle, out cell, out isfirst);\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+\r
+      T retval;\r
+\r
+      if (isfirst)\r
+      {\r
+        retval = heap[cell].first;\r
+        heap[cell].first = item;\r
+        if (size == 2 * cell + 1) // cell == lastcell\r
+        {\r
+          int p = (cell + 1) / 2 - 1;\r
+          if (comparer.Compare(item, heap[p].last) > 0)\r
+          {\r
+            Handle thehandle = heap[cell].firsthandle;\r
+            updateFirst(cell, heap[p].last, heap[p].lasthandle);\r
+            updateLast(p, item, thehandle);\r
+            bubbleUpMax(p);\r
+          }\r
+          else\r
+            bubbleUpMin(cell);\r
+        }\r
+        else if (heapifyMin(cell))\r
+          bubbleUpMax(cell);\r
+        else\r
+          bubbleUpMin(cell);\r
+      }\r
+      else\r
+      {\r
+        retval = heap[cell].last;\r
+        heap[cell].last = item;\r
+        if (heapifyMax(cell))\r
+          bubbleUpMin(cell);\r
+        else\r
+          bubbleUpMax(cell);\r
+      }\r
+\r
+      raiseItemsRemoved(retval, 1);\r
+      raiseItemsAdded(item, 1);\r
+      raiseCollectionChanged();\r
+\r
+      return retval;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Find the current least item of this priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the item.</param>\r
+    /// <returns>The least item.</returns>\r
+    public T FindMin(out IPriorityQueueHandle<T> handle)\r
+    {\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+      handle = heap[0].firsthandle;\r
+\r
+      return heap[0].first;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Find the current largest item of this priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the item.</param>\r
+    /// <returns>The largest item.</returns>\r
+    public T FindMax(out IPriorityQueueHandle<T> handle)\r
+    {\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+      else if (size == 1)\r
+      {\r
+        handle = heap[0].firsthandle;\r
+        return heap[0].first;\r
+      }\r
+      else\r
+      {\r
+        handle = heap[0].lasthandle;\r
+        return heap[0].last;\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove the least item from this priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the removed item.</param>\r
+    /// <returns>The removed item.</returns>\r
+    public T DeleteMin(out IPriorityQueueHandle<T> handle)\r
+    {\r
+      stamp++;\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+\r
+      T retval = heap[0].first;\r
+      Handle myhandle = heap[0].firsthandle;\r
+      handle = myhandle;\r
+      if (myhandle != null)\r
+        myhandle.index = -1;\r
+\r
+      if (size == 1)\r
+      {\r
+        size = 0;\r
+        heap[0].first = default(T);\r
+        heap[0].firsthandle = null;\r
+      }\r
+      else\r
+      {\r
+        int lastcell = (size - 1) / 2;\r
+\r
+        if (size % 2 == 0)\r
+        {\r
+          updateFirst(0, heap[lastcell].last, heap[lastcell].lasthandle);\r
+          heap[lastcell].last = default(T);\r
+          heap[lastcell].lasthandle = null;\r
+        }\r
+        else\r
+        {\r
+          updateFirst(0, heap[lastcell].first, heap[lastcell].firsthandle);\r
+          heap[lastcell].first = default(T);\r
+          heap[lastcell].firsthandle = null;\r
+        }\r
+\r
+        size--;\r
+        heapifyMin(0);\r
+      }\r
+\r
+      raiseItemsRemoved(retval, 1);\r
+      raiseCollectionChanged();\r
+      return retval;\r
+\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove the largest item from this priority queue.\r
+    /// </summary>\r
+    /// <param name="handle">On return: the handle of the removed item.</param>\r
+    /// <returns>The removed item.</returns>\r
+    public T DeleteMax(out IPriorityQueueHandle<T> handle)\r
+    {\r
+      stamp++;\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+\r
+      T retval;\r
+      Handle myhandle;\r
+\r
+      if (size == 1)\r
+      {\r
+        size = 0;\r
+        retval = heap[0].first;\r
+        myhandle = heap[0].firsthandle;\r
+        if (myhandle != null)\r
+          myhandle.index = -1;\r
+        heap[0].first = default(T);\r
+        heap[0].firsthandle = null;\r
+      }\r
+      else\r
+      {\r
+        retval = heap[0].last;\r
+        myhandle = heap[0].lasthandle;\r
+        if (myhandle != null)\r
+          myhandle.index = -1;\r
+\r
+        int lastcell = (size - 1) / 2;\r
+\r
+        if (size % 2 == 0)\r
+        {\r
+          updateLast(0, heap[lastcell].last, heap[lastcell].lasthandle);\r
+          heap[lastcell].last = default(T);\r
+          heap[lastcell].lasthandle = null;\r
+        }\r
+        else\r
+        {\r
+          updateLast(0, heap[lastcell].first, heap[lastcell].firsthandle);\r
+          heap[lastcell].first = default(T);\r
+          heap[lastcell].firsthandle = null;\r
+        }\r
+\r
+        size--;\r
+        heapifyMax(0);\r
+      }\r
+      raiseItemsRemoved(retval, 1);\r
+      raiseCollectionChanged();\r
+      handle = myhandle;\r
+      return retval;\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this IntervalHeap.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      IntervalHeap<T> clone = new IntervalHeap<T>(size, comparer, itemequalityComparer);\r
+      clone.AddAll(this);\r
+      return clone;\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+\r
+}\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..322a4c0
--- /dev/null
@@ -0,0 +1,3782 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 HASHINDEXnot\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using SCG = System.Collections.Generic;\r
+\r
+namespace C5\r
+{\r
+  /// <summary>\r
+  /// A list collection class based on a doubly linked list data structure.\r
+  /// </summary>\r
+  [Serializable]\r
+  public class LinkedList<T> : SequencedBase<T>, IList<T>\r
+#if HASHINDEX\r
+#else\r
+, IStack<T>, IQueue<T>\r
+#endif\r
+  {\r
+    #region Fields\r
+    /// <summary>\r
+    /// IExtensible.Add(T) always does AddLast(T), fIFO determines \r
+    /// if T Remove() does RemoveFirst() or RemoveLast()\r
+    /// </summary>\r
+    bool fIFO = true;\r
+\r
+    #region Events\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override EventTypeEnum ListenableEvents { get { return underlying == null ? EventTypeEnum.All : EventTypeEnum.None; } }\r
+\r
+    #endregion\r
+\r
+    //Invariant:  startsentinel != null && endsentinel != null\r
+    //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel\r
+    //Else:      startsentinel.next == First && endsentinel.prev == Last)\r
+    /// <summary>\r
+    /// Node to the left of first node \r
+    /// </summary>\r
+    Node startsentinel;\r
+    /// <summary>\r
+    /// Node to the right of last node\r
+    /// </summary>\r
+    Node endsentinel;\r
+    /// <summary>\r
+    /// Offset of this view in underlying list\r
+    /// </summary>\r
+#if HASHINDEX\r
+    int? offset;\r
+#else\r
+    int offset;\r
+#endif\r
+\r
+    /// <summary>\r
+    /// underlying list of this view (or null for the underlying list)\r
+    /// </summary>\r
+    LinkedList<T> underlying;\r
+\r
+    //Note: all views will have the same views list since all view objects are created by MemeberwiseClone()\r
+    WeakViewList<LinkedList<T>> views;\r
+    WeakViewList<LinkedList<T>>.Node myWeakReference;\r
+\r
+    /// <summary>\r
+    /// Has this list or view not been invalidated by some operation (by someone calling Dispose())\r
+    /// </summary>\r
+    bool isValid = true;\r
+\r
+\r
+#if HASHINDEX\r
+    HashDictionary<T, Node> dict;\r
+    /// <summary>\r
+    /// Number of taggroups\r
+    /// </summary>\r
+    int taggroups;\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    int Taggroups\r
+    {\r
+      get { return underlying == null ? taggroups : underlying.taggroups; }\r
+      set { if (underlying == null) taggroups = value; else underlying.taggroups = value; }\r
+    }\r
+#endif\r
+\r
+    #endregion\r
+\r
+    #region Util\r
+\r
+    bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }\r
+\r
+    #region Check utilities\r
+    /// <summary>\r
+    /// Check if it is valid to perform updates and increment stamp of \r
+    /// underlying if this is a view.\r
+    /// <para>This method should be called in every public modifying \r
+    /// methods before any modifications are performed.\r
+    /// </para>\r
+    /// </summary>\r
+    /// <exception cref="InvalidOperationException"> if check fails.</exception>\r
+    protected override void updatecheck()\r
+    {\r
+      validitycheck();\r
+      base.updatecheck();\r
+      if (underlying != null)\r
+        underlying.stamp++;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if we are a view that the underlyinglist has only been updated through us.\r
+    /// <br/>\r
+    /// This method should be called from enumerators etc to guard against \r
+    /// modification of the base collection.\r
+    /// </summary>\r
+    /// <exception cref="InvalidOperationException"> if check fails.</exception>\r
+    void validitycheck()\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException();\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check that the list has not been updated since a particular time.\r
+    /// </summary>\r
+    /// <param name="stamp">The stamp indicating the time.</param>\r
+    /// <exception cref="CollectionModifiedException"> if check fails.</exception>\r
+    protected override void modifycheck(int stamp)\r
+    {\r
+      validitycheck();\r
+      if ((underlying != null ? underlying.stamp : this.stamp) != stamp)\r
+        throw new CollectionModifiedException();\r
+    }\r
+    #endregion\r
+\r
+    #region Searching\r
+    bool contains(T item, out Node node)\r
+    {\r
+#if HASHINDEX\r
+      if (dict.Find(item, out node))\r
+        return insideview(node);\r
+#else\r
+      //TODO: search from both ends? Or search from the end selected by FIFO?\r
+      node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        if (equals(item, node.item))\r
+          return true;\r
+        node = node.next;\r
+      }\r
+#endif\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Search forwards from a node for a node with a particular item.\r
+    /// </summary>\r
+    /// <param name="item">The item to look for</param>\r
+    /// <param name="node">On input, the node to start at. If item was found, the node found on output.</param>\r
+    /// <param name="index">If node was found, the value will be the number of links followed higher than \r
+    /// the value on input. If item was not found, the value on output is undefined.</param>\r
+    /// <returns>True if node was found.</returns>\r
+    bool find(T item, ref Node node, ref int index)\r
+    {\r
+      while (node != endsentinel)\r
+      {\r
+        //if (item.Equals(node.item))\r
+        if (itemequalityComparer.Equals(item, node.item))\r
+          return true;\r
+\r
+        index++;\r
+        node = node.next;\r
+      }\r
+\r
+      return false;\r
+    }\r
+\r
+    bool dnif(T item, ref Node node, ref int index)\r
+    {\r
+      while (node != startsentinel)\r
+      {\r
+        //if (item.Equals(node.item))\r
+        if (itemequalityComparer.Equals(item, node.item))\r
+          return true;\r
+\r
+        index--;\r
+        node = node.prev;\r
+      }\r
+\r
+      return false;\r
+    }\r
+\r
+#if HASHINDEX\r
+    bool insideview(Node node)\r
+    {\r
+      if (underlying == null)\r
+        return true;\r
+      return (startsentinel.precedes(node) && node.precedes(endsentinel));\r
+    }\r
+#endif\r
+\r
+    #endregion\r
+\r
+    #region Indexing\r
+    /// <summary>\r
+    /// Return the node at position pos\r
+    /// </summary>\r
+    /// <param name="pos"></param>\r
+    /// <returns></returns>\r
+    Node get(int pos)\r
+    {\r
+      if (pos < 0 || pos >= size)\r
+        throw new IndexOutOfRangeException();\r
+      else if (pos < size / 2)\r
+      {              // Closer to front\r
+        Node node = startsentinel;\r
+\r
+        for (int i = 0; i <= pos; i++)\r
+          node = node.next;\r
+\r
+        return node;\r
+      }\r
+      else\r
+      {                            // Closer to end\r
+        Node node = endsentinel;\r
+\r
+        for (int i = size; i > pos; i--)\r
+          node = node.prev;\r
+\r
+        return node;\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Find the distance from pos to the set given by positions. Return the\r
+    /// signed distance as return value and as an out parameter, the\r
+    /// array index of the nearest position. This is used for up to length 5 of\r
+    /// positions, and we do not assume it is sorted. \r
+    /// </summary>\r
+    /// <param name="pos"></param>\r
+    /// <param name="positions"></param>\r
+    /// <param name="nearest"></param>\r
+    /// <returns></returns>\r
+    int dist(int pos, out int nearest, int[] positions)\r
+    {\r
+      nearest = -1;\r
+      int bestdist = int.MaxValue;\r
+      int signeddist = bestdist;\r
+      for (int i = 0; i < positions.Length; i++)\r
+      {\r
+        int thisdist = positions[i] - pos;\r
+        if (thisdist >= 0 && thisdist < bestdist) { nearest = i; bestdist = thisdist; signeddist = thisdist; }\r
+        if (thisdist < 0 && -thisdist < bestdist) { nearest = i; bestdist = -thisdist; signeddist = thisdist; }\r
+      }\r
+      return signeddist;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Find the node at position pos, given known positions of several nodes.\r
+    /// </summary>\r
+    /// <param name="pos"></param>\r
+    /// <param name="positions"></param>\r
+    /// <param name="nodes"></param>\r
+    /// <returns></returns>\r
+    Node get(int pos, int[] positions, Node[] nodes)\r
+    {\r
+      int nearest;\r
+      int delta = dist(pos, out nearest, positions);\r
+      Node node = nodes[nearest];\r
+      if (delta > 0)\r
+        for (int i = 0; i < delta; i++)\r
+          node = node.prev;\r
+      else\r
+        for (int i = 0; i > delta; i--)\r
+          node = node.next;\r
+      return node;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Get nodes at positions p1 and p2, given nodes at several positions.\r
+    /// </summary>\r
+    /// <param name="p1"></param>\r
+    /// <param name="p2"></param>\r
+    /// <param name="n1"></param>\r
+    /// <param name="n2"></param>\r
+    /// <param name="positions"></param>\r
+    /// <param name="nodes"></param>\r
+    void getPair(int p1, int p2, out Node n1, out Node n2, int[] positions, Node[] nodes)\r
+    {\r
+      int nearest1, nearest2;\r
+      int delta1 = dist(p1, out nearest1, positions), d1 = delta1 < 0 ? -delta1 : delta1;\r
+      int delta2 = dist(p2, out nearest2, positions), d2 = delta2 < 0 ? -delta2 : delta2;\r
+\r
+      if (d1 < d2)\r
+      {\r
+        n1 = get(p1, positions, nodes);\r
+        n2 = get(p2, new int[] { positions[nearest2], p1 }, new Node[] { nodes[nearest2], n1 });\r
+      }\r
+      else\r
+      {\r
+        n2 = get(p2, positions, nodes);\r
+        n1 = get(p1, new int[] { positions[nearest1], p2 }, new Node[] { nodes[nearest1], n2 });\r
+      }\r
+    }\r
+    #endregion\r
+\r
+    #region Insertion\r
+#if HASHINDEX\r
+    void insert(int index, Node succ, T item)\r
+    {\r
+      Node newnode = new Node(item);\r
+      if (dict.FindOrAdd(item, ref newnode))\r
+        throw new DuplicateNotAllowedException("Item already in indexed list");\r
+      insertNode(true, succ, newnode);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Insert a Node before another one. Unchecked version. \r
+    /// </summary>\r
+    /// <param name="succ">The successor to be</param>\r
+    /// <param name="newnode">Node to insert</param>\r
+    /// <param name="updateViews">update overlapping view in this call</param>\r
+    void insertNode(bool updateViews, Node succ, Node newnode)\r
+    {\r
+      newnode.next = succ;\r
+      Node pred = newnode.prev = succ.prev;\r
+      succ.prev.next = newnode;\r
+      succ.prev = newnode;\r
+      size++;\r
+      if (underlying != null)\r
+        underlying.size++;\r
+      settag(newnode);\r
+      if (updateViews)\r
+        fixViewsAfterInsert(succ, pred, 1, 0);\r
+    }\r
+#else\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="index">The index in this view</param>\r
+    /// <param name="succ"></param>\r
+    /// <param name="item"></param>\r
+    /// <returns></returns>\r
+    Node insert(int index, Node succ, T item)\r
+    {\r
+      Node newnode = new Node(item, succ.prev, succ);\r
+      succ.prev.next = newnode;\r
+      succ.prev = newnode;\r
+      size++;\r
+      if (underlying != null)\r
+        underlying.size++;\r
+      fixViewsAfterInsert(succ, newnode.prev, 1, Offset + index);\r
+      return newnode;\r
+    }\r
+#endif\r
+    #endregion\r
+\r
+    #region Removal\r
+    T remove(Node node, int index)\r
+    {\r
+      fixViewsBeforeSingleRemove(node, Offset + index);\r
+      node.prev.next = node.next;\r
+      node.next.prev = node.prev;\r
+      size--;\r
+      if (underlying != null)\r
+        underlying.size--;\r
+#if HASHINDEX\r
+        removefromtaggroup(node);\r
+#endif\r
+      return node.item;\r
+    }\r
+\r
+#if HASHINDEX\r
+    private bool dictremove(T item, out Node node)\r
+    {\r
+      if (underlying == 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
+        dict.Remove(item);\r
+      }\r
+      return true;\r
+    }\r
+#endif\r
+    #endregion\r
+\r
+    #region fixView utilities\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="added">The actual number of inserted nodes</param>\r
+    /// <param name="pred">The predecessor of the inserted nodes</param>\r
+    /// <param name="succ">The successor of the added nodes</param>\r
+    /// <param name="realInsertionIndex"></param>\r
+    void fixViewsAfterInsert(Node succ, Node pred, int added, int realInsertionIndex)\r
+    {\r
+      if (views != null)\r
+        foreach (LinkedList<T> view in views)\r
+        {\r
+          if (view != this)\r
+          {\r
+#if HASHINDEX\r
+          if (pred.precedes(view.startsentinel) || (view.startsentinel == pred && view.size > 0))\r
+            view.offset += added;\r
+          if (view.startsentinel.precedes(pred) && succ.precedes(view.endsentinel))\r
+            view.size += added;\r
+          if (view.startsentinel == pred && view.size > 0)\r
+            view.startsentinel = succ.prev;\r
+          if (view.endsentinel == succ)\r
+            view.endsentinel = pred.next;\r
+#else\r
+            if (view.Offset == realInsertionIndex && view.size > 0)\r
+              view.startsentinel = succ.prev;\r
+            if (view.Offset + view.size == realInsertionIndex)\r
+              view.endsentinel = pred.next;\r
+            if (view.Offset < realInsertionIndex && view.Offset + view.size > realInsertionIndex)\r
+              view.size += added;\r
+            if (view.Offset > realInsertionIndex || (view.Offset == realInsertionIndex && view.size > 0))\r
+              view.offset += added;\r
+#endif\r
+          }\r
+        }\r
+    }\r
+\r
+    void fixViewsBeforeSingleRemove(Node node, int realRemovalIndex)\r
+    {\r
+      if (views != null)\r
+        foreach (LinkedList<T> view in views)\r
+        {\r
+          if (view != this)\r
+          {\r
+#if HASHINDEX\r
+          if (view.startsentinel.precedes(node) && node.precedes(view.endsentinel))\r
+            view.size--;\r
+          if (!view.startsentinel.precedes(node))\r
+            view.offset--;\r
+          if (view.startsentinel == node)\r
+            view.startsentinel = node.prev;\r
+          if (view.endsentinel == node)\r
+            view.endsentinel = node.next;\r
+#else\r
+            if (view.offset - 1 == realRemovalIndex)\r
+              view.startsentinel = node.prev;\r
+            if (view.offset + view.size == realRemovalIndex)\r
+              view.endsentinel = node.next;\r
+            if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex)\r
+              view.size--;\r
+            if (view.offset > realRemovalIndex)\r
+              view.offset--;\r
+#endif\r
+          }\r
+        }\r
+    }\r
+\r
+#if HASHINDEX\r
+#else\r
+    void fixViewsBeforeRemove(int start, int count, Node first, Node last)\r
+    {\r
+      int clearend = start + count - 1;\r
+      if (views != null)\r
+        foreach (LinkedList<T> view in views)\r
+        {\r
+          if (view == this)\r
+            continue;\r
+          int viewoffset = view.Offset, viewend = viewoffset + view.size - 1;\r
+          //sentinels\r
+          if (start < viewoffset && viewoffset - 1 <= clearend)\r
+            view.startsentinel = first.prev;\r
+          if (start <= viewend + 1 && viewend < clearend)\r
+            view.endsentinel = last.next;\r
+          //offsets and sizes\r
+          if (start < viewoffset)\r
+          {\r
+            if (clearend < viewoffset)\r
+              view.offset = viewoffset - count;\r
+            else\r
+            {\r
+              view.offset = start;\r
+              view.size = clearend < viewend ? viewend - clearend : 0;\r
+            }\r
+          }\r
+          else if (start <= viewend)\r
+            view.size = clearend <= viewend ? view.size - count : start - viewoffset;\r
+        }\r
+    }\r
+#endif\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="otherView"></param>\r
+    /// <returns>The position of View(otherOffset, otherSize) wrt. this view</returns>\r
+    MutualViewPosition viewPosition(LinkedList<T> otherView)\r
+    {\r
+#if HASHINDEX\r
+      Node otherstartsentinel = otherView.startsentinel, otherendsentinel = otherView.endsentinel,\r
+        first = startsentinel.next, last = endsentinel.prev,\r
+        otherfirst = otherstartsentinel.next, otherlast = otherendsentinel.prev;\r
+      if (last.precedes(otherfirst) || otherlast.precedes(first))\r
+        return MutualViewPosition.NonOverlapping;\r
+      if (size == 0 || (otherstartsentinel.precedes(first) && last.precedes(otherendsentinel)))\r
+        return MutualViewPosition.Contains;\r
+      if (otherView.size == 0 || (startsentinel.precedes(otherfirst) && otherlast.precedes(endsentinel)))\r
+        return MutualViewPosition.ContainedIn;\r
+      return MutualViewPosition.Overlapping;\r
+#else\r
+      int end = offset + size, otherOffset = otherView.offset, otherSize = otherView.size, otherEnd = otherOffset + otherSize;\r
+      if (otherOffset >= end || otherEnd <= offset)\r
+        return MutualViewPosition.NonOverlapping;\r
+      if (size == 0 || (otherOffset <= offset && end <= otherEnd))\r
+        return MutualViewPosition.Contains;\r
+      if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end))\r
+        return MutualViewPosition.ContainedIn;\r
+      return MutualViewPosition.Overlapping;\r
+#endif\r
+    }\r
+\r
+    void disposeOverlappingViews(bool reverse)\r
+    {\r
+      if (views != null)\r
+      {\r
+        foreach (LinkedList<T> view in views)\r
+        {\r
+          if (view != this)\r
+          {\r
+            switch (viewPosition(view))\r
+            {\r
+              case MutualViewPosition.ContainedIn:\r
+                if (reverse)\r
+                { }\r
+                else\r
+                  view.Dispose();\r
+                break;\r
+              case MutualViewPosition.Overlapping:\r
+                view.Dispose();\r
+                break;\r
+              case MutualViewPosition.Contains:\r
+              case MutualViewPosition.NonOverlapping:\r
+                break;\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    #endregion\r
+\r
+    #region Constructors\r
+\r
+    /// <summary>\r
+    /// Create a linked list with en external item equalityComparer\r
+    /// </summary>\r
+    /// <param name="itemequalityComparer">The external equalityComparer</param>\r
+    public LinkedList(SCG.IEqualityComparer<T> itemequalityComparer)\r
+      : base(itemequalityComparer)\r
+    {\r
+      offset = 0;\r
+      size = stamp = 0;\r
+      startsentinel = new Node(default(T));\r
+      endsentinel = new Node(default(T));\r
+      startsentinel.next = endsentinel;\r
+      endsentinel.prev = startsentinel;\r
+#if HASHINDEX\r
+      //It is important that the sentinels are different:\r
+      startsentinel.taggroup = new TagGroup();\r
+      startsentinel.taggroup.tag = int.MinValue;\r
+      startsentinel.taggroup.count = 0;\r
+      endsentinel.taggroup = new TagGroup();\r
+      endsentinel.taggroup.tag = int.MaxValue;\r
+      endsentinel.taggroup.count = 0;\r
+      dict = new HashDictionary<T, Node>(itemequalityComparer);\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a linked list with the natural item equalityComparer\r
+    /// </summary>\r
+    public LinkedList() : this(EqualityComparer<T>.Default) { }\r
+\r
+    #endregion\r
+\r
+    #region Node nested class\r
+\r
+    /// <summary>\r
+    /// An individual cell in the linked list\r
+    /// </summary>\r
+    [Serializable]\r
+    class Node\r
+    {\r
+      public Node prev;\r
+\r
+      public Node next;\r
+\r
+      public T item;\r
+\r
+      #region Tag support\r
+#if HASHINDEX\r
+      internal int tag;\r
+\r
+      internal TagGroup taggroup;\r
+\r
+      internal bool precedes(Node that)\r
+      {\r
+        //Debug.Assert(taggroup != null, "taggroup field null");\r
+        //Debug.Assert(that.taggroup != null, "that.taggroup field null");\r
+        int t1 = taggroup.tag;\r
+        int t2 = that.taggroup.tag;\r
+\r
+        return t1 < t2 ? true : t1 > t2 ? false : tag < that.tag;\r
+      }\r
+#endif\r
+      #endregion\r
+\r
+      [Tested]\r
+      internal Node(T item) { this.item = item; }\r
+\r
+      [Tested]\r
+      internal Node(T item, Node prev, Node next)\r
+      {\r
+        this.item = item; this.prev = prev; this.next = next;\r
+      }\r
+\r
+      public override string ToString()\r
+      {\r
+#if HASHINDEX\r
+        return String.Format("Node: (item={0}, tag={1})", item, tag);\r
+#else\r
+        return String.Format("Node(item={0})", item);\r
+#endif\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region Taggroup nested class and tag maintenance utilities\r
+#if HASHINDEX\r
+    /// <summary>\r
+    /// A group of nodes with the same high tag. Purpose is to be\r
+    /// able to tell the sequence order of two nodes without having to scan through\r
+    /// the list.\r
+    /// </summary>\r
+    [Serializable]\r
+    class TagGroup\r
+    {\r
+      internal int tag, count;\r
+\r
+      internal Node first, last;\r
+\r
+      /// <summary>\r
+      /// Pretty print a tag group\r
+      /// </summary>\r
+      /// <returns>Formatted tag group</returns>\r
+      public override string ToString()\r
+      { return String.Format("TagGroup(tag={0}, cnt={1}, fst={2}, lst={3})", tag, count, first, last); }\r
+    }\r
+\r
+    //Constants for tag maintenance\r
+    const int wordsize = 32;\r
+\r
+    const int lobits = 3;\r
+\r
+    const int hibits = lobits + 1;\r
+\r
+    const int losize = 1 << lobits;\r
+\r
+    const int hisize = 1 << hibits;\r
+\r
+    const int logwordsize = 5;\r
+\r
+    TagGroup gettaggroup(Node pred, Node succ, out int lowbound, out int highbound)\r
+    {\r
+      TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;\r
+\r
+      if (predgroup == succgroup)\r
+      {\r
+        lowbound = pred.tag + 1;\r
+        highbound = succ.tag - 1;\r
+        return predgroup;\r
+      }\r
+      else if (predgroup.first != null)\r
+      {\r
+        lowbound = pred.tag + 1;\r
+        highbound = int.MaxValue;\r
+        return predgroup;\r
+      }\r
+      else if (succgroup.first != null)\r
+      {\r
+        lowbound = int.MinValue;\r
+        highbound = succ.tag - 1;\r
+        return succgroup;\r
+      }\r
+      else\r
+      {\r
+        lowbound = int.MinValue;\r
+        highbound = int.MaxValue;\r
+        return new TagGroup();\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Put a tag on a node (already inserted in the list). Split taggroups and renumber as \r
+    /// necessary.\r
+    /// </summary>\r
+    /// <param name="node">The node to tag</param>\r
+    void settag(Node node)\r
+    {\r
+      Node pred = node.prev, succ = node.next;\r
+      TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;\r
+\r
+      if (predgroup == succgroup)\r
+      {\r
+        node.taggroup = predgroup;\r
+        predgroup.count++;\r
+        if (pred.tag + 1 == succ.tag)\r
+          splittaggroup(predgroup);\r
+        else\r
+          node.tag = (pred.tag + 1) / 2 + (succ.tag - 1) / 2;\r
+      }\r
+      else if (predgroup.first != null)\r
+      {\r
+        node.taggroup = predgroup;\r
+        predgroup.last = node;\r
+        predgroup.count++;\r
+        if (pred.tag == int.MaxValue)\r
+          splittaggroup(predgroup);\r
+        else\r
+          node.tag = pred.tag / 2 + int.MaxValue / 2 + 1;\r
+      }\r
+      else if (succgroup.first != null)\r
+      {\r
+        node.taggroup = succgroup;\r
+        succgroup.first = node;\r
+        succgroup.count++;\r
+        if (succ.tag == int.MinValue)\r
+          splittaggroup(node.taggroup);\r
+        else\r
+          node.tag = int.MinValue / 2 + (succ.tag - 1) / 2;\r
+      }\r
+      else\r
+      {\r
+        Debug.Assert(Taggroups == 0);\r
+\r
+        TagGroup newgroup = new TagGroup();\r
+\r
+        Taggroups = 1;\r
+        node.taggroup = newgroup;\r
+        newgroup.first = newgroup.last = node;\r
+        newgroup.count = 1;\r
+        return;\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Remove a node from its taggroup.\r
+    /// <br/> When this is called, node must already have been removed from the underlying list\r
+    /// </summary>\r
+    /// <param name="node">The node to remove</param>\r
+    void removefromtaggroup(Node node)\r
+    {\r
+      //\r
+      TagGroup taggroup = node.taggroup;\r
+\r
+      if (--taggroup.count == 0)\r
+      {\r
+        Taggroups--;\r
+        return;\r
+      }\r
+\r
+      if (node == taggroup.first)\r
+        taggroup.first = node.next;\r
+\r
+      if (node == taggroup.last)\r
+        taggroup.last = node.prev;\r
+\r
+      //node.taggroup = null;\r
+      if (taggroup.count != losize || Taggroups == 1)\r
+        return;\r
+\r
+      TagGroup otg;\r
+\r
+      if ((otg = taggroup.first.prev.taggroup).count <= losize)\r
+        taggroup.first = otg.first;\r
+      else if ((otg = taggroup.last.next.taggroup).count <= losize)\r
+        taggroup.last = otg.last;\r
+      else\r
+        return;\r
+\r
+      Node n = otg.first;\r
+\r
+      for (int i = 0, length = otg.count; i < length; i++)\r
+      {\r
+        n.taggroup = taggroup;\r
+        n = n.next;\r
+      }\r
+\r
+      taggroup.count += otg.count;\r
+      Taggroups--;\r
+      n = taggroup.first;\r
+\r
+      const int ofs = wordsize - hibits;\r
+\r
+      for (int i = 0, count = taggroup.count; i < count; i++)\r
+      {\r
+        n.tag = (i - losize) << ofs; //(i-8)<<28 \r
+        n = n.next;\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Split a tag group to make rom for more tags.\r
+    /// </summary>\r
+    /// <param name="taggroup">The tag group</param>\r
+    void splittaggroup(TagGroup taggroup)\r
+    {\r
+      Node n = taggroup.first;\r
+      int ptgt = taggroup.first.prev.taggroup.tag;\r
+      int ntgt = taggroup.last.next.taggroup.tag;\r
+\r
+      Debug.Assert(ptgt + 1 <= ntgt - 1);\r
+\r
+      int ofs = wordsize - hibits;\r
+#warning hack alert was there a -1 here?\r
+      int newtgs = taggroup.count / hisize;// - 1;\r
+      int tgtdelta = (int)((ntgt + 0.0 - ptgt) / (newtgs + 2)), tgtag = ptgt;\r
+\r
+      tgtdelta = tgtdelta == 0 ? 1 : tgtdelta;\r
+      for (int j = 0; j < newtgs; j++)\r
+      {\r
+        TagGroup newtaggroup = new TagGroup();\r
+\r
+        newtaggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta);\r
+        newtaggroup.first = n;\r
+        newtaggroup.count = hisize;\r
+        for (int i = 0; i < hisize; i++)\r
+        {\r
+          n.taggroup = newtaggroup;\r
+          n.tag = (i - losize) << ofs; //(i-8)<<28 \r
+          n = n.next;\r
+        }\r
+\r
+        newtaggroup.last = n.prev;\r
+      }\r
+\r
+      int rest = taggroup.count - hisize * newtgs;\r
+\r
+      taggroup.first = n;\r
+      taggroup.count = rest;\r
+      taggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta); ofs--;\r
+      for (int i = 0; i < rest; i++)\r
+      {\r
+        n.tag = (i - hisize) << ofs; //(i-16)<<27 \r
+        n = n.next;\r
+      }\r
+\r
+      taggroup.last = n.prev;\r
+      Taggroups += newtgs;\r
+      if (tgtag == ntgt)\r
+        redistributetaggroups(taggroup);\r
+    }\r
+\r
+\r
+    private void redistributetaggroups(TagGroup taggroup)\r
+    {\r
+      TagGroup pred = taggroup, succ = taggroup, tmp;\r
+      double limit = 1, bigt = Math.Pow(Taggroups, 1.0 / 30);//?????\r
+      int bits = 1, count = 1, lowmask = 0, himask = 0, target = 0;\r
+\r
+      do\r
+      {\r
+        bits++;\r
+        lowmask = (1 << bits) - 1;\r
+        himask = ~lowmask;\r
+        target = taggroup.tag & himask;\r
+        while ((tmp = pred.first.prev.taggroup).first != null && (tmp.tag & himask) == target)\r
+        { count++; pred = tmp; }\r
+\r
+        while ((tmp = succ.last.next.taggroup).last != null && (tmp.tag & himask) == target)\r
+        { count++; succ = tmp; }\r
+\r
+        limit *= bigt;\r
+      } while (count > limit);\r
+\r
+      //redistibute tags\r
+      int lob = pred.first.prev.taggroup.tag, upb = succ.last.next.taggroup.tag;\r
+      int delta = upb / (count + 1) - lob / (count + 1);\r
+\r
+      Debug.Assert(delta > 0);\r
+      for (int i = 0; i < count; i++)\r
+      {\r
+        pred.tag = lob + (i + 1) * delta;\r
+        pred = pred.last.next.taggroup;\r
+      }\r
+    }\r
+#endif\r
+\r
+    #endregion\r
+\r
+    #region Position, PositionComparer and ViewHandler nested types\r
+    class PositionComparer : SCG.IComparer<Position>\r
+    {\r
+      static PositionComparer _default;\r
+      PositionComparer() { }\r
+      public static PositionComparer Default { get { return _default ?? (_default = new PositionComparer()); } }\r
+      public int Compare(Position a, Position b)\r
+      {\r
+#if HASHINDEX\r
+        return a.Endpoint == b.Endpoint ? 0 : a.Endpoint.precedes(b.Endpoint) ? -1 : 1;\r
+#else\r
+        return a.Index.CompareTo(b.Index);\r
+#endif\r
+      }\r
+    }\r
+    /// <summary>\r
+    /// During RemoveAll, we need to cache the original endpoint indices of views\r
+    /// </summary>\r
+    struct Position\r
+    {\r
+      public readonly LinkedList<T> View;\r
+      public bool Left;\r
+#if HASHINDEX\r
+      public readonly Node Endpoint;\r
+#else\r
+      public readonly int Index;\r
+#endif\r
+      public Position(LinkedList<T> view, bool left)\r
+      {\r
+        View = view;\r
+        Left = left;\r
+#if HASHINDEX\r
+        Endpoint = left ? view.startsentinel.next : view.endsentinel.prev;\r
+#else\r
+        Index = left ? view.Offset : view.Offset + view.size - 1;\r
+#endif\r
+      }\r
+#if HASHINDEX\r
+      public Position(Node node, int foo) { this.Endpoint = node; View = null; Left = false;}\r
+#else\r
+      public Position(int index) { this.Index = index; View = null; Left = false; }\r
+#endif\r
+    }\r
+\r
+    //TODO: merge the two implementations using Position values as arguments\r
+    /// <summary>\r
+    /// Handle the update of (other) views during a multi-remove operation.\r
+    /// </summary>\r
+    struct ViewHandler\r
+    {\r
+      ArrayList<Position> leftEnds;\r
+      ArrayList<Position> rightEnds;\r
+      int leftEndIndex, rightEndIndex, leftEndIndex2, rightEndIndex2;\r
+      internal readonly int viewCount;\r
+      internal ViewHandler(LinkedList<T> list)\r
+      {\r
+        leftEndIndex = rightEndIndex = leftEndIndex2 = rightEndIndex2 = viewCount = 0;\r
+        leftEnds = rightEnds = null;\r
+        if (list.views != null)\r
+          foreach (LinkedList<T> v in list.views)\r
+            if (v != list)\r
+            {\r
+              if (leftEnds == null)\r
+              {\r
+                leftEnds = new ArrayList<Position>();\r
+                rightEnds = new ArrayList<Position>();\r
+              }\r
+              leftEnds.Add(new Position(v, true));\r
+              rightEnds.Add(new Position(v, false));\r
+            }\r
+        if (leftEnds == null)\r
+          return;\r
+        viewCount = leftEnds.Count;\r
+        leftEnds.Sort(PositionComparer.Default);\r
+        rightEnds.Sort(PositionComparer.Default);\r
+      }\r
+#if HASHINDEX\r
+      internal void skipEndpoints(int removed, Node n)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex < viewCount && ((endpoint = leftEnds[leftEndIndex]).Endpoint.prev.precedes(n)))\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.offset = view.offset - removed;//TODO: extract offset.Value?\r
+            view.size += removed;\r
+            leftEndIndex++;\r
+          }\r
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Endpoint.precedes(n))\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.size -= removed;\r
+            rightEndIndex++;\r
+          }\r
+        }\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Endpoint.prev.precedes(n))\r
+            leftEndIndex2++;\r
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Endpoint.next.precedes(n))\r
+            rightEndIndex2++;\r
+        }\r
+      }\r
+      /// <summary>\r
+      /// To be called with n pointing to the right of each node to be removed in a stretch. \r
+      /// And at the endsentinel. \r
+      /// \r
+      /// Update offset of a view whose left endpoint (has not already been handled and) is n or precedes n.\r
+      /// I.e. startsentinel precedes n.\r
+      /// Also update the size as a prelude to handling the right endpoint.\r
+      /// \r
+      /// Update size of a view not already handled and whose right endpoint precedes n.\r
+      /// </summary>\r
+      /// <param name="removed">The number of nodes left of n to be removed</param>\r
+      /// <param name="n"></param>\r
+      internal void updateViewSizesAndCounts(int removed, Node n)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex < viewCount && ((endpoint = leftEnds[leftEndIndex]).Endpoint.prev.precedes(n)))\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.offset = view.offset - removed; //TODO: fix use of offset\r
+            view.size += removed;\r
+            leftEndIndex++;\r
+          }\r
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Endpoint.precedes(n))\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.size -= removed;\r
+            rightEndIndex++;\r
+          }\r
+        }\r
+      }\r
+      /// <summary>\r
+      /// To be called with n being the first not-to-be-removed node after a (stretch of) node(s) to be removed.\r
+      /// \r
+      /// It will update the startsentinel of views (that have not been handled before and) \r
+      /// whose startsentinel precedes n, i.e. is to be deleted.\r
+      /// \r
+      /// It will update the endsentinel of views (...) whose endsentinel precedes n, i.e. is to be deleted.\r
+      /// \r
+      /// PROBLEM: DOESNT WORK AS ORIGINALLY ADVERTISED. WE MUST DO THIS BEFORE WE ACTUALLY REMOVE THE NODES. WHEN THE \r
+      /// NODES HAVE BEEN REMOVED, THE precedes METHOD WILL NOT WORK!\r
+      /// </summary>\r
+      /// <param name="n"></param>\r
+      /// <param name="newstart"></param>\r
+      /// <param name="newend"></param>\r
+      internal void updateSentinels(Node n, Node newstart, Node newend)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Endpoint.prev.precedes(n))\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.startsentinel = newstart;\r
+            leftEndIndex2++;\r
+          }\r
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Endpoint.next.precedes(n))\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.endsentinel = newend;\r
+            rightEndIndex2++;\r
+          }\r
+        }\r
+      }\r
+#else\r
+      /// <summary>\r
+      /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed\r
+      /// </summary>\r
+      /// <param name="removed"></param>\r
+      /// <param name="realindex"></param>\r
+      internal void skipEndpoints(int removed, int realindex)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).Index <= realindex)\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.offset = view.offset - removed;\r
+            view.size += removed;\r
+            leftEndIndex++;\r
+          }\r
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Index < realindex)\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.size -= removed;\r
+            rightEndIndex++;\r
+          }\r
+        }\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Index <= realindex)\r
+            leftEndIndex2++;\r
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Index < realindex - 1)\r
+            rightEndIndex2++;\r
+        }\r
+      }\r
+      internal void updateViewSizesAndCounts(int removed, int realindex)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).Index <= realindex)\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.offset = view.Offset - removed;\r
+            view.size += removed;\r
+            leftEndIndex++;\r
+          }\r
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Index < realindex)\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.size -= removed;\r
+            rightEndIndex++;\r
+          }\r
+        }\r
+      }\r
+      internal void updateSentinels(int realindex, Node newstart, Node newend)\r
+      {\r
+        if (viewCount > 0)\r
+        {\r
+          Position endpoint;\r
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Index <= realindex)\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.startsentinel = newstart;\r
+            leftEndIndex2++;\r
+          }\r
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Index < realindex - 1)\r
+          {\r
+            LinkedList<T> view = endpoint.View;\r
+            view.endsentinel = newend;\r
+            rightEndIndex2++;\r
+          }\r
+        }\r
+      }\r
+#endif\r
+    }\r
+    #endregion\r
+\r
+    #region Range nested class\r
+\r
+    class Range : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>\r
+    {\r
+      int start, count, rangestamp;\r
+      Node startnode, endnode;\r
+\r
+      LinkedList<T> list;\r
+\r
+      bool forwards;\r
+\r
+\r
+      internal Range(LinkedList<T> list, int start, int count, bool forwards)\r
+      {\r
+        this.list = list; this.rangestamp = list.underlying != null ? list.underlying.stamp : list.stamp;\r
+        this.start = start; this.count = count; this.forwards = forwards;\r
+        if (count > 0)\r
+        {\r
+          startnode = list.get(start);\r
+          endnode = list.get(start + count - 1);\r
+        }\r
+      }\r
+\r
+      public override bool IsEmpty { get { list.modifycheck(rangestamp); return count == 0; } }\r
+\r
+      [Tested]\r
+      public override int Count { [Tested]get { list.modifycheck(rangestamp); return count; } }\r
+\r
+\r
+      public override Speed CountSpeed { get { list.modifycheck(rangestamp); return Speed.Constant; } }\r
+\r
+\r
+      public override T Choose()\r
+      {\r
+        list.modifycheck(rangestamp);\r
+        if (count > 0) return startnode.item;\r
+        throw new NoSuchItemException();\r
+      }\r
+\r
+\r
+      [Tested]\r
+      public override SCG.IEnumerator<T> GetEnumerator()\r
+      {\r
+        int togo = count;\r
+\r
+        list.modifycheck(rangestamp);\r
+        if (togo == 0)\r
+          yield break;\r
+\r
+        Node cursor = forwards ? startnode : endnode;\r
+\r
+        yield return cursor.item;\r
+        while (--togo > 0)\r
+        {\r
+          cursor = forwards ? cursor.next : cursor.prev;\r
+          list.modifycheck(rangestamp);\r
+          yield return cursor.item;\r
+        }\r
+      }\r
+\r
+\r
+      [Tested]\r
+      public override IDirectedCollectionValue<T> Backwards()\r
+      {\r
+        list.modifycheck(rangestamp);\r
+\r
+        Range b = (Range)MemberwiseClone();\r
+\r
+        b.forwards = !forwards;\r
+        return b;\r
+      }\r
+\r
+\r
+      [Tested]\r
+      IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\r
+\r
+      [Tested]\r
+      public override EnumerationDirection Direction\r
+      {\r
+        [Tested]\r
+        get\r
+        { return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards; }\r
+      }\r
+    }\r
+\r
+\r
+    #endregion\r
+\r
+    #region IDisposable Members\r
+\r
+    /// <summary>\r
+    /// Invalidate this list. If a view, just invalidate the view. \r
+    /// If not a view, invalidate the list and all views on it.\r
+    /// </summary>\r
+    public virtual void Dispose()\r
+    {\r
+      Dispose(false);\r
+    }\r
+\r
+    void Dispose(bool disposingUnderlying)\r
+    {\r
+      if (isValid)\r
+      {\r
+        if (underlying != null)\r
+        {\r
+          isValid = false;\r
+          if (!disposingUnderlying)\r
+            views.Remove(myWeakReference);\r
+          endsentinel = null;\r
+          startsentinel = null;\r
+          underlying = null;\r
+          views = null;\r
+          myWeakReference = null;\r
+        }\r
+        else\r
+        {\r
+          //isValid = false;\r
+          //endsentinel = null;\r
+          //startsentinel = null;\r
+          foreach (LinkedList<T> view in views)\r
+            view.Dispose(true);\r
+          //views = null;\r
+          Clear();\r
+        }\r
+      }\r
+    }\r
+\r
+    #endregion IDisposable stuff\r
+\r
+    #region IList<T> Members\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <value>The first item in this list.</value>\r
+    [Tested]\r
+    public virtual T First\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+        validitycheck();\r
+        if (size == 0)\r
+          throw new NoSuchItemException();\r
+        return startsentinel.next.item;\r
+      }\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>\r
+    /// <value>The last item in this list.</value>\r
+    [Tested]\r
+    public virtual T Last\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+        validitycheck();\r
+        if (size == 0)\r
+          throw new NoSuchItemException();\r
+        return endsentinel.prev.item;\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. THe default for a new linked list is true.</value>\r
+    [Tested]\r
+    public virtual bool FIFO\r
+    {\r
+      [Tested]\r
+      get { validitycheck(); return fIFO; }\r
+      [Tested]\r
+      set { updatecheck(); fIFO = value; }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    public virtual bool IsFixedSize\r
+    {\r
+      get { validitycheck(); return false; }\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="index">The index of the item to fetch or store.</param>\r
+    [Tested]\r
+    public virtual T this[int index]\r
+    {\r
+      [Tested]\r
+      get { validitycheck(); return get(index).item; }\r
+      [Tested]\r
+      set\r
+      {\r
+        updatecheck();\r
+        Node n = get(index);\r
+        //\r
+        T item = n.item;\r
+#if HASHINDEX\r
+\r
+        if (itemequalityComparer.Equals(value, item))\r
+        {\r
+          n.item = value;\r
+          dict.Update(value, n);\r
+        }\r
+        else if (!dict.FindOrAdd(value, ref n))\r
+        {\r
+          dict.Remove(item);\r
+          n.item = value;\r
+        }\r
+        else\r
+          throw new ArgumentException("Item already in indexed list");\r
+#else\r
+        n.item = value;\r
+#endif\r
+        (underlying ?? this).raiseForSetThis(index, value, item);\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual Speed IndexingSpeed { get { return Speed.Linear; } }\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
+      insert(i, i == size ? endsentinel : get(i), item);\r
+      if (ActiveEvents != EventTypeEnum.None)\r
+        (underlying ?? this).raiseForInsert(i + Offset, item);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Insert an item at the end of a compatible view, used as a pointer.\r
+    /// <para>The <code>pointer</code> must be a view on the same list as\r
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be\r
+    /// a valid insertion point of <code>this</code></para>\r
+    /// </summary>\r
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> \r
+    /// is not a view on the same list as <code>this</code></exception>\r
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of \r
+    ///  <code>pointer</code> is not inside <code>this</code></exception>\r
+    /// <exception cref="DuplicateNotAllowedException"> if the list has\r
+    /// <code>AllowsDuplicates==false</code> and the item is \r
+    /// already in the list.</exception>\r
+    /// <param name="pointer"></param>\r
+    /// <param name="item"></param>\r
+    public void Insert(IList<T> pointer, T item)\r
+    {\r
+      updatecheck();\r
+      if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this)))\r
+        throw new IncompatibleViewException();\r
+#warning INEFFICIENT\r
+      //TODO: make this efficient (the whole point of the method:\r
+      //Do NOT use Insert, but insert the node at pointer.endsentinel, checking\r
+      //via the ordering that this is a valid insertion point\r
+      Insert(pointer.Offset + pointer.Count - Offset, item);\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
+    /// <typeparam name="U"></typeparam>\r
+    [Tested]\r
+    public virtual void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      insertAll(i, items, true);\r
+    }\r
+\r
+    void insertAll<U>(int i, SCG.IEnumerable<U> items, bool insertion) where U : T\r
+    {\r
+      updatecheck();\r
+      Node succ, node, pred;\r
+      int count = 0;\r
+      succ = i == size ? endsentinel : get(i);\r
+      pred = node = succ.prev;\r
+#if HASHINDEX\r
+      TagGroup taggroup = null;\r
+      int taglimit = 0, thetag = 0;\r
+      taggroup = gettaggroup(node, succ, out thetag, out taglimit);\r
+      try\r
+      {\r
+        foreach (T item in items)\r
+        {\r
+          Node tmp = new Node(item, node, null);\r
+          if (!dict.FindOrAdd(item, ref tmp))\r
+          {\r
+            tmp.tag = thetag < taglimit ? ++thetag : thetag;\r
+            tmp.taggroup = taggroup;\r
+            node.next = tmp;\r
+            count++;\r
+            node = tmp;\r
+          }\r
+          else\r
+            throw new DuplicateNotAllowedException("Item already in indexed list");\r
+        }\r
+      }\r
+      finally\r
+      {\r
+        taggroup.count += count;\r
+        taggroup.first = succ.prev;\r
+        taggroup.last = node;\r
+        succ.prev = node;\r
+        node.next = succ;\r
+        if (node.tag == node.prev.tag)\r
+          splittaggroup(taggroup);\r
+        size += count;\r
+        if (underlying != null)\r
+          underlying.size += count;\r
+        if (count > 0)\r
+        {\r
+          fixViewsAfterInsert(succ, pred, count, 0);\r
+          raiseForInsertAll(pred, i, count, insertion);\r
+        }\r
+      }\r
+#else\r
+      foreach (T item in items)\r
+      {\r
+        Node tmp = new Node(item, node, null);\r
+        node.next = tmp;\r
+        count++;\r
+        node = tmp;\r
+      }\r
+      if (count == 0)\r
+        return;\r
+      succ.prev = node;\r
+      node.next = succ;\r
+      size += count;\r
+      if (underlying != null)\r
+        underlying.size += count;\r
+      if (count > 0)\r
+      {\r
+        fixViewsAfterInsert(succ, pred, count, offset + i);\r
+        raiseForInsertAll(pred, i, count, insertion);\r
+      }\r
+#endif\r
+    }\r
+\r
+    private void raiseForInsertAll(Node node, int i, int added, bool insertion)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        int index = Offset + i;\r
+        if ((ActiveEvents & (EventTypeEnum.Added | EventTypeEnum.Inserted)) != 0)\r
+          for (int j = index; j < index + added; j++)\r
+          {\r
+#warning must we check stamps here?\r
+            node = node.next;\r
+            T item = node.item;\r
+            if (insertion) raiseItemInserted(item, j);\r
+            raiseItemsAdded(item, 1);\r
+          }\r
+        raiseCollectionChanged();\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, startsentinel.next, item);\r
+      if (ActiveEvents != EventTypeEnum.None)\r
+        (underlying ?? this).raiseForInsert(0 + Offset, item);\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, endsentinel, item);\r
+      if (ActiveEvents != EventTypeEnum.None)\r
+        (underlying ?? this).raiseForInsert(size - 1 + Offset, item);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a new list consisting of the results of mapping all items of this\r
+    /// list.\r
+    /// </summary>\r
+    /// <param name="mapper">The delegate definging the map.</param>\r
+    /// <returns>The new list.</returns>\r
+    [Tested]\r
+    public IList<V> Map<V>(Fun<T, V> mapper)\r
+    {\r
+      validitycheck();\r
+\r
+      LinkedList<V> retval = new LinkedList<V>();\r
+      return map<V>(mapper, retval);\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 equalityComparer 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="equalityComparer">The equalityComparer to use for the new list</param>\r
+    /// <returns>The new list.</returns>\r
+    public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer)\r
+    {\r
+      validitycheck();\r
+\r
+      LinkedList<V> retval = new LinkedList<V>(equalityComparer);\r
+      return map<V>(mapper, retval);\r
+    }\r
+\r
+    private IList<V> map<V>(Fun<T, V> mapper, LinkedList<V> retval)\r
+    {\r
+      if (size == 0)\r
+        return retval;\r
+      int stamp = this.stamp;\r
+      Node cursor = startsentinel.next;\r
+      LinkedList<V>.Node mcursor = retval.startsentinel;\r
+\r
+#if HASHINDEX\r
+      double tagdelta = int.MaxValue / (size + 1.0);\r
+      int count = 1;\r
+      LinkedList<V>.TagGroup taggroup = null;\r
+      taggroup = new LinkedList<V>.TagGroup();\r
+      retval.taggroups = 1;\r
+      taggroup.count = size;\r
+#endif\r
+      while (cursor != endsentinel)\r
+      {\r
+        V v = mapper(cursor.item);\r
+        modifycheck(stamp);\r
+        mcursor.next = new LinkedList<V>.Node(v, mcursor, null);\r
+        cursor = cursor.next;\r
+        mcursor = mcursor.next;\r
+#if HASHINDEX\r
+        retval.dict.Add(v, mcursor);\r
+        mcursor.taggroup = taggroup;\r
+        mcursor.tag = (int)(tagdelta * count++);\r
+#endif\r
+      }\r
+\r
+      retval.endsentinel.prev = mcursor;\r
+      mcursor.next = retval.endsentinel;\r
+      retval.size = size;\r
+      return retval;\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="NoSuchItemException"/> if this list is empty.\r
+    /// </summary>\r
+    /// <returns>The removed item.</returns>\r
+    [Tested]\r
+    public virtual T Remove()\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        throw new NoSuchItemException("List is empty");\r
+      T item = fIFO ? remove(startsentinel.next, 0) : remove(endsentinel.prev, size - 1);\r
+#if HASHINDEX\r
+      dict.Remove(item);\r
+#endif\r
+      (underlying ?? this).raiseForRemove(item);\r
+      return item;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove one item from the front of the list.\r
+    /// <exception cref="NoSuchItemException"/> 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 NoSuchItemException("List is empty");\r
+\r
+      T item = remove(startsentinel.next, 0);\r
+#if HASHINDEX\r
+      dict.Remove(item);\r
+#endif\r
+      if (ActiveEvents != EventTypeEnum.None)\r
+        (underlying ?? this).raiseForRemoveAt(Offset, item);\r
+      return item;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove one item from the back of the list.\r
+    /// <exception cref="NoSuchItemException"/> if this list is empty.\r
+    /// </summary>\r
+    /// <returns>The removed item.</returns>\r
+    [Tested]\r
+    public virtual T RemoveLast()\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        throw new NoSuchItemException("List is empty");\r
+\r
+      T item = remove(endsentinel.prev, size - 1);\r
+#if HASHINDEX\r
+      dict.Remove(item);\r
+#endif\r
+      if (ActiveEvents != EventTypeEnum.None)\r
+        (underlying ?? this).raiseForRemoveAt(size + Offset, item);\r
+      return item;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a list view on this list. \r
+    /// </summary>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative</exception>\r
+    /// <exception cref="ArgumentException"> if the range does not fit within list.</exception>\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
+      checkRange(start, count);\r
+      validitycheck();\r
+      if (views == null)\r
+        views = new WeakViewList<LinkedList<T>>();\r
+      LinkedList<T> retval = (LinkedList<T>)MemberwiseClone();\r
+      retval.underlying = underlying != null ? underlying : this;\r
+      retval.offset = offset + start;\r
+      retval.size = count;\r
+      getPair(start - 1, start + count, out retval.startsentinel, out retval.endsentinel,\r
+          new int[] { -1, size }, new Node[] { startsentinel, endsentinel });\r
+      //retval.startsentinel = start == 0 ? startsentinel : get(start - 1);\r
+      //retval.endsentinel = start + count == size ? endsentinel : get(start + count);\r
+\r
+      //TODO: for the purpose of Dispose, we need to retain a ref to the node\r
+      retval.myWeakReference = views.Add(retval);\r
+      return retval;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a list view on this list containing the (first) occurrence of a particular item. \r
+    /// </summary>\r
+    /// <exception cref="ArgumentException"> if the item is not in this list.</exception>\r
+    /// <param name="item">The item to find.</param>\r
+    /// <returns>The new list view.</returns>\r
+    public virtual IList<T> ViewOf(T item)\r
+    {\r
+#if HASHINDEX\r
+      Node n;\r
+      validitycheck();\r
+      if (!contains(item, out n))\r
+        return null;\r
+      LinkedList<T> retval = (LinkedList<T>)MemberwiseClone();\r
+      retval.underlying = underlying != null ? underlying : this;\r
+      retval.offset = null;\r
+      retval.startsentinel = n.prev;\r
+      retval.endsentinel = n.next;\r
+      retval.size = 1;\r
+      return retval;\r
+#else\r
+      int index = 0;\r
+      Node n = startsentinel.next;\r
+      if (!find(item, ref n, ref index))\r
+        return null;\r
+      //TODO: optimize with getpair!\r
+      return View(index, 1);\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// Create a list view on this list containing the last occurrence of a particular item. \r
+    /// <exception cref="ArgumentException"/> if the item is not in this list.\r
+    /// </summary>\r
+    /// <param name="item">The item to find.</param>\r
+    /// <returns>The new list view.</returns>\r
+    public virtual IList<T> LastViewOf(T item)\r
+    {\r
+#if HASHINDEX\r
+      return ViewOf(item);\r
+#else\r
+      int index = size - 1;\r
+      Node n = endsentinel.prev;\r
+      if (!dnif(item, ref n, ref index))\r
+        return null;\r
+      return View(index, 1);\r
+#endif\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 virtual IList<T> Underlying { [Tested]get { validitycheck(); return underlying; } }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual bool IsValid { get { return isValid; } }\r
+\r
+    /// <summary>\r
+    /// </summary>\r
+    /// <value>Offset for this list view or 0 for a underlying list.</value>\r
+    [Tested]\r
+    public virtual int Offset\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+        validitycheck();\r
+#if HASHINDEX\r
+        if (offset == null && underlying != null)\r
+        {\r
+          //TODO: search from both ends simultaneously!\r
+          Node n = underlying.startsentinel;\r
+          int i = 0;\r
+          while (n != startsentinel) { n = n.next; i++; }\r
+          offset = i;\r
+        }\r
+#endif\r
+        return (int)offset;\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Slide this list view along the underlying list.\r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation\r
+    /// would bring either end of the view outside the underlying list.</exception>\r
+    /// <param name="offset">The signed amount to slide: positive to slide\r
+    /// towards the end.</param>\r
+    [Tested]\r
+    public IList<T> Slide(int offset)\r
+    {\r
+      if (!TrySlide(offset, size))\r
+        throw new ArgumentOutOfRangeException();\r
+      return this;\r
+    }\r
+\r
+    //TODO: more test cases\r
+    /// <summary>\r
+    /// Slide this list view along the underlying list, perhaps changing its size.\r
+    /// </summary>\r
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>\r
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation\r
+    /// would bring either end of the view outside the underlying list.</exception>\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
+    public IList<T> Slide(int offset, int size)\r
+    {\r
+      if (!TrySlide(offset, size))\r
+        throw new ArgumentOutOfRangeException();\r
+      return this;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <returns></returns>\r
+    public virtual bool TrySlide(int offset) { return TrySlide(offset, size); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="offset"></param>\r
+    /// <param name="size"></param>\r
+    /// <returns></returns>\r
+    public virtual bool TrySlide(int offset, int size)\r
+    {\r
+      updatecheck();\r
+      if (underlying == null)\r
+        throw new NotAViewException("List not a view");\r
+\r
+#pragma warning disable 472\r
+      if (this.offset == null) //Note: only possible with HASHINDEX\r
+#pragma warning restore 472\r
+      {\r
+#pragma warning disable 162\r
+        try\r
+        {\r
+          getPair(offset - 1, offset + size, out startsentinel, out endsentinel,\r
+              new int[] { -1, this.size }, new Node[] { startsentinel, endsentinel });\r
+          //TODO: maybe-update offset field\r
+        }\r
+        catch (NullReferenceException)\r
+        {\r
+          return false;\r
+        }\r
+#pragma warning restore 162\r
+      }\r
+      else\r
+      {\r
+        if (offset + this.offset < 0 || offset + this.offset + size > underlying.size)\r
+          return false;\r
+        int oldoffset = (int)(this.offset);\r
+        getPair(offset - 1, offset + size, out startsentinel, out endsentinel,\r
+            new int[] { -oldoffset - 1, -1, this.size, underlying.size - oldoffset },\r
+            new Node[] { underlying.startsentinel, startsentinel, endsentinel, underlying.endsentinel });\r
+      }\r
+      this.size = size;\r
+      this.offset += offset;\r
+      return true;\r
+    }\r
+\r
+\r
+    //TODO: improve the complexity of the implementation\r
+    /// <summary>\r
+    /// \r
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>\r
+    /// </summary>\r
+    /// <param name="otherView"></param>\r
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>\r
+    /// <returns></returns>\r
+    public virtual IList<T> Span(IList<T> otherView)\r
+    {\r
+      if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this)))\r
+        throw new IncompatibleViewException();\r
+      if (otherView.Offset + otherView.Count - Offset < 0)\r
+        return null;\r
+      return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset);\r
+    }\r
+\r
+\r
+    //Question: should we swap items or move nodes around?\r
+    //The first seems much more efficient unless the items are value types \r
+    //with a large memory footprint.\r
+    //(Swapping will do count*3/2 T assignments, linking around will do \r
+    // 4*count ref assignments; note that ref assignments are more expensive \r
+    //than copying non-ref bits)\r
+    /// <summary>\r
+    /// Reverse the list so the items are in the opposite sequence order.\r
+    /// </summary>\r
+    [Tested]\r
+    public virtual void Reverse()\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+\r
+      Position[] positions = null;\r
+      int poslow = 0, poshigh = 0;\r
+      if (views != null)\r
+      {\r
+        CircularQueue<Position> _positions = null;\r
+        foreach (LinkedList<T> view in views)\r
+        {\r
+          if (view != this)\r
+          {\r
+            switch (viewPosition(view))\r
+            {\r
+              case MutualViewPosition.ContainedIn:\r
+                (_positions ?? (_positions = new CircularQueue<Position>())).Enqueue(new Position(view, true));\r
+                _positions.Enqueue(new Position(view, false));\r
+                break;\r
+              case MutualViewPosition.Overlapping:\r
+                view.Dispose();\r
+                break;\r
+              case MutualViewPosition.Contains:\r
+              case MutualViewPosition.NonOverlapping:\r
+                break;\r
+            }\r
+          }\r
+        }\r
+        if (_positions != null)\r
+        {\r
+          positions = _positions.ToArray();\r
+          Sorting.IntroSort<Position>(positions, 0, positions.Length, PositionComparer.Default);\r
+          poshigh = positions.Length - 1;\r
+        }\r
+      }\r
+\r
+      Node a = get(0), b = get(size - 1);\r
+      for (int i = 0; i < size / 2; i++)\r
+      {\r
+        T swap;\r
+        swap = a.item; a.item = b.item; b.item = swap;\r
+#if HASHINDEX\r
+        dict[a.item] = a; dict[b.item] = b;\r
+#endif\r
+        if (positions != null)\r
+          mirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, i);\r
+        a = a.next; b = b.prev;\r
+      }\r
+      if (positions != null && size % 2 != 0)\r
+        mirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, size / 2);\r
+      (underlying ?? this).raiseCollectionChanged();\r
+    }\r
+\r
+    private void mirrorViewSentinelsForReverse(Position[] positions, ref int poslow, ref int poshigh, Node a, Node b, int i)\r
+    {\r
+#if HASHINDEX\r
+      int? aindex = offset + i, bindex = offset + size - 1 - i;\r
+#else\r
+      int aindex = offset + i, bindex = offset + size - 1 - i;\r
+#endif\r
+      Position pos;\r
+#if HASHINDEX\r
+      while (poslow <= poshigh && (pos = positions[poslow]).Endpoint == a)\r
+#else\r
+      while (poslow <= poshigh && (pos = positions[poslow]).Index == aindex)\r
+#endif\r
+      {\r
+        //TODO: Note: in the case og hashed linked list, if this.offset == null, but pos.View.offset!=null\r
+        //we may at this point compute this.offset and non-null values of aindex and bindex\r
+        if (pos.Left)\r
+          pos.View.endsentinel = b.next;\r
+        else\r
+        {\r
+          pos.View.startsentinel = b.prev;\r
+          pos.View.offset = bindex;\r
+        }\r
+        poslow++;\r
+      }\r
+#if HASHINDEX\r
+      while (poslow < poshigh && (pos = positions[poshigh]).Endpoint == b)\r
+#else\r
+      while (poslow < poshigh && (pos = positions[poshigh]).Index == bindex)\r
+#endif\r
+      {\r
+        if (pos.Left)\r
+          pos.View.endsentinel = a.next;\r
+        else\r
+        {\r
+          pos.View.startsentinel = a.prev;\r
+          pos.View.offset = aindex;\r
+        }\r
+        poshigh--;\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this list is sorted according to the default sorting order\r
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class \r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">if T is not comparable</exception>\r
+    /// <returns>True if the list is sorted, else false.</returns>\r
+    public bool IsSorted() { return IsSorted(Comparer<T>.Default); }\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(SCG.IComparer<T> c)\r
+    {\r
+      validitycheck();\r
+      if (size <= 1)\r
+        return true;\r
+\r
+      Node node = startsentinel.next;\r
+      T prevItem = node.item;\r
+\r
+      node = node.next;\r
+      while (node != endsentinel)\r
+      {\r
+        if (c.Compare(prevItem, node.item) > 0)\r
+          return false;\r
+        else\r
+        {\r
+          prevItem = node.item;\r
+          node = node.next;\r
+        }\r
+      }\r
+\r
+      return true;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Sort the items of the list according to the default sorting order\r
+    /// for the item type T, as defined by the Comparer[T] class. \r
+    /// (<see cref="T:C5.Comparer`1"/>).\r
+    /// The sorting is stable.\r
+    /// </summary>\r
+    /// <exception cref="InvalidOperationException">if T is not comparable</exception>\r
+    public virtual void Sort() { Sort(Comparer<T>.Default); }\r
+\r
+    // Sort the linked list using mergesort\r
+    /// <summary>\r
+    /// Sort the items of the list according to a specific sorting order.\r
+    /// The sorting is stable.\r
+    /// </summary>\r
+    /// <param name="c">The comparer defining the sorting order.</param>\r
+    [Tested]\r
+    public virtual void Sort(SCG.IComparer<T> c)\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      disposeOverlappingViews(false);\r
+#if HASHINDEX\r
+      if (underlying != null)\r
+      {\r
+        Node cursor = startsentinel.next;\r
+        while (cursor != endsentinel)\r
+        {\r
+          cursor.taggroup.count--;\r
+          cursor = cursor.next;\r
+        }\r
+      }\r
+#endif\r
+      // Build a linked list of non-empty runs.\r
+      // The prev field in first node of a run points to next run's first node\r
+      Node runTail = startsentinel.next;\r
+      Node prevNode = startsentinel.next;\r
+\r
+      endsentinel.prev.next = null;\r
+      while (prevNode != null)\r
+      {\r
+        Node node = prevNode.next;\r
+\r
+        while (node != null && c.Compare(prevNode.item, node.item) <= 0)\r
+        {\r
+          prevNode = node;\r
+          node = prevNode.next;\r
+        }\r
+\r
+        // Completed a run; prevNode is the last node of that run\r
+        prevNode.next = null;  // Finish the run\r
+        runTail.prev = node;   // Link it into the chain of runs\r
+        runTail = node;\r
+        if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0)\r
+          endsentinel.prev = prevNode; // Update last pointer to point to largest\r
+\r
+        prevNode = node;               // Start a new run\r
+      }\r
+\r
+      // Repeatedly merge runs two and two, until only one run remains\r
+      while (startsentinel.next.prev != null)\r
+      {\r
+        Node run = startsentinel.next;\r
+        Node newRunTail = null;\r
+\r
+        while (run != null && run.prev != null)\r
+        { // At least two runs, merge\r
+          Node nextRun = run.prev.prev;\r
+          Node newrun = mergeRuns(run, run.prev, c);\r
+\r
+          if (newRunTail != null)\r
+            newRunTail.prev = newrun;\r
+          else\r
+            startsentinel.next = newrun;\r
+\r
+          newRunTail = newrun;\r
+          run = nextRun;\r
+        }\r
+\r
+        if (run != null) // Add the last run, if any\r
+          newRunTail.prev = run;\r
+      }\r
+\r
+      endsentinel.prev.next = endsentinel;\r
+      startsentinel.next.prev = startsentinel;\r
+\r
+      //assert invariant();\r
+      //assert isSorted();\r
+#if HASHINDEX\r
+      {\r
+        Node cursor = startsentinel.next, end = endsentinel;\r
+        int tag, taglimit;\r
+        TagGroup t = gettaggroup(startsentinel, endsentinel, out tag, out taglimit);\r
+        int tagdelta = taglimit / (size + 1) - tag / (size + 1);\r
+        tagdelta = tagdelta == 0 ? 1 : tagdelta;\r
+        if (underlying == null)\r
+          taggroups = 1;\r
+        while (cursor != end)\r
+        {\r
+          tag = tag + tagdelta > taglimit ? taglimit : tag + tagdelta;\r
+          cursor.tag = tag;\r
+          t.count++;\r
+          cursor = cursor.next;\r
+        }\r
+        if (tag == taglimit)\r
+          splittaggroup(t);\r
+      }\r
+#endif\r
+      (underlying ?? this).raiseCollectionChanged();\r
+    }\r
+\r
+    private static Node mergeRuns(Node run1, Node run2, SCG.IComparer<T> c)\r
+    {\r
+      //assert run1 != null && run2 != null;\r
+      Node prev;\r
+      bool prev1;      // is prev from run1?\r
+\r
+      if (c.Compare(run1.item, run2.item) <= 0)\r
+      {\r
+        prev = run1;\r
+        prev1 = true;\r
+        run1 = run1.next;\r
+      }\r
+      else\r
+      {\r
+        prev = run2;\r
+        prev1 = false;\r
+        run2 = run2.next;\r
+      }\r
+\r
+      Node start = prev;\r
+\r
+      //assert start != null;\r
+      start.prev = null;\r
+      while (run1 != null && run2 != null)\r
+      {\r
+        if (prev1)\r
+        {\r
+          //assert prev.next == run1;\r
+          //Comparable run2item = (Comparable)run2.item;\r
+          while (run1 != null && c.Compare(run2.item, run1.item) >= 0)\r
+          {\r
+            prev = run1;\r
+            run1 = prev.next;\r
+          }\r
+\r
+          if (run1 != null)\r
+          { // prev.item <= run2.item < run1.item; insert run2\r
+            prev.next = run2;\r
+            run2.prev = prev;\r
+            prev = run2;\r
+            run2 = prev.next;\r
+            prev1 = false;\r
+          }\r
+        }\r
+        else\r
+        {\r
+          //assert prev.next == run2;\r
+          //Comparable run1item = (Comparable)run1.item;\r
+          while (run2 != null && c.Compare(run1.item, run2.item) > 0)\r
+          {\r
+            prev = run2;\r
+            run2 = prev.next;\r
+          }\r
+\r
+          if (run2 != null)\r
+          { // prev.item < run1.item <= run2.item; insert run1\r
+            prev.next = run1;\r
+            run1.prev = prev;\r
+            prev = run1;\r
+            run1 = prev.next;\r
+            prev1 = true;\r
+          }\r
+        }\r
+      }\r
+\r
+      //assert !(run1 != null && prev1) && !(run2 != null && !prev1);\r
+      if (run1 != null)\r
+      { // last run2 < all of run1; attach run1 at end\r
+        prev.next = run1;\r
+        run1.prev = prev;\r
+      }\r
+      else if (run2 != null)\r
+      { // last run1 \r
+        prev.next = run2;\r
+        run2.prev = prev;\r
+      }\r
+\r
+      return start;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Randomly shuffle the items of this list. \r
+    /// <para>Will invalidate overlapping views???</para>\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
+    /// <para>Will invalidate overlapping views???</para>\r
+    /// </summary>\r
+    /// <param name="rnd">The random source.</param>\r
+    public virtual void Shuffle(Random rnd)\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      disposeOverlappingViews(false);\r
+      ArrayList<T> a = new ArrayList<T>();\r
+      a.AddAll(this);\r
+      a.Shuffle(rnd);\r
+      Node cursor = startsentinel.next;\r
+      int j = 0;\r
+      while (cursor != endsentinel)\r
+      {\r
+        cursor.item = a[j++];\r
+#if HASHINDEX\r
+        dict[cursor.item] = cursor;\r
+#endif\r
+        cursor = cursor.next;\r
+      }\r
+      (underlying ?? this).raiseCollectionChanged();\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IIndexed<T> 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
+        validitycheck();\r
+        checkRange(start, count);\r
+        return new Range(this, start, count, true);\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 virtual int IndexOf(T item)\r
+    {\r
+      validitycheck();\r
+      Node node;\r
+#if HASHINDEX\r
+      if (!dict.Find(item, out node) || !insideview(node))\r
+        return ~size;\r
+#endif\r
+      node = startsentinel.next;\r
+      int index = 0;\r
+      if (find(item, ref node, ref index))\r
+        return index;\r
+      else\r
+        return ~size;\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 virtual int LastIndexOf(T item)\r
+    {\r
+#if HASHINDEX\r
+      return IndexOf(item);\r
+#else\r
+      validitycheck();\r
+\r
+      Node node = endsentinel.prev;\r
+      int index = size - 1;\r
+\r
+      if (dnif(item, ref node, ref index))\r
+        return index;\r
+      else\r
+        return ~size;\r
+#endif\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
+      T retval = remove(get(i), i);\r
+#if HASHINDEX\r
+      dict.Remove(retval);\r
+#endif\r
+      if (ActiveEvents != EventTypeEnum.None)\r
+        (underlying ?? this).raiseForRemoveAt(Offset + i, retval);\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 virtual void RemoveInterval(int start, int count)\r
+    {\r
+#if HASHINDEX\r
+      updatecheck();\r
+      checkRange(start, count);\r
+      if (count == 0)\r
+        return;\r
+\r
+      View(start, count).Clear();\r
+#else\r
+      //Note: this is really almost equaivalent to Clear on a view\r
+      updatecheck();\r
+      checkRange(start, count);\r
+      if (count == 0)\r
+        return;\r
+\r
+      //for small count: optimize\r
+      //use an optimal get(int i, int j, ref Node ni, ref Node nj)?\r
+      Node a = get(start), b = get(start + count - 1);\r
+      fixViewsBeforeRemove(start, count, a, b);\r
+      a.prev.next = b.next;\r
+      b.next.prev = a.prev;\r
+      if (underlying != null)\r
+        underlying.size -= count;\r
+\r
+      size -= count;\r
+      if (ActiveEvents != EventTypeEnum.None)\r
+        (underlying ?? this).raiseForRemoveInterval(start + Offset, count);\r
+#endif\r
+    }\r
+\r
+    void raiseForRemoveInterval(int start, int count)\r
+    {\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseCollectionCleared(size == 0, count, start);\r
+        raiseCollectionChanged();\r
+      }\r
+    }\r
+    #endregion\r
+\r
+    #region ISequenced<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override int GetSequencedHashCode() { validitycheck(); return base.GetSequencedHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="that"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override bool SequencedEquals(ISequenced<T> that) { validitycheck(); return base.SequencedEquals(that); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedCollection<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
+    public override IDirectedCollectionValue<T> Backwards()\r
+    { return this[0, size].Backwards(); }\r
+\r
+    #endregion\r
+\r
+    #region IDirectedEnumerable<T> Members\r
+\r
+    [Tested]\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\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 (worst-case or amortized as\r
+    /// relevant).\r
+    /// </summary>\r
+    /// <value>Speed.Linear</value>\r
+    [Tested]\r
+    public virtual Speed ContainsSpeed\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+#if HASHINDEX\r
+        return  Speed.Constant ;\r
+#else\r
+        return Speed.Linear;\r
+#endif\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// Performs a check for view validity before calling base.GetUnsequencedHashCode()\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override int GetUnsequencedHashCode()\r
+    { validitycheck(); return base.GetUnsequencedHashCode(); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="that"></param>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override bool UnsequencedEquals(ICollection<T> that)\r
+    { validitycheck(); return base.UnsequencedEquals(that); }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains (an item equivalent to according to the\r
+    /// itemequalityComparer) 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
+    {\r
+      validitycheck();\r
+      Node node;\r
+      return contains(item, out node);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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
+      validitycheck();\r
+      Node node;\r
+      if (contains(item, out node)) { item = node.item; return true; }\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer to a particular value. If so, update the item in the collection \r
+    /// to with a binary copy of the supplied value. Will update a single 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) { T olditem; return Update(item, out olditem); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool Update(T item, out T olditem)\r
+    {\r
+      updatecheck();\r
+      Node node;\r
+\r
+      if (contains(item, out node))\r
+      {\r
+        olditem = node.item;\r
+        node.item = item;\r
+#if HASHINDEX\r
+        //Avoid clinging onto a reference to olditem via dict!\r
+        dict.Update(item, node);\r
+#endif\r
+        (underlying ?? this).raiseForUpdate(item, olditem);\r
+        return true;\r
+      }\r
+\r
+      olditem = default(T);\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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 HASHINDEX\r
+      //This is an extended myinsert:\r
+      Node node = new Node(item);\r
+      if (!dict.FindOrAdd(item, ref node))\r
+      {\r
+        insertNode(true, endsentinel, node);\r
+        (underlying ?? this).raiseForAdd(item);\r
+        return false; \r
+      }\r
+      if (!insideview(node))\r
+        throw new ArgumentException("Item alredy in indexed list but outside view");\r
+      item = node.item;\r
+      return true;\r
+#else\r
+      if (Find(ref item))\r
+        return true;\r
+\r
+      Add(item);\r
+      return false;\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer 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 virtual bool UpdateOrAdd(T item) { T olditem; return UpdateOrAdd(item, out olditem); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public virtual bool UpdateOrAdd(T item, out T olditem)\r
+    {\r
+      updatecheck();\r
+#if HASHINDEX\r
+      Node node = new Node(item);\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
+        olditem = node.item;\r
+        //Avoid clinging onto a reference to olditem via dict!\r
+        dict.Update(item, node);\r
+        node.item = item;\r
+        (underlying ?? this).raiseForUpdate(item, olditem);\r
+        return true;\r
+      }\r
+      insertNode(true, endsentinel, node);\r
+      (underlying ?? this).raiseForAdd(item);\r
+#else\r
+      if (Update(item, out olditem))\r
+        return true;\r
+      Add(item);\r
+#endif\r
+      olditem = default(T);\r
+      return false;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove a particular item from this collection. Since 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 virtual bool Remove(T item)\r
+    {\r
+      updatecheck();\r
+      int i = 0;\r
+      Node node;\r
+#if HASHINDEX\r
+      if (!dictremove(item, out node))\r
+#else\r
+      node = fIFO ? startsentinel.next : endsentinel.prev;\r
+      if (!(fIFO ? find(item, ref node, ref i) : dnif(item, ref node, ref i)))\r
+#endif\r
+        return false;\r
+      T removeditem = remove(node, i);\r
+      (underlying ?? this).raiseForRemove(removeditem);\r
+      return true;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove a particular item from this collection if found (only one copy). \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
+    /// <param name="removeditem">The value removed.</param>\r
+    /// <returns>True if the item was found (and removed).</returns>\r
+    [Tested]\r
+    public virtual bool Remove(T item, out T removeditem)\r
+    {\r
+      updatecheck();\r
+      int i = 0;\r
+      Node node;\r
+#if HASHINDEX\r
+      if (!dictremove(item, out node))\r
+#else\r
+      node = fIFO ? startsentinel.next : endsentinel.prev;\r
+      if (!(fIFO ? find(item, ref node, ref i) : dnif(item, ref node, ref i)))\r
+#endif\r
+      {\r
+        removeditem = default(T);\r
+        return false;\r
+      }\r
+      removeditem = node.item;\r
+      remove(node, i);\r
+      (underlying ?? this).raiseForRemove(removeditem);\r
+      return true;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove all items in another collection from this one, taking multiplicities into account.\r
+    /// <para>Always removes from the front of the list.\r
+    /// </para>\r
+    /// <para>The asymptotic running time complexity of this method is <code>O(n+m+v*log(v))</code>, \r
+    /// where <code>n</code> is the size of this list, <code>m</code> is the size of the\r
+    /// <code>items</code> collection and <code>v</code> is the number of views. \r
+    /// The method will temporarily allocate memory of size <code>O(m+v)</code>.\r
+    /// </para>\r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to remove.</param>\r
+    [Tested]\r
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+#if HASHINDEX\r
+      Node node;\r
+      foreach (T item in items)\r
+        if (dictremove(item, out node))\r
+        {\r
+          if (mustFire)\r
+            raiseHandler.Remove(node.item);\r
+          remove(node, 118);\r
+        }\r
+#else\r
+      HashBag<T> toremove = new HashBag<T>(itemequalityComparer);\r
+      toremove.AddAll(items);\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int index = 0, removed = 0, myoffset = Offset;\r
+      Node node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        //pass by a stretch of nodes\r
+        while (node != endsentinel && !toremove.Contains(node.item))\r
+        {\r
+          node = node.next;\r
+          index++;\r
+        }\r
+        viewHandler.skipEndpoints(removed, myoffset + index);\r
+        //Remove a stretch of nodes\r
+        Node localend = node.prev; //Latest node not to be removed\r
+        while (node != endsentinel && toremove.Remove(node.item))\r
+        {\r
+          if (mustFire)\r
+            raiseHandler.Remove(node.item);\r
+          removed++;\r
+          node = node.next;\r
+          index++;\r
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+        }\r
+        viewHandler.updateSentinels(myoffset + index, localend, node);\r
+        localend.next = node;\r
+        node.prev = localend;\r
+      }\r
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;\r
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+      size -= removed;\r
+      if (underlying != null)\r
+        underlying.size -= removed;\r
+#endif\r
+      raiseHandler.Raise();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    void RemoveAll(Fun<T, bool> predicate)\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+#if HASHINDEX\r
+      {\r
+        Node n = startsentinel.next;\r
+\r
+        while (n != endsentinel)\r
+        {\r
+          bool removeIt = predicate(n.item);\r
+          updatecheck();\r
+          if (removeIt)\r
+          {\r
+            dict.Remove(n.item);\r
+            remove(n, 119);\r
+            if (mustFire)\r
+              raiseHandler.Remove(n.item);\r
+          }\r
+\r
+          n = n.next;\r
+        }\r
+      }\r
+#else\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int index = 0, removed = 0, myoffset = Offset;\r
+      Node node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        //pass by a stretch of nodes\r
+        while (node != endsentinel && !predicate(node.item))\r
+        {\r
+          updatecheck();\r
+          node = node.next;\r
+          index++;\r
+        }\r
+        updatecheck();\r
+        viewHandler.skipEndpoints(removed, myoffset + index);\r
+        //Remove a stretch of nodes\r
+        Node localend = node.prev; //Latest node not to be removed\r
+        while (node != endsentinel && predicate(node.item))\r
+        {\r
+          updatecheck();\r
+          if (mustFire)\r
+            raiseHandler.Remove(node.item);\r
+          removed++;\r
+          node = node.next;\r
+          index++;\r
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+        }\r
+        updatecheck();\r
+        viewHandler.updateSentinels(myoffset + index, localend, node);\r
+        localend.next = node;\r
+        node.prev = localend;\r
+      }\r
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;\r
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+      size -= removed;\r
+      if (underlying != null)\r
+        underlying.size -= removed;\r
+#endif\r
+      raiseHandler.Raise();\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove all items from this collection.\r
+    /// </summary>\r
+    [Tested]\r
+    public virtual void Clear()\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      int oldsize = size;\r
+#if HASHINDEX\r
+      if (underlying == null)\r
+        dict.Clear();\r
+      else\r
+        foreach (T item in this)\r
+          dict.Remove(item);\r
+#endif\r
+      clear();\r
+      (underlying ?? this).raiseForRemoveInterval(Offset, oldsize);\r
+    }\r
+\r
+    void clear()\r
+    {\r
+      if (size == 0)\r
+        return;\r
+#if HASHINDEX\r
+      //TODO: mix with tag maintenance to only run through list once?\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      if (viewHandler.viewCount > 0)\r
+      {\r
+        int removed = 0;\r
+        Node n = startsentinel.next;\r
+        viewHandler.skipEndpoints(0, n);\r
+        while (n != endsentinel)\r
+        {\r
+          removed++;\r
+          n = n.next;\r
+          viewHandler.updateViewSizesAndCounts(removed, n);\r
+        }\r
+        viewHandler.updateSentinels(endsentinel, startsentinel, endsentinel);\r
+        if (underlying != null)\r
+          viewHandler.updateViewSizesAndCounts(removed, underlying.endsentinel);\r
+      }\r
+#else\r
+      fixViewsBeforeRemove(Offset, size, startsentinel.next, endsentinel.prev);\r
+#endif\r
+#if HASHINDEX\r
+      if (underlying != null)\r
+      {\r
+        Node n = startsentinel.next;\r
+\r
+        while (n != endsentinel)\r
+        {\r
+          n.next.prev = startsentinel;\r
+          startsentinel.next = n.next;\r
+          removefromtaggroup(n);\r
+          n = n.next;\r
+        }\r
+      }\r
+      else\r
+        taggroups = 0;\r
+#endif\r
+      endsentinel.prev = startsentinel;\r
+      startsentinel.next = endsentinel;\r
+      if (underlying != null)\r
+        underlying.size -= size;\r
+      size = 0;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove all items not in some other collection from this one, taking multiplicities into account.\r
+    /// <para>The asymptotic running time complexity of this method is <code>O(n+m+v*log(v))</code>, \r
+    /// where <code>n</code> is the size of this collection, <code>m</code> is the size of the\r
+    /// <code>items</code> collection and <code>v</code> is the number of views. \r
+    /// The method will temporarily allocate memory of size <code>O(m+v)</code>. The stated complexitiy \r
+    /// holds under the assumption that the itemequalityComparer of this list is well-behaved.\r
+    /// </para>\r
+    /// </summary>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to retain.</param>\r
+    [Tested]\r
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+#if HASHINDEX\r
+      /*if (underlying == null)\r
+      {\r
+        HashDictionary<T, Node> newdict = new HashDictionary<T, Node>(itemequalityComparer);\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
+        foreach (KeyValuePair<T, Node> pair in dict)\r
+        {\r
+          Node n = pair.Value;\r
+          fixViewsBeforeSingleRemove(n, 117);\r
+          Node p = n.prev, s = n.next; s.prev = p; p.next = s;\r
+          removefromtaggroup(n);\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> toremove = new HashSet<T>(itemequalityComparer);\r
+\r
+        foreach (T item in this)\r
+          toremove.Add(item);\r
+\r
+        foreach (T item in items)\r
+          toremove.Remove(item);\r
+\r
+        Node n = startsentinel.next;\r
+\r
+        while (n != endsentinel && toremove.Count > 0)\r
+        {\r
+          if (toremove.Contains(n.item))\r
+          {\r
+            dict.Remove(n.item);\r
+            remove(n, 119);\r
+            if (mustFire)\r
+              raiseHandler.Remove(n.item);\r
+          }\r
+\r
+          n = n.next;\r
+        }\r
+      }\r
+#else\r
+      HashBag<T> toretain = new HashBag<T>(itemequalityComparer);\r
+      toretain.AddAll(items);\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int index = 0, removed = 0, myoffset = Offset;\r
+      Node node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        //Skip a stretch of nodes\r
+        while (node != endsentinel && toretain.Remove(node.item))\r
+        {\r
+          node = node.next;\r
+          index++;\r
+        }\r
+        viewHandler.skipEndpoints(removed, myoffset + index);\r
+        //Remove a stretch of nodes\r
+        Node localend = node.prev; //Latest node not to be removed\r
+        while (node != endsentinel && !toretain.Contains(node.item))\r
+        {\r
+          if (mustFire)\r
+            raiseHandler.Remove(node.item);\r
+          removed++;\r
+          node = node.next;\r
+          index++;\r
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+        }\r
+        viewHandler.updateSentinels(myoffset + index, localend, node);\r
+        localend.next = node;\r
+        node.prev = localend;\r
+      }\r
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;\r
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+      size -= removed;\r
+      if (underlying != null)\r
+        underlying.size -= removed;\r
+#endif\r
+      raiseHandler.Raise();\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="predicate"></param>\r
+    void RetainAll(Fun<T,bool> predicate)\r
+    {\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+#if HASHINDEX\r
+      {\r
+        Node n = startsentinel.next;\r
+\r
+        while (n != endsentinel)\r
+        {\r
+          bool removeIt = !predicate(n.item);\r
+          updatecheck();\r
+          if (removeIt)\r
+          {\r
+            dict.Remove(n.item);\r
+            remove(n, 119);\r
+            if (mustFire)\r
+              raiseHandler.Remove(n.item);\r
+          }\r
+\r
+          n = n.next;\r
+        }\r
+      }\r
+#else\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int index = 0, removed = 0, myoffset = Offset;\r
+      Node node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        //Skip a stretch of nodes\r
+        while (node != endsentinel && predicate(node.item))\r
+        {\r
+          updatecheck();\r
+          node = node.next;\r
+          index++;\r
+        }\r
+        updatecheck();\r
+        viewHandler.skipEndpoints(removed, myoffset + index);\r
+        //Remove a stretch of nodes\r
+        Node localend = node.prev; //Latest node not to be removed\r
+        while (node != endsentinel && !predicate(node.item))\r
+        {\r
+          updatecheck();\r
+          if (mustFire)\r
+            raiseHandler.Remove(node.item);\r
+          removed++;\r
+          node = node.next;\r
+          index++;\r
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+        }\r
+        updatecheck();\r
+        viewHandler.updateSentinels(myoffset + index, localend, node);\r
+        localend.next = node;\r
+        node.prev = localend;\r
+      }\r
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;\r
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+      size -= removed;\r
+      if (underlying != null)\r
+        underlying.size -= removed;\r
+#endif\r
+      raiseHandler.Raise();\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains all the values in another collection\r
+    /// with respect to multiplicities.\r
+    /// </summary>\r
+    /// <param name="items">The </param>\r
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+    [Tested]\r
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      validitycheck();\r
+#if HASHINDEX\r
+      Node node;\r
+      foreach (T item in items)\r
+        if (!contains(item, out node))\r
+          return false;\r
+      return true;\r
+#else\r
+      HashBag<T> tocheck = new HashBag<T>(itemequalityComparer);\r
+      tocheck.AddAll(items);\r
+      if (tocheck.Count > size)\r
+        return false;\r
+      Node node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        tocheck.Remove(node.item);\r
+        node = node.next;\r
+      }\r
+      return tocheck.IsEmpty;\r
+#endif\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 IList<T> FindAll(Fun<T, bool> filter)\r
+    {\r
+      validitycheck();\r
+      int stamp = this.stamp;\r
+      LinkedList<T> retval = new LinkedList<T>();\r
+      Node cursor = startsentinel.next;\r
+      Node mcursor = retval.startsentinel;\r
+#if HASHINDEX\r
+      double tagdelta = int.MaxValue / (size + 1.0);\r
+      int count = 1;\r
+      TagGroup taggroup = new TagGroup();\r
+      retval.taggroups = 1;\r
+#endif\r
+      while (cursor != endsentinel)\r
+      {\r
+        bool found = filter(cursor.item);\r
+        modifycheck(stamp);\r
+        if (found)\r
+        {\r
+          mcursor.next = new Node(cursor.item, mcursor, null);\r
+          mcursor = mcursor.next;\r
+          retval.size++;\r
+#if HASHINDEX\r
+          retval.dict.Add(cursor.item, mcursor); \r
+          mcursor.taggroup = taggroup;\r
+          mcursor.tag = (int)(tagdelta * count++);\r
+#endif\r
+        }\r
+        cursor = cursor.next;\r
+      }\r
+#if HASHINDEX\r
+      taggroup.count = retval.size;\r
+#endif\r
+      retval.endsentinel.prev = mcursor;\r
+      mcursor.next = retval.endsentinel;\r
+      return retval;\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
+#if HASHINDEX\r
+      return Contains(item) ? 1 : 0;\r
+#else\r
+      validitycheck();\r
+      int retval = 0;\r
+      Node node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        if (itemequalityComparer.Equals(node.item, item))\r
+          retval++;\r
+        node = node.next;\r
+      }\r
+      return retval;\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<T> UniqueItems()\r
+    {\r
+#if HASHINDEX\r
+      return this;\r
+#else\r
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);\r
+      hashbag.AddAll(this);\r
+      return hashbag.UniqueItems();\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()\r
+    {\r
+#if HASHINDEX\r
+      return new MultiplicityOne<T>(this);\r
+#else\r
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);\r
+      hashbag.AddAll(this);\r
+      return hashbag.ItemMultiplicities();\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// Remove all items equivalent to a given value.\r
+    /// <para>The asymptotic complexity of this method is <code>O(n+v*log(v))</code>, \r
+    /// where <code>n</code> is the size of the collection and <code>v</code> \r
+    /// is the number of views.\r
+    /// </para>\r
+    /// </summary>\r
+    /// <param name="item">The value to remove.</param>\r
+    [Tested]\r
+    public virtual void RemoveAllCopies(T item)\r
+    {\r
+#if HASHINDEX\r
+      Remove(item);\r
+#else\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);\r
+      bool mustFire = raiseHandler.MustFire;\r
+      ViewHandler viewHandler = new ViewHandler(this);\r
+      int index = 0, removed = 0, myoffset = Offset;\r
+      //\r
+      Node node = startsentinel.next;\r
+      while (node != endsentinel)\r
+      {\r
+        //pass by a stretch of nodes\r
+        while (node != endsentinel && !itemequalityComparer.Equals(node.item, item))\r
+        {\r
+          node = node.next;\r
+          index++;\r
+        }\r
+        viewHandler.skipEndpoints(removed, myoffset + index);\r
+        //Remove a stretch of nodes\r
+        Node localend = node.prev; //Latest node not to be removed\r
+        while (node != endsentinel && itemequalityComparer.Equals(node.item, item))\r
+        {\r
+          if (mustFire)\r
+            raiseHandler.Remove(node.item);\r
+          removed++;\r
+          node = node.next;\r
+          index++;\r
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+        }\r
+        viewHandler.updateSentinels(myoffset + index, localend, node);\r
+        localend.next = node;\r
+        node.prev = localend;\r
+      }\r
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;\r
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);\r
+      size -= removed;\r
+      if (underlying != null)\r
+        underlying.size -= removed;\r
+      raiseHandler.Raise();\r
+#endif\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region ICollectionValue<T> Members\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>The number of items in this collection</value>\r
+    [Tested]\r
+    public override int Count { [Tested]get { validitycheck(); return size; } }\r
+\r
+    /// <summary>\r
+    /// Choose some item of this collection. \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override T Choose() { return First; }\r
+\r
+    /// <summary>\r
+    /// Create an enumerable, enumerating the items of this collection that satisfies \r
+    /// a certain condition.\r
+    /// </summary>\r
+    /// <param name="filter">The T->bool filter delegate defining the condition</param>\r
+    /// <returns>The filtered enumerable</returns>\r
+    public override SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { validitycheck(); return base.Filter(filter); }\r
+\r
+    #endregion\r
+\r
+    #region IEnumerable<T> Members\r
+    /// <summary>\r
+    /// Create an enumerator for the collection\r
+    /// </summary>\r
+    /// <returns>The enumerator</returns>\r
+    [Tested]\r
+    public override SCG.IEnumerator<T> GetEnumerator()\r
+    {\r
+      validitycheck();\r
+      Node cursor = startsentinel.next;\r
+      int enumeratorstamp = underlying != null ? underlying.stamp : this.stamp;\r
+\r
+      while (cursor != endsentinel)\r
+      {\r
+        modifycheck(enumeratorstamp);\r
+        yield return cursor.item;\r
+        cursor = cursor.next;\r
+      }\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IExtensible<T> Members\r
+    /// <summary>\r
+    /// Add an item to this collection if possible. \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
+#if HASHINDEX\r
+      Node node = new Node(item);\r
+      if (!dict.FindOrAdd(item, ref node))\r
+      {\r
+        insertNode(true, endsentinel, node);\r
+        (underlying ?? this).raiseForAdd(item);\r
+        return true;\r
+      }\r
+      return false;\r
+#else\r
+      insert(size, endsentinel, item);\r
+      (underlying ?? this).raiseForAdd(item);\r
+      return true;\r
+#endif\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value>True since this collection has bag semantics.</value>\r
+    [Tested]\r
+    public virtual bool AllowsDuplicates\r
+    {\r
+      [Tested]\r
+      get\r
+      {\r
+#if HASHINDEX\r
+        return false;\r
+#else\r
+        return true;\r
+#endif\r
+      }\r
+    }\r
+\r
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting\r
+    {\r
+      get\r
+      {\r
+#if HASHINDEX\r
+        return true;\r
+#else\r
+        return false;\r
+#endif\r
+      }\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
+    [Tested]\r
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+#if HASHINDEX\r
+      updatecheck();\r
+      int added = 0;\r
+      Node pred = endsentinel.prev;\r
+      foreach (U item in items)\r
+      {\r
+        Node node = new Node(item);\r
+        if (!dict.FindOrAdd(item, ref node))\r
+        {\r
+          insertNode(false, endsentinel, node);\r
+          added++;\r
+        }\r
+      }\r
+      if (added > 0)\r
+      {\r
+        fixViewsAfterInsert(endsentinel, pred, added, 0);\r
+        raiseForInsertAll(pred, size - added, added, false);\r
+      }\r
+#else\r
+      insertAll(size, items, false);\r
+#endif\r
+    }\r
+\r
+    #endregion\r
+\r
+#if HASHINDEX\r
+#else\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
+      InsertLast(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 virtual void Enqueue(T item)\r
+    {\r
+      InsertLast(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 virtual T Dequeue()\r
+    {\r
+      return RemoveFirst();\r
+    }\r
+    #endregion\r
+#endif\r
+\r
+    #region Diagnostic\r
+\r
+    private bool checkViews()\r
+    {\r
+      if (underlying != null)\r
+        throw new InternalException(System.Reflection.MethodInfo.GetCurrentMethod() + " called on a view");\r
+      if (views == null)\r
+        return true;\r
+      bool retval = true;\r
+\r
+      Node[] nodes = new Node[size + 2];\r
+      int i = 0;\r
+      Node n = startsentinel;\r
+      while (n != null)\r
+      {\r
+        nodes[i++] = n;\r
+        n = n.next;\r
+      }\r
+      //Console.WriteLine("###");\r
+      foreach (LinkedList<T> view in views)\r
+      {\r
+        if (!view.isValid)\r
+        {\r
+          Console.WriteLine("Invalid view(hash {0}, offset {1}, size {2})",\r
+            view.GetHashCode(), view.offset, view.size);\r
+          retval = false;\r
+          continue;\r
+        }\r
+        if (view.Offset > size || view.Offset < 0)\r
+        {\r
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), Offset > underlying.size ({2})",\r
+            view.GetHashCode(), view.offset, view.size, size);\r
+          retval = false;\r
+        }\r
+        else if (view.startsentinel != nodes[view.Offset])\r
+        {\r
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), startsentinel {3} should be {4}",\r
+            view.GetHashCode(), view.offset, view.size,\r
+            view.startsentinel + " " + view.startsentinel.GetHashCode(),\r
+            nodes[view.Offset] + " " + nodes[view.Offset].GetHashCode());\r
+          retval = false;\r
+        }\r
+        if (view.Offset + view.size > size || view.Offset + view.size < 0)\r
+        {\r
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), end index > underlying.size ({3})",\r
+            view.GetHashCode(), view.offset, view.size, size);\r
+          retval = false;\r
+        }\r
+        else if (view.endsentinel != nodes[view.Offset + view.size + 1])\r
+        {\r
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), endsentinel {3} should be {4}",\r
+            view.GetHashCode(), view.offset, view.size,\r
+            view.endsentinel + " " + view.endsentinel.GetHashCode(),\r
+            nodes[view.Offset + view.size + 1] + " " + nodes[view.Offset + view.size + 1].GetHashCode());\r
+          retval = false;\r
+        }\r
+        if (view.views != views)\r
+        {\r
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong views list {3} <> {4}",\r
+            view.GetHashCode(), view.offset, view.size, view.views.GetHashCode(), views.GetHashCode());\r
+          retval = false;\r
+        }\r
+        if (view.underlying != this)\r
+        {\r
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong underlying {3} <> this {4}",\r
+            view.GetHashCode(), view.offset, view.size, view.underlying.GetHashCode(), GetHashCode());\r
+          retval = false;\r
+        }\r
+        if (view.stamp != stamp)\r
+        {\r
+          //Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong stamp view:{2} underlying: {3}", view.GetHashCode(),view.offset, view.size, view.stamp, stamp);\r
+          //retval = false;\r
+        }\r
+      }\r
+      return retval;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check the sanity of this list\r
+    /// </summary>\r
+    /// <returns>true if sane</returns>\r
+    [Tested]\r
+    public virtual bool Check()\r
+    {\r
+      bool retval = true;\r
+\r
+      /*if (underlying != null && underlying.stamp != stamp)\r
+      {\r
+        Console.WriteLine("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp);\r
+        retval = false;\r
+      }*/\r
+\r
+      if (underlying != null)\r
+      {\r
+        //TODO: check that this view is included in viewsEndpoints tree\r
+        return underlying.Check();\r
+      }\r
+\r
+      if (startsentinel == null)\r
+      {\r
+        Console.WriteLine("startsentinel == null");\r
+        retval = false;\r
+      }\r
+\r
+      if (endsentinel == null)\r
+      {\r
+        Console.WriteLine("endsentinel == null");\r
+        retval = false;\r
+      }\r
+\r
+      if (size == 0)\r
+      {\r
+        if (startsentinel != null && startsentinel.next != endsentinel)\r
+        {\r
+          Console.WriteLine("size == 0 but startsentinel.next != endsentinel");\r
+          retval = false;\r
+        }\r
+\r
+        if (endsentinel != null && endsentinel.prev != startsentinel)\r
+        {\r
+          Console.WriteLine("size == 0 but endsentinel.prev != startsentinel");\r
+          retval = false;\r
+        }\r
+      }\r
+\r
+      if (startsentinel == null)\r
+      {\r
+        Console.WriteLine("NULL startsentinel");\r
+        return retval;\r
+      }\r
+\r
+      int count = 0;\r
+      Node node = startsentinel.next, prev = startsentinel;\r
+#if HASHINDEX\r
+      int taggroupsize = 0, oldtaggroupsize = losize + 1, seentaggroups = 0;\r
+      TagGroup oldtg = null;\r
+\r
+      if (underlying == null)\r
+      {\r
+        TagGroup tg = startsentinel.taggroup;\r
+\r
+        if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MinValue)\r
+        {\r
+          Console.WriteLine("Bad startsentinel tag group: {0}", tg);\r
+          retval = false;\r
+        }\r
+\r
+        tg = endsentinel.taggroup;\r
+        if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MaxValue)\r
+        {\r
+          Console.WriteLine("Bad endsentinel tag group: {0}", tg);\r
+          retval = false;\r
+        }\r
+      }\r
+#endif\r
+      while (node != endsentinel)\r
+      {\r
+        count++;\r
+        if (node.prev != prev)\r
+        {\r
+          Console.WriteLine("Bad backpointer at node {0}", count);\r
+          retval = false;\r
+        }\r
+#if HASHINDEX\r
+        if (underlying == null)\r
+        {\r
+          if (!node.prev.precedes(node))\r
+          {\r
+            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);\r
+            retval = false;\r
+          }\r
+\r
+          if (node.taggroup != oldtg)\r
+          {\r
+            if (oldtg != null)\r
+            {\r
+              if (oldtg.count != taggroupsize)\r
+              {\r
+                Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);\r
+                retval = false;\r
+              }\r
+\r
+              if (oldtaggroupsize <= losize && taggroupsize <= losize)\r
+              {\r
+                Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);\r
+                retval = false;\r
+              }\r
+\r
+              oldtaggroupsize = taggroupsize;\r
+            }\r
+\r
+            seentaggroups++;\r
+            oldtg = node.taggroup;\r
+            taggroupsize = 1;\r
+          }\r
+          else\r
+          {\r
+            taggroupsize++;\r
+          }\r
+        }\r
+\r
+#endif\r
+        prev = node;\r
+        node = node.next;\r
+        if (node == null)\r
+        {\r
+          Console.WriteLine("Null next pointer at node {0}", count);\r
+          return false;\r
+        }\r
+      }\r
+\r
+#if HASHINDEX\r
+      if (underlying == null && size == 0 && taggroups != 0)\r
+      {\r
+        Console.WriteLine("Bad taggroups for empty list: size={0}   taggroups={1}", size, taggroups);\r
+        retval = false;\r
+      }\r
+      if (underlying == null && size > 0)\r
+      {\r
+        oldtg = node.prev.taggroup;\r
+        if (oldtg != null)\r
+        {\r
+          if (oldtg.count != taggroupsize)\r
+          {\r
+            Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);\r
+            retval = false;\r
+          }\r
+\r
+          if (oldtaggroupsize <= losize && taggroupsize <= losize)\r
+          {\r
+            Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);\r
+            retval = false;\r
+          }\r
+        }\r
+\r
+        if (seentaggroups != taggroups)\r
+        {\r
+          Console.WriteLine("seentaggroups ({0}) != taggroups ({1}) (at size {2})", seentaggroups, taggroups, size);\r
+          retval = false;\r
+        }\r
+      }\r
+#endif\r
+      if (count != size)\r
+      {\r
+        Console.WriteLine("size={0} but enumeration gives {1} nodes ", size, count);\r
+        retval = false;\r
+      }\r
+\r
+      retval = checkViews() && retval;\r
+\r
+#if HASHINDEX\r
+      if (!retval)\r
+        return false;\r
+      if (underlying == 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
+        Node n = startsentinel.next, n2;\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
+          n = n.next;\r
+        }\r
+      }\r
+#endif\r
+      return retval;\r
+    }\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this LinkedList.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      LinkedList<T> clone = new LinkedList<T>(itemequalityComparer);\r
+      clone.AddAll(this);\r
+      return clone;\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+}\r
diff --git a/mcs/class/Mono.C5/C5/trees/.cvsignore b/mcs/class/Mono.C5/C5/trees/.cvsignore
new file mode 100644 (file)
index 0000000..9577892
--- /dev/null
@@ -0,0 +1 @@
+RedBlackTreeBag.cs
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/trees/RedBlackTreeDictionary.cs b/mcs/class/Mono.C5/C5/trees/RedBlackTreeDictionary.cs
new file mode 100644 (file)
index 0000000..4e1bc61
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 SCG = 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> : SortedDictionaryBase<K, V>, IDictionary<K, V>, ISortedDictionary<K, V>\r
+  {\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(Comparer<K>.Default, EqualityComparer<K>.Default) { }\r
+\r
+    /// <summary>\r
+    /// Create a red-black tree dictionary using an external comparer for keys.\r
+    /// </summary>\r
+    /// <param name="comparer">The external comparer</param>\r
+    public TreeDictionary(SCG.IComparer<K> comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer<K>(comparer)) { }\r
+\r
+    TreeDictionary(SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> equalityComparer) : base(comparer,equalityComparer)\r
+    {\r
+      pairs = sortedpairs = new TreeSet<KeyValuePair<K, V>>(new KeyValuePairComparer<K, V>(comparer));\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 SCG.IEnumerable<KeyValuePair<K, V>> Snapshot()\r
+    {\r
+      TreeDictionary<K, V> res = (TreeDictionary<K, V>)MemberwiseClone();\r
+\r
+      res.pairs = (TreeSet<KeyValuePair<K, V>>)((TreeSet<KeyValuePair<K, V>>)sortedpairs).Snapshot();\r
+      return res;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public override object Clone()\r
+    {\r
+      TreeDictionary<K, V> clone = new TreeDictionary<K, V>(Comparer, EqualityComparer);\r
+      clone.sortedpairs.AddSorted(sortedpairs);\r
+      return clone;\r
+    }\r
+\r
+  }\r
+}
\ No newline at end of file
diff --git a/mcs/class/Mono.C5/C5/trees/RedBlackTreeSet.cs b/mcs/class/Mono.C5/C5/trees/RedBlackTreeSet.cs
new file mode 100644 (file)
index 0000000..ac86cc6
--- /dev/null
@@ -0,0 +1,4490 @@
+/*\r
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft\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 BAGnot\r
+#define NCP\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 SCG = System.Collections.Generic;\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
+  /// <i>\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.</i>\r
+  ///\r
+  /// <i>TODO: describe performance here</i>\r
+  /// <i>TODO: discuss persistence and its useful usage modes. Warn about the space\r
+  /// leak possible with other usage modes.</i>\r
+  /// </summary>\r
+#endif\r
+  [Serializable]\r
+  public class TreeSet<T> : SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>\r
+  {\r
+    #region Fields\r
+\r
+    SCG.IComparer<T> comparer;\r
+\r
+    Node root;\r
+\r
+    //TODO: wonder if we should remove that\r
+    int blackdepth = 0;\r
+\r
+    //We double these stacks for the iterative add and remove on demand\r
+    //TODO: refactor dirs[] into bool fields on Node (?)\r
+    private int[] dirs = new int[2];\r
+\r
+    private Node[] path = new Node[2];\r
+#if NCP\r
+    //TODO: refactor into separate class\r
+    bool isSnapShot = false;\r
+\r
+    int generation;\r
+\r
+    bool isValid = true;\r
+\r
+    SnapRef snapList;\r
+#endif\r
+    #endregion\r
+\r
+    #region Events\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }\r
+\r
+    #endregion\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
+    [Serializable]\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 NCP\r
+      //TODO: move everything into (separate) Extra\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
+          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 equalityComparer.\r
+    /// We assume that if <code>T</code> is comparable, its default equalityComparer \r
+    /// will be compatible with the comparer.\r
+    /// </summary>\r
+    /// <exception cref="NotComparableException">If <code>T</code> is not comparable.\r
+    /// </exception>\r
+    public TreeSet() : this(Comparer<T>.Default, EqualityComparer<T>.Default) { }\r
+\r
+\r
+    /// <summary>\r
+    /// Create a red-black tree collection with an external comparer. \r
+    /// <para>The itemequalityComparer will be a compatible \r
+    /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the \r
+    /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)\r
+    /// is unlikely to be compatible with the external comparer. This makes the\r
+    /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags\r
+    /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)\r
+    /// </para>\r
+    /// </summary>\r
+    /// <param name="comparer">The external comparer</param>\r
+    public TreeSet(SCG.IComparer<T> comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }\r
+\r
+    /// <summary>\r
+    /// Create a red-black tree collection with an external comparer and an external\r
+    /// item equalityComparer, assumed consistent.\r
+    /// </summary>\r
+    /// <param name="comparer">The external comparer</param>\r
+    /// <param name="equalityComparer">The external item equalityComparer</param>\r
+    public TreeSet(SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> equalityComparer)\r
+      : base(equalityComparer)\r
+    {\r
+      if (comparer == null)\r
+        throw new NullReferenceException("Item comparer cannot be null");\r
+      this.comparer = comparer;\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
+    internal class Enumerator : SCG.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="CollectionModifiedException"/> 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
+\r
+      /// <summary>\r
+      /// Finalizer for enumerator\r
+      /// </summary>\r
+      ~Enumerator()\r
+      {\r
+        Dispose(false);\r
+      }\r
+      #endregion\r
+\r
+\r
+      #region IEnumerator Members\r
+\r
+      object System.Collections.IEnumerator.Current\r
+      {\r
+        get { return Current; }\r
+      }\r
+\r
+      bool System.Collections.IEnumerator.MoveNext()\r
+      {\r
+        return MoveNext();\r
+      }\r
+\r
+      void System.Collections.IEnumerator.Reset()\r
+      {\r
+        throw new Exception("The method or operation is not implemented.");\r
+      }\r
+\r
+      #endregion\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
+    internal class SnapEnumerator : SCG.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 SCG.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="CollectionModifiedException"/> 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
+      #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
+      #region IEnumerator Members\r
+\r
+      object System.Collections.IEnumerator.Current\r
+      {\r
+        get { return Current; }\r
+      }\r
+\r
+      bool System.Collections.IEnumerator.MoveNext()\r
+      {\r
+        return MoveNext();\r
+      }\r
+\r
+      void System.Collections.IEnumerator.Reset()\r
+      {\r
+        throw new Exception("The method or operation is not implemented.");\r
+      }\r
+\r
+      #endregion\r
+    }\r
+#endif\r
+    #endregion\r
+\r
+    #region IEnumerable<T> Members\r
+\r
+    private SCG.IEnumerator<T> getEnumerator(Node node, int origstamp)\r
+    {\r
+      if (node == null)\r
+        yield break;\r
+\r
+      if (node.left != null)\r
+      {\r
+        SCG.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
+        SCG.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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException">If tree is empty</exception>\r
+    /// <returns></returns>\r
+    [Tested]\r
+    public override T Choose()\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+      return root.item;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Create an enumerator for this tree\r
+    /// </summary>\r
+    /// <returns>The enumerator</returns>\r
+    [Tested]\r
+    public override SCG.IEnumerator<T> GetEnumerator()\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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
+        root.item = item;\r
+#if NCP\r
+        root.generation = generation;\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
+#if BAG\r
+          wasfound = true;\r
+          bool nodeWasUpdated = true;\r
+#if NCP\r
+          Node.CopyNode(ref cursor, maxsnapid, generation);\r
+#endif\r
+          if (update)\r
+            cursor.item = item;\r
+          else\r
+          {\r
+            cursor.items++;\r
+            cursor.size++;\r
+          }\r
+#else\r
+          bool nodeWasUpdated = update;\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 (nodeWasUpdated)\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
+              if (!update)\r
+                cursor.size++;\r
+#endif\r
+            }\r
+\r
+            path[level] = null;\r
+          }\r
+#if BAG\r
+          return !update;\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
+          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
+          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
+          }\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 (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
+            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
+      }\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+\r
+      //Note: blackdepth of the tree is set inside addIterative\r
+      T jtem = default(T);\r
+      if (!add(item, ref jtem))\r
+        return false;\r
+      if (ActiveEvents != 0)\r
+        raiseForAdd(jtem);\r
+      return true;\r
+    }\r
+\r
+    private bool add(T item, ref T j)\r
+    {\r
+      bool wasFound;\r
+\r
+      if (addIterative(item, ref j, false, out wasFound))\r
+      {\r
+        size++;\r
+        if (!wasFound)\r
+          j = item;\r
+        return true;\r
+      }\r
+      else\r
+        return false;\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
+    [Tested]\r
+    public void AddAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+\r
+      int c = 0;\r
+      T j = default(T);\r
+      bool tmp;\r
+\r
+      bool raiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;\r
+      CircularQueue<T> wasAdded = raiseAdded ? new CircularQueue<T>() : null;\r
+\r
+      foreach (T i in items)\r
+        if (addIterative(i, ref j, false, out tmp))\r
+        {\r
+          c++;\r
+          if (raiseAdded)\r
+            wasAdded.Enqueue(tmp ? j : i);\r
+        }\r
+      if (c == 0)\r
+        return;\r
+\r
+      size += c;\r
+      //TODO: implement a RaiseForAddAll() method\r
+      if (raiseAdded)\r
+        foreach (T item in wasAdded)\r
+          raiseItemsAdded(item, 1);\r
+      if (((ActiveEvents & EventTypeEnum.Changed) != 0))\r
+        raiseCollectionChanged();\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
+    /// <typeparam name="U"></typeparam>\r
+    [Tested]\r
+    public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      if (size > 0)\r
+        AddAll(items);\r
+      else\r
+      {\r
+        if (!isValid)\r
+          throw new ViewDisposedException("Snapshot has been disposed");\r
+        updatecheck();\r
+        addSorted(items, true, 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
+        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<U>(SCG.IEnumerable<U> items, bool safe, bool raise) where U : T\r
+    {\r
+      SCG.IEnumerator<U> e = items.GetEnumerator(); ;\r
+      if (size > 0)\r
+        throw new InternalException("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
+\r
+      if (raise)\r
+      {\r
+        if ((ActiveEvents & EventTypeEnum.Added) != 0)\r
+        {\r
+          CircularQueue<T> wasAdded = new CircularQueue<T>();\r
+          foreach (T item in this)\r
+            wasAdded.Enqueue(item);\r
+          foreach (T item in wasAdded)\r
+            raiseItemsAdded(item, 1);\r
+        }\r
+        if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+          raiseCollectionChanged();\r
+      }\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
+    /// <summary>\r
+    /// By convention this is true for any collection with set semantics.\r
+    /// </summary>\r
+    /// <value>True if only one representative of a group of equal items \r
+    /// is kept in the collection together with the total count.</value>\r
+    public virtual bool DuplicatesByCounting { get { return true; } }\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
+    /// <summary>\r
+    /// Check if this collection contains (an item equivalent to according to the\r
+    /// itemequalityComparer) 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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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
+    /// itemequalityComparer 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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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 (ActiveEvents != 0 && !wasfound)\r
+          raiseForAdd(item);\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
+    /// itemequalityComparer 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
+      T olditem = item;\r
+      return Update(item, out olditem);\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer to a particular value. If so, update the item in the collection \r
+    /// 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"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public bool Update(T item, out T olditem)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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
+          olditem = cursor.item;\r
+#if BAG\r
+          int items = cursor.items;\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
+#if BAG\r
+          if (ActiveEvents != 0)\r
+            raiseForUpdate(item, olditem, items);\r
+#else\r
+          if (ActiveEvents != 0)\r
+            raiseForUpdate(item, olditem);\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
+      olditem = default(T);\r
+      return false;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains an item equivalent according to the\r
+    /// itemequalityComparer to a particular value. If so, update the item in the collection \r
+    /// with a binary copy of the supplied value; else add the value to the collection. \r
+    ///\r
+    /// <i>NOTE: the bag implementation is currently wrong! ?????</i>\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
+    { T olditem; return UpdateOrAdd(item, out olditem); }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item"></param>\r
+    /// <param name="olditem"></param>\r
+    /// <returns></returns>\r
+    public bool UpdateOrAdd(T item, out T olditem)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+      bool wasfound;\r
+      olditem = default(T);\r
+\r
+\r
+      //Note: blackdepth of the tree is set inside addIterative\r
+      if (addIterative(item, ref olditem, true, out wasfound))\r
+      {\r
+        size++;\r
+        if (ActiveEvents != 0)\r
+          raiseForAdd(wasfound ? olditem : item);\r
+        return wasfound;\r
+      }\r
+      else\r
+      {\r
+#warning for bag implementation: count is wrong\r
+        if (ActiveEvents != 0)\r
+          raiseForUpdate(item, olditem, 1);\r
+        return true;\r
+      }\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+      if (root == null)\r
+        return false;\r
+\r
+      int junk;\r
+      bool retval = removeIterative(ref item, false, out junk);\r
+      if (ActiveEvents != 0 && retval)\r
+        raiseForRemove(item);\r
+      return retval;\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.</param>\r
+    /// <param name="removeditem">The removed value.</param>\r
+    /// <returns>True if the item was found (and removed).</returns>\r
+    [Tested]\r
+    public bool Remove(T item, out T removeditem)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+      removeditem = item;\r
+      if (root == null)\r
+        return false;\r
+\r
+      int junk;\r
+      bool retval = removeIterative(ref removeditem, false, out junk);\r
+      if (ActiveEvents != 0 && retval)\r
+        raiseForRemove(item);\r
+      return retval;\r
+    }\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <param name="item">input: item to remove; output: item actually removed</param>\r
+    /// <param name="all">If true, remove all copies</param>\r
+    /// <param name="wasRemoved"></param>\r
+    /// <returns></returns>\r
+    private bool removeIterative(ref T item, bool all, out int wasRemoved)\r
+    {\r
+      wasRemoved = 0;\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
+            wasRemoved = 1;\r
+            return true;\r
+          }\r
+          wasRemoved = cursor.items;\r
+#else\r
+          wasRemoved = 1;\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 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
+        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
+\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 (level == 0)\r
+        {\r
+          cursor.red = false;\r
+          blackdepth--;\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
+        }\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 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
+          }\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 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
+          }\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 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
+          }\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 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
+        }\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 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
+        }\r
+        else\r
+        {//Case 1a can't happen\r
+          throw new InternalException("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
+        }\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
+      }\r
+\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+      if (size == 0)\r
+        return;\r
+      int oldsize = size;\r
+      clear();\r
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)\r
+        raiseCollectionCleared(true, oldsize);\r
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\r
+    }\r
+\r
+\r
+    private void clear()\r
+    {\r
+      size = 0;\r
+      root = null;\r
+      blackdepth = 0;\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to remove.</param>\r
+    [Tested]\r
+    public void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+\r
+      T jtem;\r
+\r
+      bool mustRaise = (ActiveEvents & (EventTypeEnum.Removed | EventTypeEnum.Changed)) != 0;\r
+      RaiseForRemoveAllHandler raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null;\r
+\r
+      foreach (T item in items)\r
+      {\r
+        if (root == null)\r
+          break;\r
+\r
+        jtem = item;\r
+        int junk;\r
+        if (removeIterative(ref jtem, false, out junk) && mustRaise)\r
+          raiseHandler.Remove(jtem);\r
+      }\r
+      if (mustRaise)\r
+        raiseHandler.Raise();\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
+    /// <typeparam name="U"></typeparam>\r
+    /// <param name="items">The items to retain.</param>\r
+    [Tested]\r
+    public void RetainAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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
+#warning how does this work together with persistence?\r
+      TreeSet<T> t = (TreeSet<T>)MemberwiseClone();\r
+\r
+      T jtem = default(T);\r
+      t.clear();\r
+      foreach (T item in items)\r
+        if (ContainsCount(item) > t.ContainsCount(item))\r
+        {\r
+          t.add(item, ref jtem);\r
+        }\r
+      if (size == t.size)\r
+        return;\r
+\r
+#warning improve (mainly for bag) by usig a Node iterator instead of ItemMultiplicities()\r
+      CircularQueue<KeyValuePair<T, int>> wasRemoved = null;\r
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)\r
+      {\r
+        wasRemoved = new CircularQueue<KeyValuePair<T, int>>();\r
+        SCG.IEnumerator<KeyValuePair<T, int>> ie = ItemMultiplicities().GetEnumerator();\r
+        foreach (KeyValuePair<T, int> p in t.ItemMultiplicities())\r
+        {\r
+          //We know p.Key is in this!\r
+          while (ie.MoveNext())\r
+          {\r
+            if (comparer.Compare(ie.Current.Key, p.Key) == 0)\r
+            {\r
+#if BAG\r
+              int removed = ie.Current.Value - p.Value;\r
+              if (removed > 0)\r
+                wasRemoved.Enqueue(new KeyValuePair<T,int>(p.Key, removed));\r
+#endif\r
+              break;\r
+            }\r
+            else\r
+              wasRemoved.Enqueue(ie.Current);\r
+          }\r
+        }\r
+        while (ie.MoveNext())\r
+          wasRemoved.Enqueue(ie.Current);\r
+      }\r
+\r
+      root = t.root;\r
+      size = t.size;\r
+      blackdepth = t.blackdepth;\r
+      if (wasRemoved != null)\r
+        foreach (KeyValuePair<T, int> p in wasRemoved)\r
+          raiseItemsRemoved(p.Key, p.Value);\r
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\r
+    }\r
+\r
+    /// <summary>\r
+    /// Check if this collection contains all the values in another collection.\r
+    /// If this collection has bag semantics (<code>AllowsDuplicates==true</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
+    /// <typeparam name="U"></typeparam>\r
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>\r
+    [Tested]\r
+    public bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T\r
+    {\r
+      //TODO: fix bag implementation\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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(Fun<T, bool> filter)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      TreeSet<T> res = new TreeSet<T>(comparer);\r
+      SCG.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>(Fun<T, V> mapper, SCG.IComparer<V> c)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      TreeSet<V> res = new TreeSet<V>(c);\r
+\r
+      if (size == 0)\r
+        return res;\r
+\r
+      SCG.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 (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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 not AllowsDuplicates we just do\r
+      return Contains(item) ? 1 : 0;\r
+#endif\r
+    }\r
+\r
+#if BAG\r
+    //TODO: make work with snapshots\r
+    class Multiplicities : CollectionValueBase<KeyValuePair<T, int>>, ICollectionValue<KeyValuePair<T, int>>\r
+    {\r
+      TreeBag<T> treebag;\r
+      int origstamp;\r
+      internal Multiplicities(TreeBag<T> treebag) { this.treebag = treebag; this.origstamp = treebag.stamp; }\r
+      public override KeyValuePair<T, int> Choose() { return new KeyValuePair<T, int>(treebag.root.item, treebag.root.items); }\r
+\r
+      public override SCG.IEnumerator<KeyValuePair<T, int>> GetEnumerator()\r
+      {\r
+        return getEnumerator(treebag.root, origstamp); //TODO: NBNBNB\r
+      }\r
+\r
+      private SCG.IEnumerator<KeyValuePair<T, int>> getEnumerator(Node node, int origstamp)\r
+      {\r
+        if (node == null)\r
+          yield break;\r
+\r
+        if (node.left != null)\r
+        {\r
+          SCG.IEnumerator<KeyValuePair<T, int>> child = getEnumerator(node.left, origstamp);\r
+\r
+          while (child.MoveNext())\r
+          {\r
+            treebag.modifycheck(origstamp);\r
+            yield return child.Current;\r
+          }\r
+        }\r
+        yield return new KeyValuePair<T, int>(node.item, node.items);\r
+        if (node.right != null)\r
+        {\r
+          SCG.IEnumerator<KeyValuePair<T, int>> child = getEnumerator(node.right, origstamp);\r
+\r
+          while (child.MoveNext())\r
+          {\r
+            treebag.modifycheck(origstamp);\r
+            yield return child.Current;\r
+          }\r
+        }\r
+      }\r
+\r
+      public override bool IsEmpty { get { return treebag.IsEmpty; } }\r
+      public override int Count { get { int i = 0; foreach (KeyValuePair<T, int> p in this) i++; return i; } } //TODO: make better\r
+      public override Speed CountSpeed { get { return Speed.Linear; } } //TODO: make better\r
+    }\r
+#endif\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<T> UniqueItems()\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+#if BAG\r
+      return new DropMultiplicity<T>(ItemMultiplicities());\r
+#else\r
+      return this;\r
+#endif\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+#if BAG\r
+      return new Multiplicities(this);\r
+#else\r
+      return new MultiplicityOne<T>(this);\r
+#endif\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+      int removed;\r
+      if (removeIterative(ref item, true, out removed) && ActiveEvents != 0)\r
+      {\r
+        raiseForRemove(item, removed);\r
+      }\r
+#else\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
+    /// <summary>\r
+    /// \r
+    /// </summary>\r
+    /// <value></value>\r
+    public virtual Speed IndexingSpeed { get { return Speed.Log; } }\r
+\r
+\r
+    //TODO: return -upper instead of -1 in case of not found\r
+    /// <summary>\r
+    /// Searches for an item in this indexed collection going forwards from the start.\r
+    /// </summary>\r
+    /// <param name="item">Item to search for.</param>\r
+    /// <returns>Index of first occurrence from start of the item\r
+    /// if found, else the two-complement \r
+    /// (always negative) of the index at which the item would be put if it was added.</returns>\r
+    [Tested]\r
+    public int IndexOf(T item)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      int upper;\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 = ~ind;\r
+      return ~ind;\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// Searches for an item in the tree going backwords from the end.\r
+    /// </summary>\r
+    /// <param name="item">Item to search for.</param>\r
+    /// <returns>Index of last occurrence from the end of item if found, \r
+    /// else the two-complement (always negative) of the index at which \r
+    /// the item would be put if it was added.</returns>\r
+    [Tested]\r
+    public int LastIndexOf(T item)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+#if BAG\r
+      int res;\r
+      indexOf(item, out res);\r
+      return res;\r
+#else\r
+      //We have AllowsDuplicates==false 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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+      T retval = removeAt(i);\r
+      if (ActiveEvents != 0)\r
+        raiseForRemove(retval);\r
+      return retval;\r
+    }\r
+\r
+    T removeAt(int i)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+#if MAINTAIN_SIZE\r
+      if (i < 0 || i >= size)\r
+        throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue");\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 (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      if (start < 0 || count < 0 || start + count > this.size)\r
+        throw new ArgumentOutOfRangeException();\r
+\r
+      updatecheck();\r
+\r
+      if (count == 0)\r
+        return;\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
+      //Alternative for large counts: rebuild tree using maketree()\r
+      for (int i = 0; i < count; i++)\r
+        removeAt(start);\r
+\r
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)\r
+        raiseCollectionCleared(false, count);\r
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\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 : DirectedCollectionValueBase<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
+      public override bool IsEmpty { get { return length == 0; } }\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
+\r
+      public override T Choose()\r
+      {\r
+        if (length == 0)\r
+          throw new NoSuchItemException();\r
+        return tree[start];\r
+      }\r
+\r
+      [Tested]\r
+      public override SCG.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 override 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 override 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 override IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }\r
+\r
+\r
+    [Tested]\r
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }\r
+\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 SCG.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 (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\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
+    }\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+\r
+      //persistence guard?\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+\r
+      //We must follow the pattern of removeIterative()\r
+      stackcheck();\r
+\r
+      T retval = deleteMin();\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsRemoved(retval, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+      return retval;\r
+    }\r
+\r
+    private T deleteMin()\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 (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+\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
+    }\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      //persistence guard?\r
+      updatecheck();\r
+      if (size == 0)\r
+        throw new NoSuchItemException();\r
+\r
+      //We must follow the pattern of removeIterative()\r
+      stackcheck();\r
+\r
+      T retval = deleteMax();\r
+      if (ActiveEvents != 0)\r
+      {\r
+        raiseItemsRemoved(retval, 1);\r
+        raiseCollectionChanged();\r
+      }\r
+      return retval;\r
+    }\r
+\r
+    private T deleteMax()\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is less than or equal to the minimum of this collection.)</exception>\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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 NoSuchItemException();\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is less than the minimum of this collection.)</exception>\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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 NoSuchItemException();\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
+    /// </summary>\r
+    /// <exception cref="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is greater than or equal to the maximum of this collection.)</exception>\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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 NoSuchItemException();\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="NoSuchItemException"> if no such element exists (the\r
+    /// supplied  value is greater than the maximum of this collection.)</exception>\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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 NoSuchItemException();\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
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      return new Range(this, true, bot, false, default(T), EnumerationDirection.Forwards);\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      return new Range(this, true, bot, true, top, EnumerationDirection.Forwards);\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      return new Range(this, false, default(T), true, top, EnumerationDirection.Forwards);\r
+    }\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
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      return new Range(this, false, default(T), false, default(T), EnumerationDirection.Forwards);\r
+    }\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-increasing (i.e. weakly decrerasing) function from the item type to \r
+    /// <code>int</code> is\r
+    /// negative, zero respectively positive. If the supplied cut function is\r
+    /// not non-increasing, 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 positive (if any).</param>\r
+    /// <param name="lowIsValid">True if the cut function is positive somewhere\r
+    /// on this collection.</param>\r
+    /// <param name="high">Returns the least item in the collection, where the\r
+    /// cut function is negative (if any).</param>\r
+    /// <param name="highIsValid">True if the cut function is negative 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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      return size - countTo(bot, true);\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\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)\r
+    {\r
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      return countTo(top, true);\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+\r
+      int count = CountFrom(low);\r
+\r
+      if (count == 0)\r
+        return;\r
+\r
+      stackcheck();\r
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;\r
+\r
+      for (int i = 0; i < count; i++)\r
+      {\r
+        T item = deleteMax();\r
+        if (wasRemoved != null)\r
+          wasRemoved.Enqueue(item);\r
+      }\r
+      if (wasRemoved != null)\r
+        raiseForRemoveAll(wasRemoved);\r
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+\r
+      int count = CountFromTo(low, hi);\r
+\r
+      if (count == 0)\r
+        return;\r
+\r
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;\r
+      int junk;\r
+      for (int i = 0; i < count; i++)\r
+      {\r
+        T item = Predecessor(hi);\r
+        removeIterative(ref item, false, out junk);\r
+        if (wasRemoved != null)\r
+          wasRemoved.Enqueue(item);\r
+      }\r
+      if (wasRemoved != null)\r
+        raiseForRemoveAll(wasRemoved);\r
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\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
+      if (!isValid)\r
+        throw new ViewDisposedException("Snapshot has been disposed");\r
+      updatecheck();\r
+\r
+      int count = CountTo(hi);\r
+\r
+      if (count == 0)\r
+        return;\r
+\r
+      stackcheck();\r
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;\r
+\r
+      for (int i = 0; i < count; i++)\r
+      {\r
+        T item = deleteMin();\r
+        if (wasRemoved != null)\r
+          wasRemoved.Enqueue(item);\r
+      }\r
+      if (wasRemoved != null)\r
+        raiseForRemoveAll(wasRemoved);\r
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)\r
+        raiseCollectionChanged();\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region IPersistent<T> Members\r
+#if NCP\r
+    int maxsnapid { get { return snapList == null ? -1 : findLastLiveSnapShot(); } }\r
+\r
+    int findLastLiveSnapShot()\r
+    {\r
+      if (snapList == null)\r
+        return -1;\r
+      SnapRef lastLiveSnapRef = snapList.Prev;\r
+      object _snapshot = null;\r
+      while (lastLiveSnapRef != null && (_snapshot = lastLiveSnapRef.Tree.Target) == null)\r
+        lastLiveSnapRef = lastLiveSnapRef.Prev;\r
+      if (lastLiveSnapRef == null)\r
+      {\r
+        snapList = null;\r
+        return -1;\r
+      }\r
+      if (snapList.Prev != lastLiveSnapRef)\r
+      {\r
+        snapList.Prev = lastLiveSnapRef;\r
+        lastLiveSnapRef.Next = snapList;\r
+      }\r
+      return ((TreeSet<T>)_snapshot).generation;\r
+    }\r
+\r
+    [Serializable]\r
+    class SnapRef\r
+    {\r
+      public SnapRef Prev, Next;\r
+      public WeakReference Tree;\r
+      public SnapRef(TreeSet<T> tree) { Tree = new WeakReference(tree); }\r
+      public void Dispose()\r
+      {\r
+        Next.Prev = Prev;\r
+        if (Prev != null)\r
+          Prev.Next = Next;\r
+        Next = Prev = null;\r
+      }\r
+    }\r
+#endif\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
+#if NCP\r
+      if (!isValid)\r
+        return;\r
+      if (isSnapShot)\r
+      {\r
+        snapList.Dispose();\r
+        snapDispose();\r
+      }\r
+      else\r
+      {\r
+        if (snapList != null)\r
+        {\r
+          SnapRef someSnapRef = snapList.Prev;\r
+          while (someSnapRef != null)\r
+          {\r
+            TreeSet<T> lastsnap;\r
+            if ((lastsnap = someSnapRef.Tree.Target as TreeSet<T>) != null)\r
+              lastsnap.snapDispose();\r
+            someSnapRef = someSnapRef.Prev;\r
+          }\r
+        }\r
+        snapList = null;\r
+        Clear();\r
+      }\r
+#else\r
+      Clear();\r
+#endif\r
+    }\r
+\r
+    private void snapDispose()\r
+    {\r
+      root = null;\r
+      dirs = null;\r
+      path = null;\r
+      comparer = null;\r
+      isValid = false;\r
+      snapList = null;\r
+    }\r
+\r
+    /// <summary>\r
+    /// Make a (read-only) snapshot of this collection.\r
+    /// </summary>\r
+    /// <returns>The snapshot.</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
+      TreeSet<T> res = (TreeSet<T>)MemberwiseClone();\r
+      SnapRef newSnapRef = new SnapRef(res);\r
+      res.isReadOnly = true;\r
+      res.isSnapShot = true;\r
+      res.snapList = newSnapRef;\r
+\r
+      findLastLiveSnapShot();\r
+      if (snapList == null)\r
+        snapList = new SnapRef(this);\r
+      SnapRef lastLiveSnapRef = snapList.Prev;\r
+\r
+      newSnapRef.Prev = lastLiveSnapRef;\r
+      if (lastLiveSnapRef != null)\r
+        lastLiveSnapRef.Next = newSnapRef;\r
+      newSnapRef.Next = snapList;\r
+      snapList.Prev = newSnapRef;\r
+\r
+      generation++;\r
+\r
+      return res;\r
+#endif\r
+    }\r
+\r
+    #endregion\r
+\r
+    #region TreeSet.Range nested class\r
+\r
+    internal class Range : DirectedCollectionValueBase<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, size;\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
+        if (!basis.isSnapShot)\r
+          size = haslowend ?\r
+              (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) :\r
+              (hashighend ? basis.CountTo(highend) : basis.Count);\r
+      }\r
+\r
+      #region IEnumerable<T> Members\r
+\r
+\r
+      #region TreeSet.Range.Enumerator nested class\r
+\r
+      internal class Enumerator : SCG.IEnumerator<T>\r
+      {\r
+        #region Private Fields\r
+        private bool valid = false, ready = true;\r
+\r
+        private SCG.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="CollectionModifiedException"/> 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
+\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
+        #region IEnumerator Members\r
+\r
+        object System.Collections.IEnumerator.Current\r
+        {\r
+          get { return Current; }\r
+        }\r
+\r
+        bool System.Collections.IEnumerator.MoveNext()\r
+        {\r
+          return MoveNext();\r
+        }\r
+\r
+        void System.Collections.IEnumerator.Reset()\r
+        {\r
+          throw new Exception("The method or operation is not implemented.");\r
+        }\r
+\r
+        #endregion\r
+      }\r
+\r
+      #endregion\r
+\r
+\r
+      public override T Choose()\r
+      {\r
+        if (size == 0) throw new NoSuchItemException();\r
+        return lowend;\r
+      }\r
+\r
+      [Tested]\r
+      public override SCG.IEnumerator<T> GetEnumerator() { return new Enumerator(this); }\r
+\r
+\r
+      [Tested]\r
+      public override 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 CollectionModifiedException();\r
+      }\r
+\r
+\r
+      void syncstamp() { stamp = basis.stamp; }\r
+\r
+      #endregion\r
+\r
+      [Tested]\r
+      public override 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
+      public override bool IsEmpty { get { return size == 0; } }\r
+\r
+      [Tested]\r
+      public override int Count { [Tested] get { return size; } }\r
+\r
+      //TODO: check that this is correct\r
+      public override Speed CountSpeed { get { return Speed.Constant; } }\r
+\r
+    }\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} (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
+ 0,\r
+#if NCP\r
+ n.generation,\r
+#endif\r
+ n.red ? "RED" : "BLACK",\r
+ 0,\r
+ 0,\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
+      0\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
+      0\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
+        0\r
+        , m);\r
+\r
+      return b;\r
+    }\r
+\r
+\r
+    bool rbminicheck(Node n, bool redp, 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 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
+      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, 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, 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
+      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
+      if (!isValid)\r
+        return true;\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
+        bool res = rbminicheck(root, false, o, out min, out max, out blackheight, generation);\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
+        return !res;\r
+      }\r
+      else\r
+        return false;\r
+    }\r
+    #endregion\r
+\r
+    #region ICloneable Members\r
+\r
+    /// <summary>\r
+    /// Make a shallow copy of this TreeSet.\r
+    /// </summary>\r
+    /// <returns></returns>\r
+    public virtual object Clone()\r
+    {\r
+      TreeSet<T> clone = new TreeSet<T>(comparer, EqualityComparer);\r
+      //TODO: make sure the TreeBag AddSorted copies tree bags smartly!!!\r
+      clone.AddSorted(this);\r
+      return clone;\r
+    }\r
+\r
+    #endregion\r
+\r
+  }\r
+}\r
+\r