Repository: OpenMined/PySyft
Pull request #386 (2017-10-30 08:17:04)

add trigonometric functions
#### Reference Issue

Fixes:#381

#### Explain your changes.
added sin, cos, tan, sinh, cosh functions along with tests

codecov[bot]: # [Codecov](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=h1) Report
> Merging [#386](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=desc) into [master](https://codecov.io/gh/OpenMined/PySyft/commit/2dfa1f615e994d70378489acbc2e9e694fb89143?src=pr&el=desc) will **increase** coverage by `0.02%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/OpenMined/PySyft/pull/386/graphs/tree.svg?height=150&width=650&token=W0kQS1vaXB&src=pr)](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #386      +/-   ##
==========================================
+ Coverage   99.49%   99.52%   +0.02%     
==========================================
  Files           4        4              
  Lines        1592     1682      +90     
==========================================
+ Hits         1584     1674      +90     
  Misses          8        8
```


| [Impacted Files](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [PySyft/tests/test\_math.py](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=tree#diff-UHlTeWZ0L3Rlc3RzL3Rlc3RfbWF0aC5weQ==) | `100% <0%> (ø)` | :arrow_up: |
| [PySyft/tests/test\_tensor.py](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=tree#diff-UHlTeWZ0L3Rlc3RzL3Rlc3RfdGVuc29yLnB5) | `99.34% <0%> (+0.02%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=footer). Last update [2dfa1f6...e806aff](https://codecov.io/gh/OpenMined/PySyft/pull/386?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/syft/math.py b/syft/math.py
index f6405ccba2..e880c85ed9 100644
--- a/syft/math.py
+++ b/syft/math.py
@@ -17,10 +17,10 @@ from .tensor import TensorBase
 from .tensor import _ensure_tensorbase
 
 __all__ = [
-    'addbmm', 'addcdiv', 'addcmul', 'addmm', 'addmv', 'baddbmm', 'bmm', 'ceil',
-    'cumprod', 'cumsum', 'diag', 'dot', 'floor', 'fmod', 'lerp', 'matmul',
-    'mm', 'multinomial', 'numel', 'ones', 'rand', 'randn', 'renorm', 'sigmoid',
-    'tanh', 'transpose', 'unsqueeze', 'zeros'
+    'cumprod', 'cumsum', 'ceil', 'dot', 'floor', 'matmul', 'addmm', 'addcmul',
+    'addcdiv', 'addmv', 'bmm', 'addbmm', 'baddbmm', 'sigmoid', 'unsqueeze',
+    'sin', 'sinh', 'cos', 'cosh', 'tan', 'tanh', 'zeros', 'ones', 'rand',
+    'randn', 'mm', 'fmod', 'diag', 'lerp', 'renorm', 'numel'
 ]
 
 
@@ -763,6 +763,111 @@ def sigmoid(tensor):
     return TensorBase(1 / (1 + np.exp(np.array(-tensor.data))))
 
 
+def sin(tensor):
+    """
+    Returns a new tensor holding values of Trigonometric sine
+    function
+
+    Parameters
+    ----------
+    tensor: TensorBase
+        input Tensor
+
+    Returns
+    -------
+    TensorBase:
+        Output Tensor;
+    """
+    tensor = _ensure_tensorbase(tensor)
+    if tensor.encrypted:
+        return NotImplemented
+    return TensorBase(np.sin(np.array(tensor.data)))
+
+
+def sinh(tensor):
+    """
+    Returns a new tensor holding element wise values of hyperbolic sine
+    function
+
+    Parameters
+    ----------
+    tensor: TensorBase
+        input Tensor
+
+    Returns
+    -------
+    TensorBase:
+        Output Tensor;
+    """
+    tensor = _ensure_tensorbase(tensor)
+    if tensor.encrypted:
+        return NotImplemented
+    return TensorBase(np.sinh(np.array(tensor.data)))
+
+
+def cos(tensor):
+    """
+    Returns a new tensor holding values of Trigonometric cosine
+    function
+
+    Parameters
+    ----------
+    tensor: TensorBase
+        input Tensor
+
+    Returns
+    -------
+    TensorBase:
+        Output Tensor;
+    """
+    tensor = _ensure_tensorbase(tensor)
+    if tensor.encrypted:
+        return NotImplemented
+    return TensorBase(np.cos(np.array(tensor.data)))
+
+
+def cosh(tensor):
+    """
+    Returns a new tensor holding element wise values of hyperbolic cosine
+    function
+
+    Parameters
+    ----------
+    tensor: TensorBase
+        input Tensor
+
+    Returns
+    -------
+    TensorBase:
+        Output Tensor;
+    """
+    tensor = _ensure_tensorbase(tensor)
+    if tensor.encrypted:
+        return NotImplemented
+    return TensorBase(np.cosh(np.array(tensor.data)))
+
+
+def tan(tensor):
+    """
+    Returns a new tensor holding values of Trigonometric tan
+    function
+
+    Parameters
+    ----------
+    tensor: TensorBase
+        input Tensor
+
+    Returns
+    -------
+    TensorBase:
+        Output Tensor;
+    """
+    tensor = _ensure_tensorbase(tensor)
+    if tensor.encrypted:
+        return NotImplemented
+    return TensorBase(np.tan(np.array(tensor.data)))
+
+
 def tanh(tensor):
     """
     Returns a new tensor holding element wise values of tanh function
diff --git a/syft/tensor.py b/syft/tensor.py
index 59e24cbcf9..f774b294e1 100644
--- a/syft/tensor.py
+++ b/syft/tensor.py
@@ -3185,6 +3185,88 @@ class TensorBase(object):
         self.transpose_(0, 1)
         return self
 
+    def sin(self):
+        """
+        Performs sine function on the Tensor
+
+        Parameters
+        ----------
+
+        Returns
+        -------
+        Output tensor with sin applied
+        """
+        if self.encrypted:
+            return NotImplemented
+        self.data = syft.math.sin(self).data
+        return self
+
+    def sinh(self):
+        """
+        Performs sine function on the Tensor
+        elementwise
+
+        Parameters
+        ----------
+
+        Returns
+        -------
+        Caller with values in-place
+        """
+        if self.encrypted:
+            return NotImplemented
+        self.data = syft.math.sinh(self).data
+        return self
+
+    def cos(self):
+        """
+        Performs cosine function on the Tensor
+
+        Parameters
+        ----------
+
+        Returns
+        -------
+        Output tensor with cos applied
+        """
+        if self.encrypted:
+            return NotImplemented
+        self.data = syft.math.cos(self).data
+        return self
+
+    def cosh(self):
+        """
+        Performs cosine function on the Tensor
+        elementwise
+
+        Parameters
+        ----------
+
+        Returns
+        -------
+        Caller with values in-place
+        """
+        if self.encrypted:
+            return NotImplemented
+        self.data = syft.math.cosh(self).data
+        return self
+
+    def tan(self):
+        """
+        Performs tan function on the Tensor
+
+        Parameters
+        ----------
+
+        Returns
+        -------
+        Output tensor with tan applied
+        """
+        if self.encrypted:
+            return NotImplemented
+        self.data = syft.math.tan(self).data
+        return self
+
     def tanh_(self):
         """
         Performs tanh (hyperbolic tangent) function on the Tensor


Test patch:
diff --git a/tests/test_math.py b/tests/test_math.py
index a8445e7512..83b590f47b 100644
--- a/tests/test_math.py
+++ b/tests/test_math.py
@@ -84,6 +84,76 @@ class FloorTests(unittest.TestCase):
                                                                     [7., 8.]])))
 
 
