355 lines
10 KiB
Python
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()
|