From 29550762bd205269a25546455923d32ad1f645ad Mon Sep 17 00:00:00 2001
From: "A. Unique TensorFlower" <gardener@tensorflow.org>
Date: Mon, 31 Jul 2017 09:53:35 -0700
Subject: [PATCH] Fixes unit tests for inverse hyperbolic functions that were
 failing because numeric gradients were computed too close to a branch cut
 (for complex arguments) or singularity (for real arguments) where the
 function is not differentiable (See, e.g.,
 http://mathworld.wolfram.com/BranchCut.html). This change moves the test
 points away from the branch cut/singularity.

Improves precision of double precision numerical gradients by using a smaller step size delta (the optimal for symmetric difference approximation with functions computed with O(epsilon) error is epsilon^(1/3), so for double64 it is ~1e-5).

PiperOrigin-RevId: 163706297
---
 .../python/kernel_tests/cwise_ops_test.py     | 45 +++++++++----------
 1 file changed, 20 insertions(+), 25 deletions(-)

diff --git a/tensorflow/python/kernel_tests/cwise_ops_test.py b/tensorflow/python/kernel_tests/cwise_ops_test.py
index 5a0fb1879aa..d03a04b24ed 100644
--- a/tensorflow/python/kernel_tests/cwise_ops_test.py
+++ b/tensorflow/python/kernel_tests/cwise_ops_test.py
@@ -100,18 +100,18 @@ class UnaryOpTest(test.TestCase):
         inxf = ops.convert_to_tensor(xf)
         yf = tf_func(inxf)
         _, jacob_n = gradient_checker.compute_gradient(
-            inxf, s, yf, s, x_init_value=xf)
+            inxf, s, yf, s, x_init_value=xf, delta=1e-2)
         jacob_n = jacob_n.astype(np.float16)
         self.assertAllClose(jacob_t, jacob_n, rtol=5e-3, atol=5e-3)
       elif x.dtype in (np.float32, np.complex64):
         s = list(np.shape(x))
         jacob_t, jacob_n = gradient_checker.compute_gradient(
-            inx, s, y, s, x_init_value=x)
+            inx, s, y, s, x_init_value=x, delta=1e-3)
         self.assertAllClose(jacob_t, jacob_n, rtol=1e-3, atol=1e-3)
       elif x.dtype in (np.float64, np.complex128):
         s = list(np.shape(x))
         jacob_t, jacob_n = gradient_checker.compute_gradient(
-            inx, s, y, s, x_init_value=x)
+            inx, s, y, s, x_init_value=x, delta=1e-5)
         self.assertAllClose(jacob_t, jacob_n, rtol=1e-5, atol=1e-5)
 
   def _check(self, result_tensor, result_np, input_sp_t, tol):
@@ -184,7 +184,7 @@ class UnaryOpTest(test.TestCase):
 
   def testFloatBasic(self):
     x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float32)
-    w = x - x.min() + 1.01 # all greater than 1
+    w = x - x.min() + 1.02  # all greater than 1
     y = (x + .5).astype(np.float32)  # no zero
     z = (x + 15.5).astype(np.float32)  # all positive
     k = np.arange(-0.90, 0.90, 0.25).astype(np.float32)  # between -1 and 1
@@ -204,10 +204,9 @@ class UnaryOpTest(test.TestCase):
     self._compareBoth(x, np.sinh, math_ops.sinh)
     self._compareBoth(x, np.cosh, math_ops.cosh)
     self._compareBoth(x, np.tanh, math_ops.tanh)
-    # b/63457572: failing under CUDA.
-    # self._compareBoth(x, np.arcsinh, math_ops.asinh)
-    # self._compareBoth(w, np.arccosh, math_ops.acosh)
-    # self._compareBoth(k, np.arctanh, math_ops.atanh)
+    self._compareBoth(x, np.arcsinh, math_ops.asinh)
+    self._compareBoth(w, np.arccosh, math_ops.acosh)
+    self._compareBoth(k, np.arctanh, math_ops.atanh)
     self._compareBoth(x, self._sigmoid, math_ops.sigmoid)
     self._compareBoth(x, self._log_sigmoid, math_ops.log_sigmoid)
     self._compareBoth(y, np.sign, math_ops.sign)
@@ -253,8 +252,7 @@ class UnaryOpTest(test.TestCase):
     self._compareBoth(x, np.log, math_ops.log)
     self._compareBoth(x, np.log1p, math_ops.log1p)
     self._compareBoth(x, np.sinh, math_ops.sinh)
-    # b/63457572.
-    # self._compareBoth(x, np.arcsinh, math_ops.asinh)
+    self._compareBoth(x, np.arcsinh, math_ops.asinh)
     self._compareBoth(x, np.cosh, math_ops.cosh)
     self._compareBoth(x, np.tanh, math_ops.tanh)
     self._compareBoth(x, self._sigmoid, math_ops.sigmoid)
