Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Src/IronPython/Runtime/Operations/ArrayOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,58 @@ public static object __new__(CodeContext context, PythonType pythonType, object
return res;
}

[StaticExtensionMethod]
public static object __eq__(CodeContext context, Array self, [NotNone] Array other) {
if (self is null) throw PythonOps.TypeError("expected Array, got None");
if (other is null) throw PythonOps.TypeError("expected Array, got None");

if (self.GetType() != other.GetType()) return ScriptingRuntimeHelpers.False;
// same type implies: same rank, same element type
for (int d = 0; d < self.Rank; d++) {
if (self.GetLowerBound(d) != other.GetLowerBound(d)) return ScriptingRuntimeHelpers.False;
if (self.GetUpperBound(d) != other.GetUpperBound(d)) return ScriptingRuntimeHelpers.False;
}
if (self.Length == 0) return ScriptingRuntimeHelpers.True; // fast track

if (self.Rank == 1 && self.GetLowerBound(0) == 0 ) {
// IStructuralEquatable.Equals only works for 1-dim, 0-based arrays
return ScriptingRuntimeHelpers.BooleanToObject(
((IStructuralEquatable)self).Equals(other, context.LanguageContext.EqualityComparerNonGeneric)
);
} else {
int[] ix = new int[self.Rank];
for (int d = 0; d < self.Rank; d++) {
ix[d] = self.GetLowerBound(d);
}
for (int i = 0; i < self.Length; i++) {
if (!PythonOps.EqualRetBool(self.GetValue(ix), other.GetValue(ix))) {
return ScriptingRuntimeHelpers.False;
}
for (int d = self.Rank - 1; d >= 0; d--) {
if (ix[d] < self.GetUpperBound(d)) {
ix[d]++;
break;
} else {
ix[d] = self.GetLowerBound(d);
}
}
}
return ScriptingRuntimeHelpers.True;
}
}

[StaticExtensionMethod]
[return: MaybeNotImplemented]
public static object __eq__(CodeContext context, object self, object? other) => NotImplementedType.Value;

[StaticExtensionMethod]
public static object __ne__(CodeContext context, Array self, [NotNone] Array other)
=> ScriptingRuntimeHelpers.BooleanToObject(ReferenceEquals(__eq__(context, self, other), ScriptingRuntimeHelpers.False));

[StaticExtensionMethod]
[return: MaybeNotImplemented]
public static object __ne__(CodeContext context, object self, object? other) => NotImplementedType.Value;

/// <summary>
/// Multiply two object[] arrays - slow version, we need to get the type, etc...
/// </summary>
Expand Down
86 changes: 86 additions & 0 deletions Tests/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,90 @@ def test_tuple_indexer(self):
array1[0,0] = 5
self.assertEqual(array1[0,0], array1[(0,0)])

def test_equality(self):
a = System.Array.CreateInstance(int, 5)
a2 = System.Array.CreateInstance(int, 5) # same as a
b = System.Array.CreateInstance(int, 5, 6) # different rank
c = System.Array.CreateInstance(int, 6) # different length
d = System.Array.CreateInstance(int, (5,), (1,)) # different base
e = System.Array.CreateInstance(System.Int32, 5) # different element type
l = [0] * 5 # different type

self.assertTrue(a == a2)
self.assertTrue(a2 == a)
self.assertFalse(a != a2)
self.assertFalse(a2 != a)

self.assertFalse(a == b)
self.assertFalse(b == a)
self.assertTrue(a != b)
self.assertTrue(b != a)

self.assertFalse(a == c)
self.assertFalse(c == a)
self.assertTrue(a != c)
self.assertTrue(c != a)

self.assertFalse(a == d)
self.assertFalse(d == a)
self.assertTrue(a != d)
self.assertTrue(d != a)

self.assertFalse(a == e)
self.assertFalse(e == a)
self.assertTrue(a != e)
self.assertTrue(e != a)

self.assertFalse(a == l)
self.assertFalse(l == a)
self.assertTrue(a != l)
self.assertTrue(l != a)

def test_equality_base(self):
a = System.Array.CreateInstance(int, (5,), (5,))
a2 = System.Array.CreateInstance(int, (5,), (5,))
b = System.Array.CreateInstance(int, (6,), (5,))
c = System.Array.CreateInstance(int, (5,), (6,))
d = System.Array.CreateInstance(int, (6,), (6,))

self.assertTrue(a == a2)
self.assertFalse(a == b)
self.assertFalse(a == c)
self.assertFalse(a == d)

self.assertFalse(a != a2)
self.assertTrue(a != b)
self.assertTrue(a != c)
self.assertTrue(a != d)

def test_equality_rank(self):
a = System.Array.CreateInstance(int, 5, 6)
a2 = System.Array.CreateInstance(int, 5, 6)
b = System.Array.CreateInstance(int, 5, 6)
b[0, 0] = 1
c = System.Array.CreateInstance(int, (6, 5), (0, 0))
c[0, 0] = 1
d = System.Array.CreateInstance(int, (6, 5), (1, 1))
d[1, 1] = 1
d1 = System.Array.CreateInstance(int, (6, 5), (1, 1))
d1[1, 1] = 1

self.assertTrue(a == a2)
self.assertFalse(a == b) # different element
self.assertFalse(a == c) # different rank
self.assertFalse(a == d) # different rank
self.assertFalse(b == c) # different shape
self.assertFalse(b == d) # different shape & base
self.assertFalse(c == d) # different base
self.assertTrue(d == d1)

self.assertFalse(a != a2)
self.assertTrue(a != b)
self.assertTrue(a != c)
self.assertTrue(a != d)
self.assertTrue(b != c)
self.assertTrue(b != d)
self.assertTrue(c != d)
self.assertFalse(d != d1)

run_test(__name__)