龙腾猫跃 пре 4 месеци
родитељ
комит
ace30bfa50
1 измењених фајлова са 70 додато и 1 уклоњено
  1. 70 1
      Shared/General/ValueRange.cs

+ 70 - 1
Shared/General/ValueRange.cs

@@ -1,7 +1,7 @@
 namespace MeloongCore;
 
 /// <summary>
-/// 表示一个由可选下界和可选上界组成的值范围。
+/// 表示一个由可选下界和可选上界组成的范围。
 /// </summary>
 public sealed class ValueRange<T>(
     T? lower, T? upper,
@@ -77,6 +77,75 @@ public sealed class ValueRange<T>(
         return true;
     }
 
+    /// <summary>
+    /// 取当前范围与另一个范围的交集。
+    /// </summary>
+    /// <returns>
+    /// 若两个范围存在交集,则返回交集范围;否则返回 <see langword="null" />。
+    /// </returns>
+    public ValueRange<T>? Intersect(ValueRange<T> other) {
+        T? lower = default;
+        T? upper = default;
+        var isLowerInclusive = true;
+        var isUpperInclusive = true;
+
+        if (HasLower && other.HasLower) {
+            switch (Lower!.CompareTo(other.Lower!)) {
+                case > 0:
+                    lower = Lower;
+                    isLowerInclusive = IsLowerInclusive;
+                    break;
+                case < 0:
+                    lower = other.Lower;
+                    isLowerInclusive = other.IsLowerInclusive;
+                    break;
+                default:
+                    lower = Lower;
+                    isLowerInclusive = IsLowerInclusive && other.IsLowerInclusive;
+                    break;
+            }
+        } else if (HasLower) {
+            lower = Lower;
+            isLowerInclusive = IsLowerInclusive;
+        } else if (other.HasLower) {
+            lower = other.Lower;
+            isLowerInclusive = other.IsLowerInclusive;
+        }
+
+        if (HasUpper && other.HasUpper) {
+            switch (Upper!.CompareTo(other.Upper!)) {
+                case < 0:
+                    upper = Upper;
+                    isUpperInclusive = IsUpperInclusive;
+                    break;
+                case > 0:
+                    upper = other.Upper;
+                    isUpperInclusive = other.IsUpperInclusive;
+                    break;
+                default:
+                    upper = Upper;
+                    isUpperInclusive = IsUpperInclusive && other.IsUpperInclusive;
+                    break;
+            }
+        } else if (HasUpper) {
+            upper = Upper;
+            isUpperInclusive = IsUpperInclusive;
+        } else if (other.HasUpper) {
+            upper = other.Upper;
+            isUpperInclusive = other.IsUpperInclusive;
+        }
+
+        var anyHasLower = HasLower || other.HasLower;
+        var anyHasUpper = HasUpper || other.HasUpper;
+        if (anyHasLower && anyHasUpper) {
+            var compare = lower!.CompareTo(upper!);
+            if (compare > 0) return null;
+            if (compare == 0 && (!isLowerInclusive || !isUpperInclusive)) return null;
+        }
+
+        return new(lower, upper, isLowerInclusive, isUpperInclusive, anyHasLower, anyHasUpper);
+    }
+
     public override string ToString()
         => $"{(HasLower && IsLowerInclusive ? "[" : "(")}{(HasLower ? Lower!.ToString() : "-∞")}, {(HasUpper ? Upper!.ToString() : "+∞")}{(HasUpper && IsUpperInclusive ? "]" : ")")}";
 }