* Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "aclnn_repeat_interleave.h"
#include "level0/arange.h"
#include "level0/broadcast_to.h"
#include "aclnn_kernels/cast.h"
#include "aclnn_kernels/contiguous.h"
#include "repeat_interleave.h"
#include "aclnn_kernels/reshape.h"
#include "aclnn_kernels/transpose.h"
#include "aclnn_kernels/common/op_error_check.h"
#include "op_api/op_api_def.h"
#include "op_api/aclnn_util.h"
#include "opdev/op_dfx.h"
#include "opdev/op_executor.h"
using namespace op;
#ifdef __cplusplus
extern "C" {
#endif
static const std::initializer_list<op::DataType> ASCEND_DTYPE_SUPPORT_LIST = {
op::DataType::DT_UINT8, op::DataType::DT_INT8, op::DataType::DT_INT16, op::DataType::DT_INT32,
op::DataType::DT_INT64, op::DataType::DT_BOOL, op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT};
static const std::initializer_list<op::DataType> ASCEND950_DTYPE_SUPPORT_LIST_SELF = {
op::DataType::DT_UINT8, op::DataType::DT_INT8, op::DataType::DT_INT16, op::DataType::DT_INT32,
op::DataType::DT_INT64, op::DataType::DT_BOOL, op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT,
op::DataType::DT_BF16, op::DataType::DT_UINT16, op::DataType::DT_UINT32, op::DataType::DT_UINT64};
static const std::initializer_list<op::DataType> ASCEND910B_DTYPE_SUPPORT_LIST = {
op::DataType::DT_UINT8, op::DataType::DT_INT8, op::DataType::DT_INT16,
op::DataType::DT_INT32, op::DataType::DT_INT64, op::DataType::DT_BOOL,
op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_BF16};
static const std::initializer_list<DataType> GetDtypeSupportList()
{
if (Ops::NN::AclnnUtil::IsRegbase()) {
return ASCEND950_DTYPE_SUPPORT_LIST_SELF;
}
if (GetCurrentPlatformInfo().GetSocVersion() >= SocVersion::ASCEND910B &&
GetCurrentPlatformInfo().GetSocVersion() <= SocVersion::ASCEND910E) {
return ASCEND910B_DTYPE_SUPPORT_LIST;
}
return ASCEND_DTYPE_SUPPORT_LIST;
}
static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LIST_REPEATS = {op::DataType::DT_INT64};
static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LIST_REPEATS_TENSOR = {op::DataType::DT_INT64,
op::DataType::DT_INT32};
static const std::string STR_SELF = "self";
static const std::string STR_REPEATS = "repeats";
static const std::string STR_OUT = "out";
static const int64_t INT32_MAX_NUM = 2147483647;
static const int64_t MTE_NUM = 256;
static const std::initializer_list<op::DataType> AICORE910B_DTYPE_SUPPORT_LIST = {
op::DataType::DT_INT16, op::DataType::DT_INT32, op::DataType::DT_INT64,
op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_BF16};
static const std::initializer_list<op::DataType> BIG_SHAPE_DTYPE_SUPPORT_LIST = {
op::DataType::DT_INT16, op::DataType::DT_INT32, op::DataType::DT_INT64,
op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_BF16,
op::DataType::DT_INT8, op::DataType::DT_UINT8, op::DataType::DT_BOOL};
static bool IsRepeatInterleaveV2Support(const aclTensor* x, const aclTensor* repeats, int64_t axis, int64_t outputSize)
{
if (GetCurrentPlatformInfo().GetCurNpuArch() != NpuArch::DAV_2201) {
return false;
}
auto xViewShape = x->GetViewShape();
auto xDataType = x->GetDataType();
int64_t xDimNum = xViewShape.GetDimNum();
for (int64_t i = 0; i < xDimNum; i++) {
if (xViewShape[i] > INT32_MAX_NUM && op::CheckType(xDataType, BIG_SHAPE_DTYPE_SUPPORT_LIST)) {
return true;
}
}
if (outputSize >= INT32_MAX_NUM) {
return false;
}
if (xDimNum == 1 && repeats->GetViewShape().GetDimNum() == 1 &&
repeats->GetViewShape().GetDim(0) == x->GetViewShape().GetDim(0)) {
if (x->GetDataType() != op::DataType::DT_INT64) {
return false;
}
}
if (xDimNum == 0) {
return false;
}
auto xDimSize = x->GetViewShape().GetDimNum();
axis = axis >= 0 ? axis : axis + xDimSize;
int64_t rows = 1;
for (int64_t i = 0; i < axis; i++) {
rows *= (x->GetViewShape())[i];
}
if (rows * outputSize < MTE_NUM) {
return false;
}
return op::CheckType(x->GetDataType(), AICORE910B_DTYPE_SUPPORT_LIST);
}
static inline int64_t GetTensorDimNum(const aclTensor* self) { return (int64_t)(self->GetViewShape().GetDimNum()); }
static inline int64_t WrapDim(int64_t dim, int64_t dimNum) { return (dim < 0) ? dim + dimNum : dim; }
static inline int64_t GetTensorElementsNum(const aclTensor* self)
{
int64_t selfSize = 1;
op::Shape selfShape = self->GetViewShape();
size_t selfDimNum = selfShape.GetDimNum();
for (size_t idx = 0; idx < selfDimNum; idx++) {
selfSize *= selfShape.GetDim(idx);
}
return selfSize;
}
static inline const aclIntArray* GetFlattenShape(const aclTensor* self, aclOpExecutor* executor)
{
int64_t valuePerm[1] = {GetTensorElementsNum(self)};
auto reshapePerm = executor->AllocIntArray(valuePerm, 1);
return reshapePerm;
}
static bool CheckIntRepeatsRange(int64_t repeats)
{
if (repeats < 0) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID, "repeats %ld can not be negative.", repeats);
return false;
}
return true;
}
static inline bool CheckRepeatsDimRange(const aclTensor* repeats)
{
OP_CHECK_MAX_DIM(repeats, 1, return false);
return true;
}
static bool CheckDimRange(const aclTensor* self, int64_t dim)
{
auto selfDim = GetTensorDimNum(self);
if (selfDim == 0) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID, "dimension specified as %ld but tensor has no dimensions.", dim);
return false;
}
auto dimMin = std::min(selfDim - 1, -selfDim);
auto dimMax = std::max(selfDim - 1, -selfDim);
if (dim > dimMax || dim < dimMin) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Dimension out of range (expected to be in range of [%ld, %ld], but got %ld).",
dimMin, dimMax, dim);
return false;
}
return true;
}
static inline bool CheckTensorDimSize(const aclTensor* self)
{
OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false);
return true;
}
static bool CheckRepeatsSizeDim(const aclTensor* self, const aclTensor* repeats, int64_t dim)
{
int64_t repeatDim = GetTensorDimNum(repeats);
if (repeatDim == 0) {
return true;
}
int64_t selfDimNum = GetTensorDimNum(self);
int64_t dimPositive = WrapDim(dim, selfDimNum);
auto selfSize = (self->GetViewShape())[dimPositive];
int64_t repeatSize = (repeats->GetViewShape())[0];
if (repeatSize != selfSize && repeatSize != 1) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID,
"Tensor repeats must be size 1 or have the same size %ld as input along dim, but got %ld.", selfSize,
repeatSize);
return false;
}
return true;
}
static bool CheckRepeatsSize(const aclTensor* self, const aclTensor* repeats)
{
int64_t repeatDim = GetTensorDimNum(repeats);
if (repeatDim == 0) {
return true;
}
int64_t selfElementsNum = GetTensorElementsNum(self);
int64_t repeatSize = (repeats->GetViewShape())[0];
if (repeatSize != selfElementsNum && repeatSize != 1) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID,
"Tensor repeats size %ld must be 1 or the number of elements in tensor self %ld.", repeatSize,
selfElementsNum);
return false;
}
return true;
}
static bool CheckEmptyTensor(const aclTensor* self, const aclTensor* repeats)
{
if (self->IsEmpty()) {
if (repeats->IsEmpty()) {
return true;
}
int64_t repeatDimNum = GetTensorDimNum(repeats);
if (repeatDimNum == 0) {
return true;
} else if (repeatDimNum == 1 && GetTensorElementsNum(repeats) == 1) {
return true;
}
OP_LOGE(ACLNN_ERR_PARAM_INVALID, "When tensor self is empty, repeats should be empty / 0 dim tensor / 1 dim \
tensor with only 1 elements, but got shape %s.",
op::ToString(repeats->GetViewShape()).GetString());
return false;
}
return true;
}
static bool CheckRepeatresOutShape(const aclTensor* repeatRes, aclTensor* out)
{
OP_CHECK_SHAPE_NOT_EQUAL(repeatRes, out, return false);
return true;
}
static aclIntArray* getBaseShape(aclOpExecutor* executor)
{
int64_t tensorShape[1] = {};
tensorShape[0] = 1;
auto res = executor->AllocIntArray(tensorShape, 1);
return res;
}
static const aclTensor* InitializeTensor(const aclTensor* x, aclOpExecutor* executor)
{
auto xContiguous = l0op::Contiguous(x, executor);
if (GetTensorDimNum(xContiguous) == 0) {
auto baseShape = getBaseShape(executor);
xContiguous = l0op::BroadcastTo(xContiguous, baseShape, executor);
}
return xContiguous;
}
static const aclTensor* IntToTensor(int64_t repeats, aclOpExecutor* executor)
{
if (!Ops::NN::AclnnUtil::IsRegbase()) {
auto repeatsScalar = executor->AllocScalar(repeats);
auto repeatsTensor = executor->ConvertToTensor(repeatsScalar, op::DataType::DT_INT64);
auto baseShape = getBaseShape(executor);
repeatsTensor = l0op::BroadcastTo(repeatsTensor, baseShape, executor);
return repeatsTensor;
}
FVector<int64_t> tmpVector = {static_cast<int64_t>(repeats)};
auto repeatsTensor = executor->ConvertToTensor(tmpVector.data(), tmpVector.size(), op::DataType::DT_INT64);
return repeatsTensor;
}
static aclnnStatus CheckParams(const aclTensor* self, const aclTensor* repeats, const aclTensor* out)
{
OP_CHECK_NULL(self, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_NULL(repeats, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_NULL(out, return ACLNN_ERR_PARAM_NULLPTR);
auto inputDtypeSupportList = GetDtypeSupportList();
OP_CHECK_DTYPE_NOT_SUPPORT(self, inputDtypeSupportList, return ACLNN_ERR_PARAM_INVALID);
OP_CHECK_DTYPE_NOT_SUPPORT(repeats, DTYPE_SUPPORT_LIST_REPEATS_TENSOR, return ACLNN_ERR_PARAM_INVALID);
OP_CHECK_DTYPE_NOT_MATCH(out, self->GetDataType(), return ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckRepeatsDimRange(repeats), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckRepeatsSize(self, repeats), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckTensorDimSize(self), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckEmptyTensor(self, repeats), ACLNN_ERR_PARAM_INVALID);
return ACLNN_SUCCESS;
}
static aclnnStatus CheckParamsDim(const aclTensor* self, const aclTensor* repeats, int64_t dim, const aclTensor* out)
{
OP_CHECK_NULL(self, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_NULL(repeats, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_NULL(out, return ACLNN_ERR_PARAM_NULLPTR);
auto inputDtypeSupportList = GetDtypeSupportList();
OP_CHECK_DTYPE_NOT_SUPPORT(self, inputDtypeSupportList, return ACLNN_ERR_PARAM_INVALID);
OP_CHECK_DTYPE_NOT_SUPPORT(repeats, DTYPE_SUPPORT_LIST_REPEATS_TENSOR, return ACLNN_ERR_PARAM_INVALID);
OP_CHECK_DTYPE_NOT_MATCH(out, self->GetDataType(), return ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckRepeatsDimRange(repeats), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckDimRange(self, dim), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckRepeatsSizeDim(self, repeats, dim), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckTensorDimSize(self), ACLNN_ERR_PARAM_INVALID);
return ACLNN_SUCCESS;
}
static aclnnStatus CheckParamsInt(const aclTensor* self, int64_t repeats, const aclTensor* out)
{
OP_CHECK_NULL(self, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_NULL(out, return ACLNN_ERR_PARAM_NULLPTR);
auto inputDtypeSupportList = GetDtypeSupportList();
OP_CHECK_DTYPE_NOT_SUPPORT(self, inputDtypeSupportList, return ACLNN_ERR_PARAM_INVALID);
OP_CHECK_DTYPE_NOT_MATCH(out, self->GetDataType(), return ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckIntRepeatsRange(repeats), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckTensorDimSize(self), ACLNN_ERR_PARAM_INVALID);
return ACLNN_SUCCESS;
}
static aclnnStatus CheckParamsDimInt(const aclTensor* self, int64_t repeats, int64_t dim, const aclTensor* out)
{
OP_CHECK_NULL(self, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_NULL(out, return ACLNN_ERR_PARAM_NULLPTR);
auto inputDtypeSupportList = GetDtypeSupportList();
OP_CHECK_DTYPE_NOT_SUPPORT(self, inputDtypeSupportList, return ACLNN_ERR_PARAM_INVALID);
OP_CHECK_DTYPE_NOT_MATCH(out, self->GetDataType(), return ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckIntRepeatsRange(repeats), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckDimRange(self, dim), ACLNN_ERR_PARAM_INVALID);
CHECK_RET(CheckTensorDimSize(self), ACLNN_ERR_PARAM_INVALID);
return ACLNN_SUCCESS;
}
static aclnnStatus CheckParamsTensor(const aclTensor* repeats, const aclTensor* out)
{
OP_CHECK_NULL(repeats, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_NULL(out, return ACLNN_ERR_PARAM_NULLPTR);
OP_CHECK_DTYPE_NOT_SUPPORT(repeats, DTYPE_SUPPORT_LIST_REPEATS_TENSOR, return ACLNN_ERR_PARAM_INVALID);
OP_CHECK_DTYPE_NOT_MATCH(out, repeats->GetDataType(), return ACLNN_ERR_PARAM_INVALID);
bool repeatsIsEmpty = repeats->IsEmpty();
bool repeatsIs1D = GetTensorDimNum(repeats) == 1;
if (!(repeatsIsEmpty || repeatsIs1D)) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID, "repeats must be an empty tensor / 1D tensor.");
return ACLNN_ERR_PARAM_INVALID;
}
return ACLNN_SUCCESS;
}
static const aclTensor* CastIfNeeded(const aclTensor* x, bool needCast, op::DataType dtype, aclOpExecutor* executor)
{
if (needCast) {
x = l0op::Cast(x, dtype, executor);
if (x == nullptr) {
OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "After cast, x is nullptr.");
}
}
return x;
}
aclnnStatus aclnnRepeatInterleaveGetWorkspaceSize(const aclTensor* self, const aclTensor* repeats, int64_t outputSize,
aclTensor* out, uint64_t* workspaceSize, aclOpExecutor** executor)
{
OP_CHECK_COMM_INPUT(workspaceSize, executor);
L2_DFX_PHASE_1(aclnnRepeatInterleave, DFX_IN(self, repeats, outputSize), DFX_OUT(out));
auto uniqueExecutor = CREATE_EXECUTOR();
CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
auto ret = CheckParams(self, repeats, out);
CHECK_RET(ret == ACLNN_SUCCESS, ret);
if (self->IsEmpty() || out->IsEmpty()) {
*workspaceSize = 0;
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
if (repeats->IsEmpty()) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID, "repeats must have the same size as input along dim.");
return ACLNN_ERR_PARAM_INVALID;
}
auto selfContiguous = InitializeTensor(self, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatsContiguous = InitializeTensor(repeats, uniqueExecutor.get());
CHECK_RET(repeatsContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
if (outputSize == GetTensorElementsNum(selfContiguous) && GetTensorElementsNum(repeatsContiguous) == 1) {
auto flattenShape = GetFlattenShape(selfContiguous, uniqueExecutor.get());
auto flattenSelf = l0op::Reshape(selfContiguous, flattenShape, uniqueExecutor.get());
CHECK_RET(flattenSelf != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto viewcopyResult = l0op::ViewCopy(flattenSelf, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
bool needCast = selfContiguous->GetDataType() == op::DataType::DT_BOOL;
selfContiguous = CastIfNeeded(selfContiguous, needCast, op::DataType::DT_INT8, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto flattenShape = GetFlattenShape(selfContiguous, uniqueExecutor.get());
auto flattenSelf = l0op::Reshape(selfContiguous, flattenShape, uniqueExecutor.get());
CHECK_RET(flattenSelf != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatInterleaveOut = l0op::RepeatInterleave(flattenSelf, repeatsContiguous, 0, outputSize,
uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
CHECK_RET(CheckRepeatresOutShape(repeatInterleaveOut, out), ACLNN_ERR_PARAM_INVALID);
repeatInterleaveOut = CastIfNeeded(repeatInterleaveOut, needCast, op::DataType::DT_BOOL, uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto viewcopyResult = l0op::ViewCopy(repeatInterleaveOut, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
aclnnStatus aclnnRepeatInterleaveWithDimGetWorkspaceSize(const aclTensor* self, const aclTensor* repeats, int64_t dim,
int64_t outputSize, aclTensor* out, uint64_t* workspaceSize,
aclOpExecutor** executor)
{
OP_CHECK_COMM_INPUT(workspaceSize, executor);
L2_DFX_PHASE_1(aclnnRepeatInterleaveWithDim, DFX_IN(self, repeats, dim, outputSize), DFX_OUT(out));
auto uniqueExecutor = CREATE_EXECUTOR();
CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
auto ret = CheckParamsDim(self, repeats, dim, out);
CHECK_RET(ret == ACLNN_SUCCESS, ret);
if (self->IsEmpty() || outputSize == 0) {
*workspaceSize = 0;
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
if (repeats->IsEmpty()) {
OP_LOGE(ACLNN_ERR_PARAM_INVALID, "repeats must have the same size as input along dim.");
return ACLNN_ERR_PARAM_INVALID;
}
auto selfContiguous = InitializeTensor(self, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatsContiguous = InitializeTensor(repeats, uniqueExecutor.get());
CHECK_RET(repeatsContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
bool needCast = selfContiguous->GetDataType() == op::DataType::DT_BOOL;
selfContiguous = CastIfNeeded(selfContiguous, needCast, op::DataType::DT_INT8, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
int64_t selfDimNum = GetTensorDimNum(self);
dim = WrapDim(dim, selfDimNum);
const aclTensor* repeatInterleaveOut = nullptr;
if (IsRepeatInterleaveV2Support(selfContiguous, repeatsContiguous, dim, outputSize)) {
repeatInterleaveOut = l0op::RepeatInterleaveV2(selfContiguous, repeatsContiguous, dim, outputSize,
uniqueExecutor.get());
} else {
repeatInterleaveOut = l0op::RepeatInterleave(selfContiguous, repeatsContiguous, dim, outputSize,
uniqueExecutor.get());
}
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
CHECK_RET(CheckRepeatresOutShape(repeatInterleaveOut, out), ACLNN_ERR_PARAM_INVALID);
repeatInterleaveOut = CastIfNeeded(repeatInterleaveOut, needCast, op::DataType::DT_BOOL, uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto viewcopyResult = l0op::ViewCopy(repeatInterleaveOut, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
aclnnStatus aclnnRepeatInterleaveIntGetWorkspaceSize(const aclTensor* self, int64_t repeats, int64_t outputSize,
aclTensor* out, uint64_t* workspaceSize, aclOpExecutor** executor)
{
OP_CHECK_COMM_INPUT(workspaceSize, executor);
L2_DFX_PHASE_1(aclnnRepeatInterleaveInt, DFX_IN(self, repeats, outputSize), DFX_OUT(out));
auto uniqueExecutor = CREATE_EXECUTOR();
CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
auto ret = CheckParamsInt(self, repeats, out);
CHECK_RET(ret == ACLNN_SUCCESS, ret);
if (self->IsEmpty() || out->IsEmpty()) {
*workspaceSize = 0;
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
if (repeats == 1) {
auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto flattenShape = GetFlattenShape(selfContiguous, uniqueExecutor.get());
auto flattenSelf = l0op::Reshape(selfContiguous, flattenShape, uniqueExecutor.get());
CHECK_RET(flattenSelf != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto viewcopyResult = l0op::ViewCopy(flattenSelf, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
auto selfContiguous = InitializeTensor(self, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatsTensor = IntToTensor(repeats, uniqueExecutor.get());
CHECK_RET(repeatsTensor != nullptr, ACLNN_ERR_INNER_NULLPTR);
bool needCast = selfContiguous->GetDataType() == op::DataType::DT_BOOL;
selfContiguous = CastIfNeeded(selfContiguous, needCast, op::DataType::DT_INT8, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto flattenShape = GetFlattenShape(selfContiguous, uniqueExecutor.get());
auto flattenSelf = l0op::Reshape(selfContiguous, flattenShape, uniqueExecutor.get());
CHECK_RET(flattenSelf != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatInterleaveOut = l0op::RepeatInterleave(flattenSelf, repeatsTensor, 0, outputSize, uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
CHECK_RET(CheckRepeatresOutShape(repeatInterleaveOut, out), ACLNN_ERR_PARAM_INVALID);
repeatInterleaveOut = CastIfNeeded(repeatInterleaveOut, needCast, op::DataType::DT_BOOL, uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto viewcopyResult = l0op::ViewCopy(repeatInterleaveOut, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
aclnnStatus aclnnRepeatInterleaveIntWithDimGetWorkspaceSize(const aclTensor* self, int64_t repeats, int64_t dim,
int64_t outputSize, aclTensor* out, uint64_t* workspaceSize,
aclOpExecutor** executor)
{
OP_CHECK_COMM_INPUT(workspaceSize, executor);
L2_DFX_PHASE_1(aclnnRepeatInterleaveIntWithDim, DFX_IN(self, repeats, dim, outputSize), DFX_OUT(out));
auto uniqueExecutor = CREATE_EXECUTOR();
CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
auto ret = CheckParamsDimInt(self, repeats, dim, out);
CHECK_RET(ret == ACLNN_SUCCESS, ret);
if (self->IsEmpty() || outputSize == 0) {
*workspaceSize = 0;
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
if (repeats == 1) {
auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get());
auto viewcopyResult = l0op::ViewCopy(selfContiguous, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
auto selfContiguous = InitializeTensor(self, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatsTensor = IntToTensor(repeats, uniqueExecutor.get());
CHECK_RET(repeatsTensor != nullptr, ACLNN_ERR_INNER_NULLPTR);
bool needCast = selfContiguous->GetDataType() == op::DataType::DT_BOOL;
selfContiguous = CastIfNeeded(selfContiguous, needCast, op::DataType::DT_INT8, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
int64_t selfDimNum = GetTensorDimNum(self);
dim = WrapDim(dim, selfDimNum);
const aclTensor* repeatInterleaveOut = nullptr;
if (IsRepeatInterleaveV2Support(selfContiguous, repeatsTensor, dim, outputSize)) {
repeatInterleaveOut = l0op::RepeatInterleaveV2(selfContiguous, repeatsTensor, dim, outputSize,
uniqueExecutor.get());
} else {
repeatInterleaveOut = l0op::RepeatInterleave(selfContiguous, repeatsTensor, dim, outputSize,
uniqueExecutor.get());
}
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
CHECK_RET(CheckRepeatresOutShape(repeatInterleaveOut, out), ACLNN_ERR_PARAM_INVALID);
repeatInterleaveOut = CastIfNeeded(repeatInterleaveOut, needCast, op::DataType::DT_BOOL, uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto viewcopyResult = l0op::ViewCopy(repeatInterleaveOut, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
aclnnStatus aclnnRepeatInterleaveTensorGetWorkspaceSize(const aclTensor* repeats, int64_t outputSize, aclTensor* out,
uint64_t* workspaceSize, aclOpExecutor** executor)
{
OP_CHECK_COMM_INPUT(workspaceSize, executor);
L2_DFX_PHASE_1(aclnnRepeatInterleaveTensor, DFX_IN(repeats, outputSize), DFX_OUT(out));
auto uniqueExecutor = CREATE_EXECUTOR();
CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
auto ret = CheckParamsTensor(repeats, out);
CHECK_RET(ret == ACLNN_SUCCESS, ret);
if (repeats->IsEmpty() || out->IsEmpty()) {
*workspaceSize = 0;
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
int64_t repeatsSize = GetTensorElementsNum(repeats);
op::Shape selfShape = {repeatsSize};
const aclTensor* self = (uniqueExecutor)->AllocTensor(selfShape, repeats->GetDataType());
auto start = (uniqueExecutor)->AllocScalar(0);
auto end = (uniqueExecutor)->AllocScalar(repeatsSize);
auto step = (uniqueExecutor)->AllocScalar(1);
auto selfContiguous = l0op::Arange(start, end, step, self, false, uniqueExecutor.get());
CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatsContiguous = InitializeTensor(repeats, uniqueExecutor.get());
CHECK_RET(repeatsContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
bool needCastInt32 = repeats->GetDataType() == op::DataType::DT_INT32;
repeatsContiguous = CastIfNeeded(repeatsContiguous, needCastInt32, op::DataType::DT_INT64, uniqueExecutor.get());
CHECK_RET(repeatsContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto repeatInterleaveOut = l0op::RepeatInterleave(selfContiguous, repeatsContiguous, 0, outputSize,
uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
CHECK_RET(CheckRepeatresOutShape(repeatInterleaveOut, out), ACLNN_ERR_PARAM_INVALID);
repeatInterleaveOut = CastIfNeeded(repeatInterleaveOut, needCastInt32, op::DataType::DT_INT32,
uniqueExecutor.get());
CHECK_RET(repeatInterleaveOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto viewcopyResult = l0op::ViewCopy(repeatInterleaveOut, out, uniqueExecutor.get());
CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
*workspaceSize = uniqueExecutor->GetWorkspaceSize();
uniqueExecutor.ReleaseTo(executor);
return ACLNN_SUCCESS;
}
aclnnStatus aclnnRepeatInterleave(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream)
{
L2_DFX_PHASE_2(aclnnRepeatInterleave);
return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
}
aclnnStatus aclnnRepeatInterleaveWithDim(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
aclrtStream stream)
{
L2_DFX_PHASE_2(aclnnRepeatInterleaveWithDim);
return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
}
aclnnStatus aclnnRepeatInterleaveInt(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
aclrtStream stream)
{
L2_DFX_PHASE_2(aclnnRepeatInterleaveInt);
return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
}
aclnnStatus aclnnRepeatInterleaveIntWithDim(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
aclrtStream stream)
{
L2_DFX_PHASE_2(aclnnRepeatInterleaveIntWithDim);
return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
}
aclnnStatus aclnnRepeatInterleaveTensor(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
aclrtStream stream)
{
L2_DFX_PHASE_2(aclnnRepeatInterleaveTensor);
return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
}
#ifdef __cplusplus
}
#endif