// Copyright (c) 2026 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. #include #include #include #include #include #include #include #include #include #include #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) #include #include #endif #include "ATen/ATen.h" #include "gtest/gtest.h" #include "paddle/phi/common/float16.h" #include "torch/all.h" // ============================================================ // Tests for at::detail::tensor_cpu / tensor_backend / complex variants // and the at::tensor() factory macro-generated overloads (ATen/Utils.h) // ============================================================ // ---- tensor_cpu (via at::tensor public API) ---- TEST(ATenUtilsTest, TensorCPU_Float) { std::vector data = {1.0f, 2.0f, 3.0f}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kFloat)); ASSERT_EQ(t.scalar_type(), at::kFloat); ASSERT_EQ(t.numel(), 3); ASSERT_NEAR(t[0].item(), 1.0f, 1e-6f); ASSERT_NEAR(t[2].item(), 3.0f, 1e-6f); } TEST(ATenUtilsTest, TensorCPU_Double) { std::vector data = {1.1, 2.2, 3.3}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kDouble)); ASSERT_EQ(t.scalar_type(), at::kDouble); ASSERT_NEAR(t[1].item(), 2.2, 1e-10); } TEST(ATenUtilsTest, TensorCPU_Int32) { std::vector data = {10, 20, 30}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kInt)); ASSERT_EQ(t.scalar_type(), at::kInt); ASSERT_EQ(t[0].item(), 10); ASSERT_EQ(t[2].item(), 30); } TEST(ATenUtilsTest, TensorCPU_Int64) { std::vector data = {100LL, 200LL}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kLong)); ASSERT_EQ(t.scalar_type(), at::kLong); ASSERT_EQ(t[1].item(), 200LL); } TEST(ATenUtilsTest, TensorCPU_Int8) { std::vector data = {-1, 0, 1}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kChar)); ASSERT_EQ(t.scalar_type(), at::kChar); ASSERT_EQ(t[0].item(), static_cast(-1)); } TEST(ATenUtilsTest, TensorCPU_Int16) { std::vector data = {256, 512}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kShort)); ASSERT_EQ(t.scalar_type(), at::kShort); ASSERT_EQ(t[0].item(), static_cast(256)); } TEST(ATenUtilsTest, TensorCPU_UInt8) { std::vector data = {200, 255}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kByte)); ASSERT_EQ(t.scalar_type(), at::kByte); ASSERT_EQ(t[1].item(), static_cast(255)); } TEST(ATenUtilsTest, TensorCPU_Bool) { // std::vector is a bitfield specialization without data(), so use a // plain C array to construct c10::ArrayRef. bool data[] = {true, false, true}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kBool)); ASSERT_EQ(t.scalar_type(), at::kBool); ASSERT_TRUE(t[0].item()); ASSERT_FALSE(t[1].item()); } // ---- dtype promotion: values stored as native type then cast ---- TEST(ATenUtilsTest, TensorCPU_DtypePromotion_IntToFloat) { // Store int32 values, but request float32 output – should auto-cast. std::vector data = {1, 2, 3}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kFloat)); ASSERT_EQ(t.scalar_type(), at::kFloat); ASSERT_NEAR(t[0].item(), 1.0f, 1e-6f); } // ---- contiguity ---- TEST(ATenUtilsTest, TensorCPU_IsContiguous) { std::vector data = {1.0f, 2.0f, 3.0f, 4.0f}; at::Tensor t = at::tensor(c10::ArrayRef(data), at::TensorOptions().dtype(at::kFloat)); ASSERT_TRUE(t.is_contiguous()); } // ---- tensor_backend (CPU -> same result since default is CPU in tests) ---- TEST(ATenUtilsTest, TensorBackend_CPUDevice_MatchesTensorCPU) { std::vector data = {5.0f, 6.0f}; at::TensorOptions opts = at::TensorOptions().dtype(at::kFloat).device(c10::Device(c10::kCPU)); at::Tensor t = at::tensor(c10::ArrayRef(data), opts); ASSERT_EQ(t.scalar_type(), at::kFloat); ASSERT_EQ(t.device().type(), c10::DeviceType::CPU); ASSERT_NEAR(t[0].item(), 5.0f, 1e-6f); } #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) TEST(ATenUtilsTest, TensorBackend_GPUDevice) { if (!at::cuda::is_available()) { return; } std::vector data = {7.0f, 8.0f}; at::TensorOptions opts = at::TensorOptions().dtype(at::kFloat).device(c10::Device(c10::kCUDA, 0)); at::Tensor t = at::tensor(c10::ArrayRef(data), opts); ASSERT_EQ(t.scalar_type(), at::kFloat); ASSERT_EQ(t.device().type(), c10::DeviceType::CUDA); } TEST(ATenUtilsTest, TensorComplexBackend_GPUDevice) { if (!at::cuda::is_available()) { return; } std::vector> data = {{1.0f, 0.0f}}; at::TensorOptions opts = at::TensorOptions() .dtype(at::kComplexFloat) .device(c10::Device(c10::kCUDA, 0)); at::Tensor t = at::tensor(c10::ArrayRef>(data), opts); ASSERT_EQ(t.scalar_type(), at::kComplexFloat); ASSERT_EQ(t.device().type(), c10::DeviceType::CUDA); } #endif