From 29494d703d54f3e13bd9c9c1ed695b873ca93e9e Mon Sep 17 00:00:00 2001 From: ShenLiang Date: Fri, 28 Aug 2020 13:22:24 +0800 Subject: [PATCH] fix remainder, floor_div (#26732) * fix remainder, floordiv --- .../elementwise/elementwise_floordiv_op.h | 24 +++++++++++++++++-- .../elementwise/elementwise_mod_op.h | 10 ++++++-- .../unittests/test_elementwise_floordiv_op.py | 21 ++++++++++++++++ .../unittests/test_elementwise_mod_op.py | 16 +++++++++++++ 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/paddle/fluid/operators/elementwise/elementwise_floordiv_op.h b/paddle/fluid/operators/elementwise/elementwise_floordiv_op.h index a5909aad99a..8afe2133c04 100644 --- a/paddle/fluid/operators/elementwise/elementwise_floordiv_op.h +++ b/paddle/fluid/operators/elementwise/elementwise_floordiv_op.h @@ -26,14 +26,34 @@ namespace operators { template struct FloorDivFunctor { inline HOSTDEVICE T operator()(T a, T b) const { - return static_cast(floor(a / b)); +#ifdef __CUDA_ARCH__ + if (b == 0) { + printf("Error: Divide by zero encounter in floor_divide\n"); + asm("trap;"); + } +#else + if (b == 0) + PADDLE_THROW(platform::errors::InvalidArgument( + "Divide by zero encounter in floor_divide")); +#endif + return static_cast(std::trunc(a / b)); } }; template struct InverseFloorDivFunctor { inline HOSTDEVICE T operator()(T a, T b) const { - return static_cast(floor(b / a)); +#ifdef __CUDA_ARCH__ + if (a == 0) { + printf("Error: Divide by zero encounter in floor_divide\n"); + asm("trap;"); + } +#else + if (a == 0) + PADDLE_THROW(platform::errors::InvalidArgument( + "Divide by zero encounter in floor_divide")); +#endif + return static_cast(std::trunc(b / a)); } }; diff --git a/paddle/fluid/operators/elementwise/elementwise_mod_op.h b/paddle/fluid/operators/elementwise/elementwise_mod_op.h index 4306a471b76..47bd6af0b95 100644 --- a/paddle/fluid/operators/elementwise/elementwise_mod_op.h +++ b/paddle/fluid/operators/elementwise/elementwise_mod_op.h @@ -24,13 +24,19 @@ namespace operators { template struct ModFunctor { - inline HOSTDEVICE T operator()(T a, T b) const { return a % b; } + inline HOSTDEVICE T operator()(T a, T b) const { + T res = a % b; + if ((res != 0) && ((res < 0) != (b < 0))) res += b; + return res; + } }; template struct ModFunctorFP { inline HOSTDEVICE T operator()(T a, T b) const { - return fmod(b + fmod(a, b), b); + T res = fmod(a, b); + if ((res != 0) && ((b < 0) != (res < 0))) res += b; + return res; } }; diff --git a/python/paddle/fluid/tests/unittests/test_elementwise_floordiv_op.py b/python/paddle/fluid/tests/unittests/test_elementwise_floordiv_op.py index 4fe085ce854..0b6acc76153 100644 --- a/python/paddle/fluid/tests/unittests/test_elementwise_floordiv_op.py +++ b/python/paddle/fluid/tests/unittests/test_elementwise_floordiv_op.py @@ -193,6 +193,27 @@ class TestFloorDivideAPI(unittest.TestCase): z_expected = np.array([2., 0., 2.]) self.assertEqual((z_expected == z.numpy()).all(), True) + with fluid.dygraph.guard(fluid.CPUPlace()): + # divide by zero + np_x = np.array([2, 3, 4]) + np_y = np.array([0]) + x = paddle.to_tensor(np_x) + y = paddle.to_tensor(np_y) + try: + z = x // y + except Exception as e: + print("Error: Divide by zero encounter in floor_divide\n") + + # divide by zero + np_x = np.array([2]) + np_y = np.array([0, 0, 0]) + x = paddle.to_tensor(np_x, dtype="int32") + y = paddle.to_tensor(np_y, dtype="int32") + try: + z = x // y + except Exception as e: + print("Error: Divide by zero encounter in floor_divide\n") + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_elementwise_mod_op.py b/python/paddle/fluid/tests/unittests/test_elementwise_mod_op.py index 25769a42aa2..f5d8b4f704d 100644 --- a/python/paddle/fluid/tests/unittests/test_elementwise_mod_op.py +++ b/python/paddle/fluid/tests/unittests/test_elementwise_mod_op.py @@ -204,6 +204,22 @@ class TestRemainderAPI(unittest.TestCase): z_expected = np.array([1., 0., 1., 1., 0., 1.]) self.assertEqual((z_expected == z.numpy()).all(), True) + np_x = np.array([-3.3, 11.5, -2, 3.5]) + np_y = np.array([-1.2, 2., 3.3, -2.3]) + x = paddle.to_tensor(np_x) + y = paddle.to_tensor(np_y) + z = x % y + z_expected = np.array([-0.9, 1.5, 1.3, -1.1]) + self.assertEqual(np.allclose(z_expected, z.numpy()), True) + + np_x = np.array([-3, 11, -2, 3]) + np_y = np.array([-1, 2, 3, -2]) + x = paddle.to_tensor(np_x, dtype="int64") + y = paddle.to_tensor(np_y, dtype="int64") + z = x % y + z_expected = np.array([0, 1, 1, -1]) + self.assertEqual(np.allclose(z_expected, z.numpy()), True) + if __name__ == '__main__': unittest.main() -- GitLab