chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ATen/core/Tensor.h>
|
||||
#include <c10/core/Scalar.h>
|
||||
#include <c10/util/ArrayRef.h>
|
||||
#include <c10/util/OptionalArrayRef.h>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "paddle/phi/api/include/api.h"
|
||||
#include "paddle/phi/common/int_array.h"
|
||||
#include "paddle/phi/common/scalar.h"
|
||||
|
||||
namespace at::detail {
|
||||
|
||||
// Internal implementation for std (standard deviation = sqrt(variance))
|
||||
inline Tensor _PD_std_impl(const Tensor& self,
|
||||
const std::vector<int64_t>& dims_vec,
|
||||
double correction_value,
|
||||
bool keepdim) {
|
||||
// Validate dimensions before processing
|
||||
int64_t ndim = self.dim();
|
||||
for (int64_t d : dims_vec) {
|
||||
int64_t dim_idx = d < 0 ? d + ndim : d;
|
||||
if (dim_idx < 0 || dim_idx >= ndim) {
|
||||
PD_CHECK(false,
|
||||
"Dimension out of range (expected to be in range of [",
|
||||
-ndim,
|
||||
", ",
|
||||
ndim - 1,
|
||||
"], but got ",
|
||||
d,
|
||||
")");
|
||||
}
|
||||
}
|
||||
phi::IntArray dims_int_array(dims_vec);
|
||||
paddle::Tensor tensor = self._PD_GetInner();
|
||||
|
||||
paddle::Tensor mean_tensor;
|
||||
if (dims_vec.empty()) {
|
||||
mean_tensor = paddle::experimental::mean(
|
||||
tensor, phi::IntArray(std::vector<int64_t>{}), true);
|
||||
} else {
|
||||
mean_tensor = paddle::experimental::mean(tensor, dims_int_array, true);
|
||||
}
|
||||
|
||||
paddle::Tensor diff = paddle::experimental::subtract(tensor, mean_tensor);
|
||||
paddle::Tensor diff_squared = paddle::experimental::multiply(diff, diff);
|
||||
|
||||
paddle::Tensor sum_squared_diff;
|
||||
if (dims_vec.empty()) {
|
||||
sum_squared_diff =
|
||||
paddle::experimental::sum(diff_squared,
|
||||
phi::IntArray(std::vector<int64_t>{}),
|
||||
diff_squared.dtype(),
|
||||
keepdim);
|
||||
} else {
|
||||
sum_squared_diff = paddle::experimental::sum(
|
||||
diff_squared, dims_int_array, diff_squared.dtype(), keepdim);
|
||||
}
|
||||
|
||||
int64_t n = tensor.numel();
|
||||
if (!dims_vec.empty()) {
|
||||
n = 1;
|
||||
for (int64_t d : dims_vec) {
|
||||
int64_t dim_idx = d < 0 ? d + tensor.dims().size() : d;
|
||||
if (dim_idx >= 0 &&
|
||||
dim_idx < static_cast<int64_t>(tensor.dims().size())) {
|
||||
n *= tensor.dims()[dim_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double corrected_n = static_cast<double>(n) - correction_value;
|
||||
if (corrected_n <= 0.0) {
|
||||
corrected_n = static_cast<double>(n);
|
||||
}
|
||||
|
||||
std::vector<int64_t> result_shape_vec;
|
||||
for (int64_t i = 0; i < sum_squared_diff.dims().size(); ++i) {
|
||||
result_shape_vec.push_back(sum_squared_diff.dims()[i]);
|
||||
}
|
||||
paddle::Tensor correction_scalar =
|
||||
paddle::experimental::full(phi::IntArray(result_shape_vec),
|
||||
phi::Scalar(corrected_n),
|
||||
sum_squared_diff.dtype(),
|
||||
sum_squared_diff.place());
|
||||
paddle::Tensor variance =
|
||||
paddle::experimental::divide(sum_squared_diff, correction_scalar);
|
||||
|
||||
paddle::Tensor result = paddle::experimental::sqrt(variance);
|
||||
|
||||
return Tensor(result);
|
||||
}
|
||||
|
||||
} // namespace at::detail
|
||||
|
||||
namespace at {
|
||||
|
||||
inline Tensor Tensor::std(bool unbiased) const {
|
||||
std::vector<int64_t> empty_dims;
|
||||
double correction = unbiased ? 1.0 : 0.0;
|
||||
return detail::_PD_std_impl(*this, empty_dims, correction, false);
|
||||
}
|
||||
|
||||
inline Tensor Tensor::std(at::OptionalIntArrayRef dim,
|
||||
bool unbiased,
|
||||
bool keepdim) const {
|
||||
double correction = unbiased ? 1.0 : 0.0;
|
||||
std::vector<int64_t> dims_vec;
|
||||
if (dim.has_value() && dim.value().size() > 0) {
|
||||
dims_vec.assign(dim.value().begin(), dim.value().end());
|
||||
}
|
||||
return detail::_PD_std_impl(*this, dims_vec, correction, keepdim);
|
||||
}
|
||||
|
||||
inline Tensor Tensor::std(at::OptionalIntArrayRef dim,
|
||||
const ::std::optional<at::Scalar>& correction,
|
||||
bool keepdim) const {
|
||||
double correction_value = 1.0;
|
||||
if (correction.has_value()) {
|
||||
const at::Scalar& scalar = correction.value();
|
||||
correction_value = scalar.to<double>();
|
||||
}
|
||||
std::vector<int64_t> dims_vec;
|
||||
if (dim.has_value() && dim.value().size() > 0) {
|
||||
dims_vec.assign(dim.value().begin(), dim.value().end());
|
||||
}
|
||||
return detail::_PD_std_impl(*this, dims_vec, correction_value, keepdim);
|
||||
}
|
||||
|
||||
} // namespace at
|
||||
Reference in New Issue
Block a user