private void TestEq <T>(bool eq, Comparable <T> id1, Comparable <T> id2) { int h1 = id1.GetHashCode(); int h2 = id2.GetHashCode(); // eq reflectivity: NUnit.Framework.Assert.IsTrue(id1.Equals(id1)); NUnit.Framework.Assert.IsTrue(id2.Equals(id2)); NUnit.Framework.Assert.AreEqual(0, id1.CompareTo((T)id1)); NUnit.Framework.Assert.AreEqual(0, id2.CompareTo((T)id2)); // eq symmetry: NUnit.Framework.Assert.AreEqual(eq, id1.Equals(id2)); NUnit.Framework.Assert.AreEqual(eq, id2.Equals(id1)); // null comparison: NUnit.Framework.Assert.IsFalse(id1.Equals(null)); NUnit.Framework.Assert.IsFalse(id2.Equals(null)); // compareTo: NUnit.Framework.Assert.AreEqual(eq, 0 == id1.CompareTo((T)id2)); NUnit.Framework.Assert.AreEqual(eq, 0 == id2.CompareTo((T)id1)); // compareTo must be antisymmetric: NUnit.Framework.Assert.AreEqual(Sign(id1.CompareTo((T)id2)), -Sign(id2.CompareTo( (T)id1))); // compare with null should never return 0 to be consistent with #equals(): NUnit.Framework.Assert.IsTrue(id1.CompareTo(null) != 0); NUnit.Framework.Assert.IsTrue(id2.CompareTo(null) != 0); // check that hash codes did not change: NUnit.Framework.Assert.AreEqual(h1, id1.GetHashCode()); NUnit.Framework.Assert.AreEqual(h2, id2.GetHashCode()); if (eq) { // in this case the hash codes must be the same: NUnit.Framework.Assert.AreEqual(h1, h2); } }
/// <summary> /// Compares two values. The values can be of different, but compatible types. /// </summary> /// <param name="Value1">First value.</param> /// <param name="Value2">Second value.</param> /// <returns> /// Negative, if <paramref name="Value1"/><<paramref name="Value2"/>. /// Positive, if <paramref name="Value1"/>><paramref name="Value2"/>. /// Zero, if <paramref name="Value1"/>=<paramref name="Value2"/>. /// </returns> public static int?Compare(object Value1, object Value2) { bool IsNull1 = Value1 is null; bool IsNull2 = Value2 is null; if (IsNull1 ^ IsNull2) { if (IsNull1) { return(-1); } else { return(1); } } else if (IsNull1) { return(0); } if (!TryMakeSameType(ref Value1, ref Value2)) { return(null); } if (Value1 is IComparable Comparable) { return(Comparable.CompareTo(Value2)); } else if (Value1 is byte[] b1 && Value2 is byte[] b2) { return(Storage.IndexRecords.BinaryCompare(b1, b2)); }
/// <summary> /// Compares two values. The values can be of different, but compatible types. /// </summary> /// <param name="Value1">First value.</param> /// <param name="Value2">Second value.</param> /// <returns> /// Negative, if <paramref name="Value1"/><<paramref name="Value2"/>. /// Positive, if <paramref name="Value1"/>><paramref name="Value2"/>. /// Zero, if <paramref name="Value1"/>=<paramref name="Value2"/>. /// </returns> public static int?Compare(object Value1, object Value2) { bool IsNull1 = Value1 is null; bool IsNull2 = Value2 is null; if (IsNull1 ^ IsNull2) { if (IsNull1) { return(-1); } else { return(1); } } else if (IsNull1) { return(0); } if (!TryMakeSameType(ref Value1, ref Value2)) { return(null); } if (!(Value1 is IComparable Comparable)) { return(null); } return(Comparable.CompareTo(Value2)); }
// @param cookies [OUT] contains the found cookies // @param cookieIndex the index // @param comparator the prediction to decide whether or not // a cookie in index should be returned private void getInternal2 <T>(IList <HttpCookie> cookies, IDictionary <T, IList <HttpCookie> > cookieIndex, Comparable <T> comparator, bool secureLink) { foreach (T index in cookieIndex.Keys) { if (comparator.CompareTo(index) == 0) { IList <HttpCookie> indexedCookies = cookieIndex[index]; // check the list of cookies associated with this domain if (indexedCookies != null) { IEnumerator <HttpCookie> it = indexedCookies.GetEnumerator(); while (it.MoveNext()) { HttpCookie ck = it.Current; if (CookieJar.IndexOf(ck) != -1) { // the cookie still in main cookie store if (!ck.HasExpired()) { // don't add twice if ((secureLink || !ck.Secure) && !cookies.Contains(ck)) { cookies.Add(ck); } } else { it.remove(); CookieJar.Remove(ck); } } else { // the cookie has beed removed from main store, // so also remove it from domain indexed store it.remove(); } } } // end of indexedCookies != null } // end of comparator.compareTo(index) == 0 } // end of cookieIndex iteration }
/// <summary>Upper bound binary search.</summary> /// <remarks> /// Upper bound binary search. Find the index to the first element in the list /// that compares greater than the input key. /// </remarks> /// <?/> /// <param name="list">The list</param> /// <param name="key">The input key.</param> /// <returns> /// The index to the desired element if it exists; or list.size() /// otherwise. /// </returns> public static int UpperBound <T, _T1>(IList <_T1> list, T key) where _T1 : Comparable <T> { int low = 0; int high = list.Count; while (low < high) { int mid = (int)(((uint)(low + high)) >> 1); Comparable <T> midVal = list[mid]; int ret = midVal.CompareTo(key); if (ret <= 0) { low = mid + 1; } else { high = mid; } } return(low); }
/// <summary> /// Merges the validation method with a secondary validation method, if possible. /// </summary> /// <param name="SecondaryValidationMethod">Secondary validation method to merge with.</param> /// <param name="DataType">Underlying data type.</param> /// <returns>If merger was possible.</returns> public override bool Merge(ValidationMethod SecondaryValidationMethod, DataType DataType) { RangeValidation V2 = SecondaryValidationMethod as RangeValidation; if (V2 is null) { return(false); } if (string.IsNullOrEmpty(this.min) ^ string.IsNullOrEmpty(V2.min)) { return(false); } if (string.IsNullOrEmpty(this.max) ^ string.IsNullOrEmpty(V2.max)) { return(false); } if (this.min == V2.min && this.max == V2.max) { return(true); } if (DataType is null) { return(false); } object Min, Max; object Min2, Max2; IComparable Comparable; int i; if (!string.IsNullOrEmpty(this.min) && this.min != V2.min) { if (string.IsNullOrEmpty(this.min)) { Min = null; } else { Min = DataType.Parse(this.min); if (Min is null) { return(false); } } if (string.IsNullOrEmpty(V2.min)) { Min2 = null; } else { Min2 = DataType.Parse(V2.min); if (Min2 is null) { return(false); } } Comparable = Min as IComparable; if (Comparable is null) { return(false); } try { i = Comparable.CompareTo(Min2); } catch (Exception) { return(false); } if (i < 0) { this.min = V2.min; } } if (!string.IsNullOrEmpty(this.max) && this.max != V2.max) { if (string.IsNullOrEmpty(this.max)) { Max = null; } else { Max = DataType.Parse(this.max); if (Max is null) { return(false); } } if (string.IsNullOrEmpty(V2.max)) { Max2 = null; } else { Max2 = DataType.Parse(V2.max); if (Max2 is null) { return(false); } } Comparable = Max as IComparable; if (Comparable is null) { return(false); } try { i = Comparable.CompareTo(Max2); } catch (Exception) { return(false); } if (i > 0) { this.max = V2.max; } } return(true); }
/// <summary> /// Like gallopLeft, except that if the range contains an element equal to /// key, gallopRight returns the index after the rightmost equal element. /// </summary> /// <param name="key"> the key whose insertion point to search for </param> /// <param name="a"> the array in which to search </param> /// <param name="base"> the index of the first element in the range </param> /// <param name="len"> the length of the range; must be > 0 </param> /// <param name="hint"> the index at which to begin the search, 0 <= hint < n. /// The closer hint is to the result, the faster this method will run. </param> /// <returns> the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] </returns> private static int GallopRight(Comparable <Object> key, Object[] a, int @base, int len, int hint) { Debug.Assert(len > 0 && hint >= 0 && hint < len); int ofs = 1; int lastOfs = 0; if (key.CompareTo(a[@base + hint]) < 0) { // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] int maxOfs = hint + 1; while (ofs < maxOfs && key.CompareTo(a[@base + hint - ofs]) < 0) { lastOfs = ofs; ofs = (ofs << 1) + 1; if (ofs <= 0) // int overflow { ofs = maxOfs; } } if (ofs > maxOfs) { ofs = maxOfs; } // Make offsets relative to b int tmp = lastOfs; lastOfs = hint - ofs; ofs = hint - tmp; } // a[b + hint] <= key else { // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] int maxOfs = len - hint; while (ofs < maxOfs && key.CompareTo(a[@base + hint + ofs]) >= 0) { lastOfs = ofs; ofs = (ofs << 1) + 1; if (ofs <= 0) // int overflow { ofs = maxOfs; } } if (ofs > maxOfs) { ofs = maxOfs; } // Make offsets relative to b lastOfs += hint; ofs += hint; } Debug.Assert(-1 <= lastOfs && lastOfs < ofs && ofs <= len); /* * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to * the right of lastOfs but no farther right than ofs. Do a binary * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. */ lastOfs++; while (lastOfs < ofs) { int m = lastOfs + ((int)((uint)(ofs - lastOfs) >> 1)); if (key.CompareTo(a[@base + m]) < 0) { ofs = m; // key < a[b + m] } else { lastOfs = m + 1; // a[b + m] <= key } } Debug.Assert(lastOfs == ofs); // so a[b + ofs - 1] <= key < a[b + ofs] return(ofs); }
/// <summary> /// Locates the position at which to insert the specified key into the /// specified sorted range; if the range contains an element equal to key, /// returns the index of the leftmost equal element. /// </summary> /// <param name="key"> the key whose insertion point to search for </param> /// <param name="a"> the array in which to search </param> /// <param name="base"> the index of the first element in the range </param> /// <param name="len"> the length of the range; must be > 0 </param> /// <param name="hint"> the index at which to begin the search, 0 <= hint < n. /// The closer hint is to the result, the faster this method will run. </param> /// <returns> the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], /// pretending that a[b - 1] is minus infinity and a[b + n] is infinity. /// In other words, key belongs at index b + k; or in other words, /// the first k elements of a should precede key, and the last n - k /// should follow it. </returns> private static int GallopLeft(Comparable <Object> key, Object[] a, int @base, int len, int hint) { Debug.Assert(len > 0 && hint >= 0 && hint < len); int lastOfs = 0; int ofs = 1; if (key.CompareTo(a[@base + hint]) > 0) { // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] int maxOfs = len - hint; while (ofs < maxOfs && key.CompareTo(a[@base + hint + ofs]) > 0) { lastOfs = ofs; ofs = (ofs << 1) + 1; if (ofs <= 0) // int overflow { ofs = maxOfs; } } if (ofs > maxOfs) { ofs = maxOfs; } // Make offsets relative to base lastOfs += hint; ofs += hint; } // key <= a[base + hint] else { // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int maxOfs = hint + 1; int maxOfs = hint + 1; while (ofs < maxOfs && key.CompareTo(a[@base + hint - ofs]) <= 0) { lastOfs = ofs; ofs = (ofs << 1) + 1; if (ofs <= 0) // int overflow { ofs = maxOfs; } } if (ofs > maxOfs) { ofs = maxOfs; } // Make offsets relative to base int tmp = lastOfs; lastOfs = hint - ofs; ofs = hint - tmp; } Debug.Assert(-1 <= lastOfs && lastOfs < ofs && ofs <= len); /* * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere * to the right of lastOfs but no farther right than ofs. Do a binary * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. */ lastOfs++; while (lastOfs < ofs) { int m = lastOfs + ((int)((uint)(ofs - lastOfs) >> 1)); if (key.CompareTo(a[@base + m]) > 0) { lastOfs = m + 1; // a[base + m] < key } else { ofs = m; // key <= a[base + m] } } Debug.Assert(lastOfs == ofs); // so a[base + ofs - 1] < key <= a[base + ofs] return(ofs); }
/// <summary> /// Sorts the specified portion of the specified array using a binary /// insertion sort. This is the best method for sorting small numbers /// of elements. It requires O(n log n) compares, but O(n^2) data /// movement (worst case). /// /// If the initial part of the specified range is already sorted, /// this method can take advantage of it: the method assumes that the /// elements from index {@code lo}, inclusive, to {@code start}, /// exclusive are already sorted. /// </summary> /// <param name="a"> the array in which a range is to be sorted </param> /// <param name="lo"> the index of the first element in the range to be sorted </param> /// <param name="hi"> the index after the last element in the range to be sorted </param> /// <param name="start"> the index of the first element in the range that is /// not already known to be sorted ({@code lo <= start <= hi}) </param> //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @SuppressWarnings({"fallthrough", "rawtypes", "unchecked"}) private static void binarySort(Object[] a, int lo, int hi, int start) private static void BinarySort(Object[] a, int lo, int hi, int start) { Debug.Assert(lo <= start && start <= hi); if (start == lo) { start++; } for (; start < hi; start++) { Comparable pivot = (Comparable)a[start]; // Set left (and right) to the index where a[start] (pivot) belongs int left = lo; int right = start; Debug.Assert(left <= right); /* * Invariants: * pivot >= all in [lo, left). * pivot < all in [right, start). */ while (left < right) { int mid = (int)((uint)(left + right) >> 1); if (pivot.CompareTo(a[mid]) < 0) { right = mid; } else { left = mid + 1; } } Debug.Assert(left == right); /* * The invariants still hold: pivot >= all in [lo, left) and * pivot < all in [left, start), so pivot belongs at left. Note * that if there are elements equal to pivot, left points to the * first slot after them -- that's why this sort is stable. * Slide elements over to make room for pivot. */ int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case switch (n) { case 2: a[left + 2] = a[left + 1]; goto case 1; case 1: a[left + 1] = a[left]; break; default: System.Array.Copy(a, left, a, left + 1, n); break; } a[left] = pivot; } }