Files
paddlepaddle--paddle/test/legacy_test/test_round_op.py
T
2026-07-13 12:40:42 +08:00

355 lines
10 KiB
Python

# Copyright (c) 2025 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.
import unittest
import numpy as np
from op_test import OpTest, get_device, get_device_place, is_custom_device
from test_activation_op import TestActivation
from utils import dygraph_guard, static_guard
import paddle
from paddle import base
from paddle.base import core
devices = ['cpu', get_device()]
class TestRound(TestActivation):
def setUp(self):
self.op_type = "round"
self.python_api = paddle.round
self.init_dtype()
self.init_shape()
self.init_decimals()
np.random.seed(1024)
x = np.random.uniform(-1, 1, self.shape).astype(self.dtype) * 100
out = np.round(x, decimals=self.decimals)
self.inputs = {'X': OpTest.np_dtype_to_base_dtype(x)}
self.outputs = {'Out': out}
self.attrs = {'decimals': self.decimals}
self.convert_input_output()
def _get_places(self):
places = [base.CPUPlace()]
if core.is_compiled_with_cuda() or is_custom_device():
places.append(get_device_place())
return places
def init_shape(self):
self.shape = [10, 12]
def init_decimals(self):
self.decimals = 0
def test_check_output(self):
self.check_output(
check_pir=True,
check_pir_onednn=self.check_pir_onednn,
check_symbol_infer=False,
)
def test_check_grad(self):
pass
class TestRoundEvenTie(TestRound):
def setUp(self):
self.op_type = "round"
self.python_api = paddle.round
self.init_dtype()
self.init_shape()
self.init_decimals()
np.random.seed(1024)
x = test_array = np.array(
[[0.5, 1.5, 2.5], [-0.5, -1.5, -2.5], [1.2, -2.3, 3.0]],
dtype=np.float32,
)
out = np.round(x, decimals=self.decimals)
self.inputs = {'X': OpTest.np_dtype_to_base_dtype(x)}
self.outputs = {'Out': out}
self.attrs = {'decimals': self.decimals}
self.convert_input_output()
class TestRound_ZeroDim(TestRound):
def init_shape(self):
self.shape = []
class TestRound_decimals1(TestRound):
def init_decimals(self):
self.decimals = 2
def test_round_api(self):
with dygraph_guard():
for device in devices:
if device == 'cpu' or (
device == get_device()
and (paddle.is_compiled_with_cuda() or is_custom_device())
):
x_np = (
np.random.uniform(-1, 1, self.shape).astype(self.dtype)
* 100
)
out_expect = np.round(x_np, decimals=self.decimals)
x_paddle = paddle.to_tensor(
x_np, dtype=self.dtype, place=device
)
y = paddle.round(x_paddle, decimals=self.decimals)
np.testing.assert_allclose(y.numpy(), out_expect, rtol=1e-3)
class TestRound_decimals2(TestRound_decimals1):
def init_decimals(self):
self.decimals = -1
class TestRoundComplexOp1(TestRound):
def init_dtype(self):
self.dtype = np.complex64
def setUp(self):
super().setUp()
x_real = np.random.uniform(-1, 1, self.shape).astype(np.float32) * 100
x_imag = np.random.uniform(-1, 1, self.shape).astype(np.float32) * 100
x = x_real + 1j * x_imag
out = np.round(x, decimals=self.decimals)
self.inputs = {'X': x}
self.outputs = {'Out': out}
self.attrs = {'decimals': self.decimals}
self.convert_input_output()
class TestRoundComplexOp2(TestRoundComplexOp1):
def init_decimals(self):
self.decimals = 2
class TestRoundComplexOp3(TestRoundComplexOp1):
def init_decimals(self):
self.decimals = -1
class TestRoundComplexOp4(TestRound):
def init_dtype(self):
self.dtype = np.complex128
def setUp(self):
super().setUp()
x_real = np.random.uniform(-1, 1, self.shape).astype(np.float64) * 100
x_imag = np.random.uniform(-1, 1, self.shape).astype(np.float64) * 100
x = x_real + 1j * x_imag
out = np.round(x, decimals=self.decimals)
self.inputs = {'X': x}
self.outputs = {'Out': out}
self.attrs = {'decimals': self.decimals}
self.convert_input_output()
class TestRoundComplexOp5(TestRoundComplexOp4):
def init_decimals(self):
self.decimals = 2
class TestRoundComplexOp6(TestRoundComplexOp4):
def init_decimals(self):
self.decimals = -1
class TestRoundComplexOp7(TestRoundComplexOp4):
def init_decimals(self):
self.decimals = -4
class TestRoundComplexOp8(TestRoundComplexOp4):
def init_decimals(self):
self.decimals = 4
class TestRoundComplexOp9(TestRoundComplexOp4):
def init_decimals(self):
self.decimals = 3
class TestRoundComplexOp10(TestRoundComplexOp4):
def init_decimals(self):
self.decimals = -3
class TestRoundInt32(TestRound):
def init_dtype(self):
self.dtype = np.int32
def setUp(self):
super().setUp()
x = np.random.randint(-100, 100, self.shape).astype(self.dtype)
out = np.round(x, decimals=self.decimals)
self.inputs = {'X': x}
self.outputs = {'Out': out}
self.attrs = {'decimals': self.decimals}
self.convert_input_output()
class TestRoundInt64(TestRound):
def init_dtype(self):
self.dtype = np.int64
def setUp(self):
super().setUp()
x = np.random.randint(-100, 100, self.shape).astype(self.dtype)
out = np.round(x, decimals=self.decimals)
self.inputs = {'X': x}
self.outputs = {'Out': out}
self.attrs = {'decimals': self.decimals}
self.convert_input_output()
class TestRoundComplex_ZeroDim(TestRoundComplexOp1):
def init_shape(self):
self.shape = []
class TestRoundInt_ZeroDim(TestRoundInt32):
def init_shape(self):
self.shape = []
class TestRoundInf(TestRound):
def setUp(self):
self.op_type = "round"
self.python_api = paddle.round
self.init_dtype()
self.init_shape()
self.init_decimals()
x = np.array(
[
np.inf,
-np.inf,
*(
np.random.uniform(-1, 1, self.shape).astype(self.dtype)
* 100
),
]
)
out = np.round(x, decimals=self.decimals)
self.inputs = {'X': OpTest.np_dtype_to_base_dtype(x)}
self.outputs = {'Out': out}
self.attrs = {'decimals': self.decimals}
self.convert_input_output()
def init_shape(self):
self.shape = [10]
def init_decimals(self):
self.decimals = 0
def test_check_output(self):
self.check_output(
check_pir=True,
check_pir_onednn=self.check_pir_onednn,
check_symbol_infer=False,
)
class TestRoundNaN(unittest.TestCase):
def setUp(self):
self.op_type = "round"
self.python_api = paddle.round
self.init_dtype()
self.init_shape()
self.init_decimals()
self.x = np.array(
[
np.nan,
-np.nan,
*(
np.random.uniform(-1, 1, self.shape).astype(self.dtype)
* 100
),
]
)
self.out = np.round(self.x, decimals=self.decimals)
def init_dtype(self):
self.dtype = 'float64'
def init_shape(self):
self.shape = [10]
def init_decimals(self):
self.decimals = 0
def test_round_nan(self):
with static_guard():
places = [core.CPUPlace()]
if core.is_compiled_with_cuda() or is_custom_device():
places.append(get_device_place())
for place in places:
with paddle.static.program_guard(paddle.static.Program()):
input = paddle.static.data(
name="input", shape=self.x.shape, dtype=self.x.dtype
)
output = self.python_api(input, decimals=self.decimals)
exe = paddle.static.Executor(place)
(result,) = exe.run(
feed={'input': self.x}, fetch_list=[output]
)
nan_mask = np.isnan(self.out)
np.testing.assert_array_equal(
result[nan_mask], self.out[nan_mask]
)
np.testing.assert_array_equal(
result[~nan_mask], self.out[~nan_mask]
)
class TestRoundAPI(unittest.TestCase):
def setUp(self):
np.random.seed(1024)
self.x_np = np.random.uniform(-5, 5, [10, 12]).astype(np.float64)
self.place = get_device_place()
def test_dygraph_api(self):
with dygraph_guard():
x = paddle.to_tensor(self.x_np)
out = paddle.round(x)
out_ref = np.round(self.x_np)
np.testing.assert_allclose(out_ref, out.numpy(), rtol=1e-05)
def test_static_api(self):
with static_guard():
with base.program_guard(base.Program()):
x = paddle.static.data('X', self.x_np.shape, self.x_np.dtype)
out = paddle.round(x)
exe = base.Executor(self.place)
res = exe.run(feed={'X': self.x_np}, fetch_list=[out])
out_ref = np.round(self.x_np)
np.testing.assert_allclose(out_ref, res[0], rtol=1e-05)
if __name__ == "__main__":
unittest.main()