Repository: OpenMined/PySyft

Issue:
Implement Default eq Functionality for Base Tensor Type
**User Story A:** As a Data Scientist using Syft's Base Tensor type, we want to implement a default method for computing operations on a Tensor of arbitrary type. For this ticket to be complete, eq() should return a new tensor and eq_() should perform the operation inline. For a reference on the operation this performs check out [PyTorch](http://pytorch.org/docs/master/tensors.html)'s documentation.

**Acceptance Criteria:**
- If the Base Tensor type's attribute "encrypted" is set to True, it should return a NotImplemented error.
- a unit test demonstrating the correct operation on the Base Tensor type implemented over int and float Tensors.
- inline documentation in the python code. For inspiration on inline documentation, please check out [PyTorch](http://pytorch.org/docs/master/tensors.html)'s documentation for this operator.


Discussion:

Resolving patch:
diff --git a/syft/tensor.py b/syft/tensor.py
--- a/syft/tensor.py
+++ b/syft/tensor.py
@@ -1200,6 +1200,21 @@ def masked_scatter_(self, mask, source):
         out_flat = [s if m == 0 else source_iter.__next__().item() for m, s in mask_self_iter]
         self.data = np.reshape(out_flat, self.data.shape)
 
+    def eq(self, t):
+        """Returns a new Tensor having boolean True values where an element of the calling tensor is equal to the second Tensor, False otherwise.
+        The second Tensor can be a number or a tensor whose shape is broadcastable with the calling Tensor."""
+        if self.encrypted:
+            return NotImplemented
+        return TensorBase(np.equal(self.data, _ensure_tensorbase(t).data))
+
+    def eq_(self, t):
+        """Writes in-place, boolean True values where an element of the calling tensor is equal to the second Tensor, False otherwise.
+        The second Tensor can be a number or a tensor whose shape is broadcastable with the calling Tensor."""
+        if self.encrypted:
+            return NotImplemented
+        self.data = np.equal(self.data, _ensure_tensorbase(t).data)
+        return self
+
 
 def mv(tensormat, tensorvector):
     """ matrix and vector multiplication """


Test patch:
diff --git a/tests/test_tensor.py b/tests/test_tensor.py
--- a/tests/test_tensor.py
+++ b/tests/test_tensor.py
@@ -908,5 +908,29 @@ def testMasked_scatter_braodcasting2(self):
         self.assertTrue(np.array_equal(t, TensorBase([[1, 2, 3], [1, 1, 1]])))
 
 
+class eqTests(unittest.TestCase):
+    def testEqWithTensor(self):
+        t1 = TensorBase(np.arange(5))
+        t2 = TensorBase(np.arange(5)[-1::-1])
+        truth_values = t1.eq(t2)
+        self.assertEqual(truth_values, [False, False, True, False, False])
+
+    def testEqWithNumber(self):
+        t1 = TensorBase(np.arange(5))
+        truth_values = t1.eq(1)
+        self.assertEqual(truth_values, [False, True, False, False, False])
+
+    def testEqInPlaceWithTensor(self):
+        t1 = TensorBase(np.arange(5))
+        t2 = TensorBase(np.arange(5)[-1::-1])
+        t1.eq_(t2)
+        self.assertEqual(t1, [False, False, True, False, False])
+
+    def testEqInPlaceWithNumber(self):
+        t1 = TensorBase(np.arange(5))
+        t1.eq_(1)
+        self.assertEqual(t1, [False, True, False, False, False])
+
+
 if __name__ == "__main__":
     unittest.main()