+class SinTests(unittest.TestCase):
+    def test_sin(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        t2 = syft.math.sin(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3, 1, 2], [0, -1, 2]])))
+        self.assertTrue(syft.equal(t2.data, np.sin(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        t2 = syft.math.sin(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]])))
+        self.assertTrue(syft.equal(t2.data, np.sin(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class SinhTests(unittest.TestCase):
+    def test_sinh(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        t2 = syft.math.sinh(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3, 1, 2], [0, -1, 2]])))
+        self.assertTrue(syft.equal(t2.data, np.sinh(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        t2 = syft.math.sinh(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]])))
+        self.assertTrue(syft.equal(t2.data, np.sinh(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class CosTests(unittest.TestCase):
+    def test_cos(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        t2 = syft.math.cos(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3, 1, 2], [0, -1, 2]])))
+        self.assertTrue(syft.equal(t2.data, np.cos(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        t2 = syft.math.cos(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]])))
+        self.assertTrue(syft.equal(t2.data, np.cos(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class CoshTests(unittest.TestCase):
+    def test_cosh(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        t2 = syft.math.cosh(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3, 1, 2], [0, -1, 2]])))
+        self.assertTrue(syft.equal(t2.data, np.cosh(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        t2 = syft.math.cosh(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]])))
+        self.assertTrue(syft.equal(t2.data, np.cosh(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class TanTests(unittest.TestCase):
+    def test_tan(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        t2 = syft.math.tan(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3, 1, 2], [0, -1, 2]])))
+        self.assertTrue(syft.equal(t2.data, np.tan(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        t2 = syft.math.tan(t1)
+        self.assertTrue(syft.equal(t1.data, np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]])))
+        self.assertTrue(syft.equal(t2.data, np.tan(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
 class TanhTests(unittest.TestCase):
     def test_tanh(self):
         # int
diff --git a/tests/test_tensor.py b/tests/test_tensor.py
index 686b3798d3..c34b4cebc6 100644
--- a/tests/test_tensor.py
+++ b/tests/test_tensor.py
@@ -863,6 +863,66 @@ class NegTests(unittest.TestCase):
         self.assertTrue(np.array_equal(t2.data, np.array([[0.0, -1.5, 2.5], [0.0, 1.5, -2.5]])))
 
 
+class SinTests(unittest.TestCase):
+    def test_sin(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        out = t1.sin()
+        self.assertTrue(np.array_equal(out.data, np.sin(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        out = t1.sin()
+        self.assertTrue(np.array_equal(out.data, np.sin(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class SinhTests(unittest.TestCase):
+    def test_sinh(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        out = t1.sinh()
+        self.assertTrue(np.array_equal(out.data, np.sinh(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        out = t1.sinh()
+        self.assertTrue(np.array_equal(out.data, np.sinh(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class CosTests(unittest.TestCase):
+    def test_cos(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        out = t1.cos()
+        self.assertTrue(np.array_equal(out.data, np.cos(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        out = t1.cos()
+        self.assertTrue(np.array_equal(out.data, np.cos(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class CoshTests(unittest.TestCase):
+    def test_cosh(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        out = t1.cosh()
+        self.assertTrue(np.array_equal(out.data, np.cosh(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        out = t1.cosh()
+        self.assertTrue(np.array_equal(out.data, np.cosh(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
+class TanTests(unittest.TestCase):
+    def test_tan(self):
+        # int
+        t1 = TensorBase(np.array([[3, 1, 2], [0, -1, 2]]))
+        out = t1.tan()
+        self.assertTrue(np.array_equal(out.data, np.tan(np.array([[3, 1, 2], [0, -1, 2]]))))
+        # float
+        t1 = TensorBase(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))
+        out = t1.tan()
+        self.assertTrue(np.array_equal(out.data, np.tan(np.array([[3.3, 1.3, 2.2], [0.0, -1.3, 2.4]]))))
+
+
 class TanhTests(unittest.TestCase):
     def test_tanh_(self):
         # int