Skip to content

Commit

Permalink
Add paddle.rad2deg and paddle.deg2rad (#37598)
Browse files Browse the repository at this point in the history
  • Loading branch information
luotao1 authored Dec 1, 2021
1 parent 661dbdb commit 8ac0344
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 2 deletions.
4 changes: 4 additions & 0 deletions python/paddle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@
from .tensor.math import digamma # noqa: F401
from .tensor.math import neg # noqa: F401
from .tensor.math import lgamma # noqa: F401
from .tensor.math import rad2deg # noqa: F401
from .tensor.math import deg2rad # noqa: F401
from .tensor.math import diff # noqa: F401

from .tensor.random import multinomial # noqa: F401
Expand Down Expand Up @@ -458,6 +460,8 @@
'ceil',
'atan',
'atan2',
'rad2deg',
'deg2rad',
'expand',
'broadcast_to',
'ones_like',
Expand Down
75 changes: 75 additions & 0 deletions python/paddle/fluid/tests/unittests/test_deg2rad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import unittest
import numpy as np
import paddle
import paddle.fluid as fluid
import paddle.fluid.core as core
from paddle.fluid import Program, program_guard
from op_test import OpTest

paddle.enable_static()


class TestDeg2radAPI(unittest.TestCase):
def setUp(self):
self.x_dtype = 'float64'
self.x_np = np.array(
[180.0, -180.0, 360.0, -360.0, 90.0, -90.0]).astype(np.float64)
self.x_shape = [6]
self.out_np = np.deg2rad(self.x_np)

def test_static_graph(self):
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(startup_program, train_program):
x = fluid.data(name='input', dtype=self.x_dtype, shape=self.x_shape)
out = paddle.deg2rad(x)

place = fluid.CUDAPlace(0) if core.is_compiled_with_cuda(
) else fluid.CPUPlace()
exe = fluid.Executor(place)
res = exe.run(fluid.default_main_program(),
feed={'input': self.x_np},
fetch_list=[out])
self.assertTrue((np.array(out[0]) == self.out_np).all())

def test_dygraph(self):
paddle.disable_static()
x1 = paddle.to_tensor([180.0, -180.0, 360.0, -360.0, 90.0, -90.0])
result1 = paddle.deg2rad(x1)
self.assertEqual(np.allclose(self.out_np, result1.numpy()), True)

paddle.enable_static()


class TestDeg2radAPI2(TestDeg2radAPI):
# Test input data type is int
def setUp(self):
self.x_np = 180
self.x_shape = [1]
self.out_np = np.pi
self.x_dtype = 'int64'

def test_dygraph(self):
paddle.disable_static()

x2 = paddle.to_tensor(180)
result2 = paddle.deg2rad(x2)
self.assertEqual(np.allclose(np.pi, result2.numpy()), True)

paddle.enable_static()
92 changes: 92 additions & 0 deletions python/paddle/fluid/tests/unittests/test_rad2deg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import unittest
import numpy as np
import paddle
import paddle.fluid as fluid
import paddle.fluid.core as core
from paddle.fluid import Program, program_guard
from op_test import OpTest

paddle.enable_static()


class TestRad2degAPI(unittest.TestCase):
def setUp(self):
self.x_dtype = 'float64'
self.x_np = np.array(
[3.142, -3.142, 6.283, -6.283, 1.570, -1.570]).astype(np.float64)
self.x_shape = [6]
self.out_np = np.rad2deg(self.x_np)

def test_static_graph(self):
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(startup_program, train_program):
x = fluid.data(name='input', dtype=self.x_dtype, shape=self.x_shape)
out = paddle.rad2deg(x)

place = fluid.CUDAPlace(0) if core.is_compiled_with_cuda(
) else fluid.CPUPlace()
exe = fluid.Executor(place)
res = exe.run(fluid.default_main_program(),
feed={'input': self.x_np},
fetch_list=[out])
self.assertTrue((np.array(out[0]) == self.out_np).all())

def test_dygraph(self):
paddle.disable_static()
x1 = paddle.to_tensor([3.142, -3.142, 6.283, -6.283, 1.570, -1.570])
result1 = paddle.rad2deg(x1)
self.assertEqual(np.allclose(self.out_np, result1.numpy()), True)

paddle.enable_static()


class TestRad2degAPI2(TestRad2degAPI):
def setUp(self):
self.x_np = np.pi / 2
self.x_shape = [1]
self.out_np = 90
self.x_dtype = 'float32'

def test_dygraph(self):
paddle.disable_static()

x2 = paddle.to_tensor(np.pi / 2)
result2 = paddle.rad2deg(x2)
self.assertEqual(np.allclose(90, result2.numpy()), True)

paddle.enable_static()


class TestRad2degAPI3(TestRad2degAPI):
# Test input data type is int
def setUp(self):
self.x_np = 1
self.x_shape = [1]
self.out_np = 180 / np.pi
self.x_dtype = 'int64'

def test_dygraph(self):
paddle.disable_static()

x2 = paddle.to_tensor(1)
result2 = paddle.rad2deg(x2)
self.assertEqual(np.allclose(180 / np.pi, result2.numpy()), True)

paddle.enable_static()
2 changes: 2 additions & 0 deletions python/paddle/tensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@
from .math import neg # noqa: F401
from .math import lgamma # noqa: F401
from .math import diagonal # noqa: F401
from .math import rad2deg # noqa: F401
from .math import deg2rad # noqa: F401
from .math import diff # noqa: F401

from .random import multinomial # noqa: F401
Expand Down
114 changes: 112 additions & 2 deletions python/paddle/tensor/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,117 @@ def atan2(x, y, name=None):
type='atan2', inputs=inputs, outputs={'Out': out})
return out

