Repository: OpenMined/PySyft

Issue:
Implement Default select Functionality for Base Tensor Type
**User Story A:** As a Data Scientist using Syft's Base Tensor type, I want to leverage a default method for computing operations on a Tensor of arbitrary type. For this ticket to be complete, select() should return a new tensor. 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:

Patch:
diff --git a/syft/tensor.py b/syft/tensor.py
index 8ed5efad8d..6cf00090e3 100644
--- a/syft/tensor.py
+++ b/syft/tensor.py
@@ -1160,6 +1160,22 @@ class TensorBase(object):
     def deserialize(b):
         return pickle.loads(b)
 
+    def index_select(self, dim, index):
+        """
+        Returns a new Tensor which indexes the ``input`` Tensor along
+        dimension ``dim`` using the entries in ``index``.
+
+        :param dim: dimension in which to index
+        :param index: 1D tensor containing the indices to index
+        :return: Tensor of selected indices
+        """
+        index = _ensure_tensorbase(index)
+        if self.encrypted or index.encrypted:
+            return NotImplemented
+        if index.data.ndim > 1:
+            raise ValueError("Index is supposed to be 1D")
+        return TensorBase(self.data.take(index, axis=dim))
+
     def mv(self, tensorvector):
         if self.encrypted:
             raise NotImplemented


Test patch:
diff --git a/tests/test_tensor.py b/tests/test_tensor.py
index f876fdf5ef..365a9e96dc 100644
--- a/tests/test_tensor.py
+++ b/tests/test_tensor.py
@@ -751,6 +751,16 @@ class notEqualTests(unittest.TestCase):
         self.assertTrue(syft.equal(t1, TensorBase([1, 1, 1, 0])))
 
 
+class index_selectTests(unittest.TestCase):
+    def testIndex_select(self):
+        t = TensorBase(np.reshape(np.arange(0, 2 * 3 * 4), (2, 3, 4)))
+        idx = np.array([1, 0])
+        dim = 2
+        result = t.index_select(dim=dim, index=idx)
+        expected = np.array([[[1, 0], [5, 4], [9, 8]], [[13, 12], [17, 16], [21, 20]]])
+        self.assertTrue(np.array_equal(result.data, expected))
+
+
 class gatherTests(unittest.TestCase):
     def testGatherNumerical1(self):
         t = TensorBase(np.array([[65, 17], [14, 25], [76, 22]]))