@@ -280,7 +278,7 @@ class UnaryOpTest(test.TestCase):
 
   def testDoubleBasic(self):
     x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float64)
-    w = x - x.min() + 1.01 # all greater than 1
+    w = x - x.min() + 1.02  # all greater than 1
     y = (x + .5).astype(np.float64)  # no zero
     z = (x + 15.5).astype(np.float64)  # all positive
     k = np.arange(-0.90, 0.90, 0.35).reshape(1, 3, 2).astype(
@@ -300,10 +298,9 @@ class UnaryOpTest(test.TestCase):
     self._compareBoth(x, np.sinh, math_ops.sinh)
     self._compareBoth(x, np.cosh, math_ops.cosh)
     self._compareBoth(x, np.tanh, math_ops.tanh)
-    # b/63457572: failing under CUDA.
-    # self._compareBoth(x, np.arcsinh, math_ops.asinh)
-    # self._compareBoth(w, np.arccosh, math_ops.acosh)
-    # self._compareBoth(k, np.arctanh, math_ops.atanh)
+    self._compareBoth(x, np.arcsinh, math_ops.asinh)
+    self._compareBoth(w, np.arccosh, math_ops.acosh)
+    self._compareBoth(k, np.arctanh, math_ops.atanh)
     self._compareBoth(x, self._sigmoid, math_ops.sigmoid)
     self._compareBoth(y, np.sign, math_ops.sign)
     self._compareBoth(x, np.sin, math_ops.sin)
@@ -394,7 +391,7 @@ class UnaryOpTest(test.TestCase):
   def testComplex64Basic(self):
     x = np.complex(1, 1) * np.arange(-3, 3).reshape(1, 3,
                                                     2).astype(np.complex64)
-    y = x + 0.5  # no zeros
+    y = x + np.complex(0.5, 0.5)  # no zeros
     self._compareBoth(x, np.abs, math_ops.abs)
     self._compareBoth(x, np.abs, _ABS)
     self._compareBoth(x, np.negative, math_ops.negative)
@@ -410,10 +407,9 @@ class UnaryOpTest(test.TestCase):
     self._compareCpu(x, np.sinh, math_ops.sinh)
     self._compareCpu(x, np.cosh, math_ops.cosh)
     self._compareCpu(x, np.tanh, math_ops.tanh)
-    # b/63457572: failing under CUDA.
-    # self._compareCpu(x, np.arcsinh, math_ops.asinh)
-    # self._compareCpu(x, np.arccosh, math_ops.acosh)
-    # self._compareCpu(x, np.arctanh, math_ops.atanh)
+    self._compareCpu(y, np.arcsinh, math_ops.asinh)
+    self._compareCpu(y, np.arccosh, math_ops.acosh)
+    self._compareCpu(y, np.arctanh, math_ops.atanh)
     self._compareCpu(x, self._sigmoid, math_ops.sigmoid)
     self._compareCpu(x, np.sin, math_ops.sin)
     self._compareCpu(x, np.cos, math_ops.cos)
@@ -434,7 +430,7 @@ class UnaryOpTest(test.TestCase):
   def testComplex128Basic(self):
     x = np.complex(1, 1) * np.arange(-3, 3).reshape(1, 3,
                                                     2).astype(np.complex128)
-    y = x + 0.5  # no zeros
+    y = x + np.complex(0.5, 0.5)  # no zeros
     self._compareBoth(x, np.abs, math_ops.abs)
     self._compareBoth(x, np.abs, _ABS)
     self._compareBoth(x, np.negative, math_ops.negative)
@@ -450,10 +446,9 @@ class UnaryOpTest(test.TestCase):
     self._compareCpu(x, np.sinh, math_ops.sinh)
     self._compareCpu(x, np.cosh, math_ops.cosh)
     self._compareCpu(x, np.tanh, math_ops.tanh)
-    # b/63457572, failing under CUDA.
-    # self._compareCpu(x, np.arcsinh, math_ops.asinh)
-    # self._compareCpu(x, np.arccosh, math_ops.acosh)
-    # self._compareCpu(x, np.arctanh, math_ops.atanh)
+    self._compareCpu(y, np.arcsinh, math_ops.asinh)
+    self._compareCpu(y, np.arccosh, math_ops.acosh)
+    self._compareCpu(y, np.arctanh, math_ops.atanh)
     self._compareCpu(x, self._sigmoid, math_ops.sigmoid)
     self._compareCpu(x, np.sin, math_ops.sin)
     self._compareCpu(x, np.cos, math_ops.cos)