def rad2deg(x, name=None):
"""
Convert each of the elements of input x from angles in radians to degrees.
Equation:
.. math::
rad2deg(x)=180/ \pi * x
Args:
x (Tensor): An N-D Tensor, the data type is float32, float64, int32, int64.
name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Returns:
out (Tensor): An N-D Tensor, the shape and data type is the same with input (The output data type is float32 when the input data type is int).
Examples:
.. code-block:: python
import paddle
import numpy as np
x1 = paddle.to_tensor([3.142, -3.142, 6.283, -6.283, 1.570, -1.570])
result1 = paddle.rad2deg(x1)
print(result1)
# Tensor(shape=[6], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
# [180.02334595, -180.02334595, 359.98937988, -359.98937988,
# 9.95437622 , -89.95437622])
x2 = paddle.to_tensor(np.pi/2)
result2 = paddle.rad2deg(x2)
print(result2)
# Tensor(shape=[1], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
# [90.])
x3 = paddle.to_tensor(1)
result3 = paddle.rad2deg(x3)
print(result3)
# Tensor(shape=[1], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
# [57.29578018])
"""
rad2deg_scale = 180 / np.pi
if in_dygraph_mode():
if convert_dtype(x.dtype) in ['int32', 'int64']:
x = cast(x, dtype="float32")
return _C_ops.scale(x, 'scale', rad2deg_scale)
else:
check_variable_and_dtype(x, 'x', ['int32', 'int64', 'float32', 'float64'], 'rad2deg')
helper = LayerHelper('rad2deg', **locals())
out_cast = x
if convert_dtype(x.dtype) in ['int32', 'int64']:
out_cast = helper.create_variable_for_type_inference(dtype=paddle.float32)
helper.append_op(
type='cast', inputs={'X':x}, outputs={'Out': out_cast}, attrs={'in_dtype': x.dtype,'out_dtype': paddle.float32})
out = helper.create_variable_for_type_inference(dtype=out_cast.dtype)
helper.append_op(
type='scale', inputs={'X':out_cast}, outputs={'Out': out}, attrs={'scale': rad2deg_scale})
return out

def deg2rad(x, name=None):
"""
Convert each of the elements of input x from degrees to angles in radians.
Equation:
.. math::
deg2rad(x)=\pi * x / 180
Args:
x (Tensor): An N-D Tensor, the data type is float32, float64, int32, int64.
name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Returns:
out (Tensor): An N-D Tensor, the shape and data type is the same with input (The output data type is float32 when the input data type is int).
Examples:
.. code-block:: python
import paddle
import numpy as np
x1 = paddle.to_tensor([180.0, -180.0, 360.0, -360.0, 90.0, -90.0])
result1 = paddle.deg2rad(x1)
print(result1)
# Tensor(shape=[6], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
# [3.14159274, -3.14159274, 6.28318548, -6.28318548, 1.57079637,
# -1.57079637])
x2 = paddle.to_tensor(180)
result2 = paddle.deg2rad(x2)
print(result2)
# Tensor(shape=[1], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
# [3.14159274])
"""
deg2rad_scale = np.pi / 180.0
if in_dygraph_mode():
if convert_dtype(x.dtype) in ['int32', 'int64']:
x = cast(x, dtype="float32")
return _C_ops.scale(x, 'scale', deg2rad_scale)
else:
check_variable_and_dtype(x, 'x', ['int32', 'int64', 'float32', 'float64'], 'deg2rad')
helper = LayerHelper('deg2rad', **locals())
out_cast = x
if convert_dtype(x.dtype) in ['int32', 'int64']:
out_cast = helper.create_variable_for_type_inference(dtype=paddle.float32)
helper.append_op(
type='cast', inputs={'X':x}, outputs={'Out': out_cast}, attrs={'in_dtype': x.dtype,'out_dtype': paddle.float32})
out = helper.create_variable_for_type_inference(dtype=out_cast.dtype)
helper.append_op(
type='scale', inputs={'X':out_cast}, outputs={'Out': out}, attrs={'scale': deg2rad_scale})
return out

def diff(x, n=1, axis=-1, prepend=None, append=None, name=None):
r"""
Expand Down Expand Up @@ -2646,6 +2757,7 @@ def diff(x, n=1, axis=-1, prepend=None, append=None, name=None):
.. code-block:: python
import paddle
x = paddle.to_tensor([1, 4, 5, 2])
out = paddle.diff(x)
print(out)
Expand All @@ -2667,8 +2779,6 @@ def diff(x, n=1, axis=-1, prepend=None, append=None, name=None):
print(out)
# out:
# [[1, 1], [1, 1]]
"""

if axis < 0:
Expand Down

0 comments on commit 8ac0344

Please sign in to comment.