From aaa12450c06d994900ae86fc7a1a9f8f2e25038d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 11 Mar 2019 23:05:10 +0100 Subject: [PATCH] Implement set-theoretic methods in std::set C# typemaps These implementations are not optimized, i.e. are done in a naive way in C#, rather than using C++ functions more efficiently, but are better than nothing. --- CHANGES.current | 3 - .../test-suite/csharp/li_std_set_runme.cs | 34 +++++++ Lib/csharp/std_set.i | 88 ++++++++++++++++--- 3 files changed, 112 insertions(+), 13 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 3e3da1099..3765a8273 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -10,9 +10,6 @@ Version 4.0.0 (in progress) 2019-03-12: vadz [C#] Add std::set<> typemaps. - Not all methods of System.Collections.Generic.ISet are implemented yet, but all the - basic methods, including elements access and iteration, are. - 2019-03-11: dirteat,opoplawski [Octave] Fix compilation errors in Octave 5.1. diff --git a/Examples/test-suite/csharp/li_std_set_runme.cs b/Examples/test-suite/csharp/li_std_set_runme.cs index c186c2f7a..6519e8c8d 100644 --- a/Examples/test-suite/csharp/li_std_set_runme.cs +++ b/Examples/test-suite/csharp/li_std_set_runme.cs @@ -51,5 +51,39 @@ public class runme ss.Clear(); checkThat(ss.Count == 0, "is empty after Clear()"); + + // Check set-theoretic methods. + checkThat(new StringSet().SetEquals(new StringSet()), "SetEquals() works for empty sets"); + checkThat(new StringSet{"foo"}.SetEquals(new StringSet{"foo"}), "SetEquals() works for non-empty sets"); + checkThat(!new StringSet{"foo"}.SetEquals(new[] {"bar"}), "SetEquals() doesn't always return true"); + + ss = new StringSet{"foo", "bar", "baz"}; + ss.ExceptWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"foo", "bar"}), "ExceptWith works"); + + ss = new StringSet{"foo", "bar", "baz"}; + ss.IntersectWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"baz"}), "IntersectWith works"); + + checkThat(ss.IsProperSubsetOf(new[] {"bar", "baz"}), "IsProperSubsetOf works"); + checkThat(!ss.IsProperSubsetOf(new[] {"baz"}), "!IsProperSubsetOf works"); + checkThat(ss.IsSubsetOf(new[] {"bar", "baz"}), "IsSubsetOf works"); + checkThat(!ss.IsSubsetOf(new[] {"bar"}), "!IsSubsetOf works"); + + ss = new StringSet{"foo", "bar", "baz"}; + checkThat(ss.IsProperSupersetOf(new[] {"bar"}), "IsProperSupersetOf works"); + checkThat(!ss.IsProperSupersetOf(new[] {"quux"}), "IsProperSupersetOf works"); + checkThat(ss.IsSupersetOf(new[] {"foo", "bar", "baz"}), "IsProperSupersetOf works"); + checkThat(!ss.IsSupersetOf(new[] {"foo", "bar", "baz", "quux"}), "IsProperSupersetOf works"); + + checkThat(ss.Overlaps(new[] {"foo"}), "Overlaps works"); + checkThat(!ss.Overlaps(new[] {"moo"}), "!Overlaps works"); + + ss.SymmetricExceptWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"foo", "bar", "quux"}), "SymmetricExceptWith works"); + + ss = new StringSet{"foo", "bar", "baz"}; + ss.UnionWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"foo", "bar", "baz", "quux"}), "UnionWith works"); } } diff --git a/Lib/csharp/std_set.i b/Lib/csharp/std_set.i index b988d8d91..c5dd09473 100644 --- a/Lib/csharp/std_set.i +++ b/Lib/csharp/std_set.i @@ -71,16 +71,84 @@ class set { } } - public void ExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public void IntersectWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public bool IsProperSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public bool IsProperSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public bool IsSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public bool IsSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public bool Overlaps(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public bool SetEquals(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public void SymmetricExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } - public void UnionWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); } + public void ExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + Remove(item); + } + } + + public void IntersectWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + $csclassname old = new $csclassname(this); + + Clear(); + foreach ($typemap(cstype, T) item in other) { + if (old.Contains(item)) + Add(item); + } + } + + private static int count_enum(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + int count = 0; + foreach ($typemap(cstype, T) item in other) { + count++; + } + + return count; + } + + public bool IsProperSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSubsetOf(other) && Count < count_enum(other); + } + + public bool IsProperSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSupersetOf(other) && Count > count_enum(other); + } + + public bool IsSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + int countContained = 0; + + foreach ($typemap(cstype, T) item in other) { + if (Contains(item)) + countContained++; + } + + return countContained == Count; + } + + public bool IsSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (!Contains(item)) + return false; + } + + return true; + } + + public bool Overlaps(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (Contains(item)) + return true; + } + + return false; + } + + public bool SetEquals(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSupersetOf(other) && Count == count_enum(other); + } + + public void SymmetricExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (!Remove(item)) + Add(item); + } + } + + public void UnionWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + Add(item); + } + } private global::System.Collections.Generic.ICollection<$typemap(cstype, T)> Items { get {