// 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 "ATen/ATen.h" #include "gtest/gtest.h" #include "torch/all.h" // ======================== std tests ======================== TEST(TensorStdTest, StdDefault) { // Create tensor [1, 2, 3, 4, 5, 6] at::Tensor t = at::arange(1, 7, at::kFloat); at::Tensor result = t.std(); // std of [1,2,3,4,5,6] with unbiased=true (ddof=1) = sqrt(3.5) ASSERT_EQ(result.numel(), 1); float val = result.item(); ASSERT_NEAR(val, std::sqrt(3.5f), 1e-4); } TEST(TensorStdTest, StdBiased) { at::Tensor t = at::arange(1, 7, at::kFloat); at::Tensor result = t.std(false); // unbiased=false // std with ddof=0: sqrt(sum((x-mean)^2)/N) // mean=3.5, sum_sq_diff = 17.5, var=17.5/6, std=sqrt(17.5/6) ASSERT_EQ(result.numel(), 1); float val = result.item(); ASSERT_NEAR(val, std::sqrt(17.5f / 6.0f), 1e-4); } TEST(TensorStdTest, StdWithDim) { // Create 2x3 tensor at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.std(at::OptionalIntArrayRef({1}), /*unbiased=*/true, /*keepdim=*/false); ASSERT_EQ(result.numel(), 2); } TEST(TensorStdTest, StdWithDimAndCorrection) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.std( at::OptionalIntArrayRef({1}), ::std::optional(1.0), false); ASSERT_EQ(result.numel(), 2); } TEST(TensorStdTest, StdSingleDim) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.std(1); ASSERT_EQ(result.numel(), 2); } // ======================== var tests ======================== TEST(TensorVarTest, VarDefault) { at::Tensor t = at::arange(1, 7, at::kFloat); at::Tensor result = t.var(); // var of [1,2,3,4,5,6] with unbiased=true: 17.5/5 = 3.5 float val = result.item(); ASSERT_NEAR(val, 3.5f, 1e-4); } TEST(TensorVarTest, VarBiased) { at::Tensor t = at::arange(1, 7, at::kFloat); at::Tensor result = t.var(false); // var with unbiased=false: 17.5/6 float val = result.item(); ASSERT_NEAR(val, 17.5f / 6.0f, 1e-4); } TEST(TensorVarTest, VarWithDim) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.var(at::OptionalIntArrayRef({1}), /*unbiased=*/true, /*keepdim=*/false); ASSERT_EQ(result.numel(), 2); } TEST(TensorVarTest, VarWithCorrection) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.var( at::OptionalIntArrayRef({0}), ::std::optional(1.0), false); ASSERT_EQ(result.numel(), 3); } TEST(TensorVarTest, VarSingleDim) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.var(0); ASSERT_EQ(result.numel(), 3); } // ======================= Additional std edge case tests // ======================== TEST(TensorStdTest, StdWithKeepdim) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.std(at::OptionalIntArrayRef({1}), /*unbiased=*/true, /*keepdim=*/true); // keepdim should preserve dimension ASSERT_EQ(result.sizes().size(), 2); ASSERT_EQ(result.size(0), 2); ASSERT_EQ(result.size(1), 1); } TEST(TensorStdTest, StdWithMultipleDims) { at::Tensor t = at::arange(1, 13, at::kFloat).reshape({2, 2, 3}); at::Tensor result = t.std( at::OptionalIntArrayRef({0, 2}), /*unbiased=*/true, /*keepdim=*/false); ASSERT_EQ(result.numel(), 2); } TEST(TensorStdTest, StdWithCorrectionValue) { at::Tensor t = at::arange(1, 7, at::kFloat); // Test with custom correction value (ddof) at::Tensor result = t.std( at::OptionalIntArrayRef({}), ::std::optional(2.0), false); ASSERT_EQ(result.numel(), 1); } TEST(TensorStdTest, StdNegativeDim) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); // Test with negative dimension (-1 means last dimension) at::Tensor result = t.std(-1); ASSERT_EQ(result.numel(), 2); } TEST(TensorVarTest, VarWithKeepdim) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.var(at::OptionalIntArrayRef({1}), /*unbiased=*/true, /*keepdim=*/true); ASSERT_EQ(result.sizes().size(), 2); ASSERT_EQ(result.size(0), 2); ASSERT_EQ(result.size(1), 1); } TEST(TensorVarTest, VarWithMultipleDims) { at::Tensor t = at::arange(1, 13, at::kFloat).reshape({2, 2, 3}); at::Tensor result = t.var( at::OptionalIntArrayRef({0, 2}), /*unbiased=*/true, /*keepdim=*/false); ASSERT_EQ(result.numel(), 2); } TEST(TensorVarTest, VarWithCorrectionValue) { at::Tensor t = at::arange(1, 7, at::kFloat); at::Tensor result = t.var( at::OptionalIntArrayRef({}), ::std::optional(2.0), false); ASSERT_EQ(result.numel(), 1); } TEST(TensorVarTest, VarNegativeDim) { at::Tensor t = at::arange(1, 7, at::kFloat).reshape({2, 3}); at::Tensor result = t.var(-1); ASSERT_EQ(result.numel(), 2); }