| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| /*! |
| * \brief Registration of transform operators |
| * \file transform.cc |
| */ |
| #include <tvm/ffi/function.h> |
| #include <tvm/ffi/reflection/registry.h> |
| #include <tvm/topi/einsum.h> |
| #include <tvm/topi/transform.h> |
| #include <tvm/topi/utils.h> |
| |
| #include <iostream> |
| |
| #include "tvm/ir/expr.h" |
| |
| namespace tvm { |
| namespace topi { |
| |
| using namespace tvm; |
| using namespace tvm::runtime; |
| |
| TVM_FFI_STATIC_INIT_BLOCK() { |
| namespace refl = tvm::ffi::reflection; |
| refl::GlobalDef() |
| .def_packed("topi.expand_dims", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = expand_dims(args[0].cast<te::Tensor>(), args[1].cast<int>(), |
| args[2].cast<int>()); |
| }) |
| .def_packed("topi.transpose", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = transpose(args[0].cast<te::Tensor>(), |
| args[1].cast<ffi::Optional<ffi::Array<int64_t>>>()); |
| }) |
| .def_packed("topi.flip", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| // pass empty seq_lengths tensor to reverse_sequence |
| *rv = reverse_sequence(args[0].cast<te::Tensor>(), te::Tensor(), |
| args[1].cast<int>()); |
| }) |
| .def_packed("topi.reverse_sequence", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| int batch_axis = args.size() >= 4 ? args[3].cast<int>() : 0; |
| *rv = reverse_sequence(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| args[2].cast<int>(), batch_axis); |
| }) |
| .def_packed("topi.reshape", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = reshape(args[0].cast<te::Tensor>(), args[1].cast<ffi::Array<PrimExpr>>()); |
| }) |
| .def_packed("topi.sliding_window", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = sliding_window(args[0].cast<te::Tensor>(), args[1].cast<int>(), |
| args[2].cast<ffi::Array<int64_t>>(), |
| args[3].cast<ffi::Array<int64_t>>()); |
| }) |
| .def_packed("topi.squeeze", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = squeeze(args[0].cast<te::Tensor>(), ArrayOrInt(args[1])); |
| }) |
| .def_packed("topi.concatenate", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = concatenate(args[0].cast<ffi::Array<te::Tensor>>(), args[1].cast<int>()); |
| }) |
| .def_packed("topi.stack", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = stack(args[0].cast<ffi::Array<te::Tensor>>(), args[1].cast<int>()); |
| }) |
| .def_packed("topi.shape", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = shape(args[0].cast<te::Tensor>(), args[1].cast<PrimType>()); |
| }) |
| .def_packed("topi.tensor_size", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = tensor_size(args[0].cast<te::Tensor>(), args[1].cast<PrimType>()); |
| }) |
| .def_packed("topi.split", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| if (args[1].try_cast<int>()) { |
| *rv = split_n_sections(args[0].cast<te::Tensor>(), args[1].cast<int>(), |
| args[2].cast<int>()); |
| } else { |
| *rv = split_indices_array(args[0].cast<te::Tensor>(), |
| args[1].cast<ffi::Array<PrimExpr>>(), |
| args[2].cast<int>()); |
| } |
| }) |
| .def_packed("topi.layout_transform", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = |
| layout_transform(args[0].cast<te::Tensor>(), args[1].cast<std::string>(), |
| args[2].cast<std::string>(), args[3].cast<std::string>()); |
| }) |
| .def_packed( |
| "topi.take", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| if (args.size() == 4) { |
| auto mode = args[3].cast<std::string>(); |
| int batch_dims = args[2].cast<int>(); |
| *rv = take(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), batch_dims, mode); |
| } else { |
| TVM_FFI_ICHECK_EQ(args.size(), 5) << "topi.take expects 4 or 5 arguments"; |
| int batch_dims = args[2].cast<int>(); |
| int axis = args[3].cast<int>(); |
| auto mode = args[4].cast<std::string>(); |
| *rv = |
| take(args[0].cast<te::Tensor>(), |
| args[1].cast<ffi::Variant<te::Tensor, PrimExpr>>(), batch_dims, axis, mode); |
| } |
| }) |
| .def_packed("topi.sequence_mask", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| double pad_val = args[2].cast<double>(); |
| int axis = args[3].cast<int>(); |
| *rv = sequence_mask(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| pad_val, axis); |
| }) |
| .def_packed("topi.where", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = where(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| args[2].cast<te::Tensor>()); |
| }) |
| .def_packed("topi.arange", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = arange(args[0].cast<PrimExpr>(), args[1].cast<PrimExpr>(), |
| args[2].cast<PrimExpr>(), args[3].cast<PrimType>()); |
| }) |
| .def_packed("topi.meshgrid", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = meshgrid(args[0].cast<ffi::Array<te::Tensor>>(), |
| args[1].cast<std::string>()); |
| }) |
| .def_packed("topi.repeat", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = repeat(args[0].cast<te::Tensor>(), args[1].cast<int>(), |
| args[2].cast<int>()); |
| }) |
| .def_packed("topi.tile", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = tile(args[0].cast<te::Tensor>(), args[1].cast<ffi::Array<int64_t>>()); |
| }) |
| .def_packed("topi.dyn_tile", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = dyn_tile(args[0].cast<te::Tensor>(), args[1].cast<ffi::Array<PrimExpr>>(), |
| args[2].cast<int>()); |
| }) |
| .def_packed("topi.gather", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = gather(args[0].cast<te::Tensor>(), args[1].cast<int>(), |
| args[2].cast<te::Tensor>()); |
| }) |
| .def_packed("topi.gather_nd", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| int batch_dims = args[2].cast<int>(); |
| *rv = gather_nd(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| batch_dims); |
| }) |
| .def_packed("topi.unravel_index", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = unravel_index(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>()); |
| }) |
| .def_packed("topi.sparse_to_dense", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| *rv = sparse_to_dense(args[0].cast<te::Tensor>(), |
| args[1].cast<ffi::Array<PrimExpr>>(), |
| args[2].cast<te::Tensor>(), args[3].cast<PrimExpr>()); |
| }) |
| .def_packed("topi.matmul", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| switch (args.size()) { |
| case 2: |
| *rv = matmul(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>()); |
| break; |
| case 3: |
| *rv = matmul(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| args[2].cast<bool>()); |
| break; |
| case 4: |
| *rv = matmul(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| args[2].cast<bool>(), args[3].cast<bool>()); |
| break; |
| default: |
| TVM_FFI_ICHECK(0) << "topi.matmul expects 2, 3 or 4 arguments"; |
| } |
| }) |
| .def_packed("topi.tensordot", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| if (args.size() == 2) { |
| *rv = tensordot(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>()); |
| } else if (args.size() == 3) { |
| *rv = tensordot(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| args[2].cast<int>()); |
| } else { |
| ffi::Array<PrimExpr> axes = args[3].cast<ffi::Array<PrimExpr>>(); |
| *rv = tensordot(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| args[2].cast<ffi::Array<PrimExpr>>(), axes); |
| } |
| }) |
| .def_packed( |
| "topi.strided_slice", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| te::Tensor x = args[0].cast<te::Tensor>(); |
| ffi::Array<PrimExpr> begin = args[1].cast<ffi::Array<PrimExpr>>(); |
| ffi::Array<PrimExpr> end = args[2].cast<ffi::Array<PrimExpr>>(); |
| ffi::Array<PrimExpr> strides = args[3].cast<ffi::Array<PrimExpr>>(); |
| ffi::Array<int64_t> axes = args[4].cast<ffi::Array<int64_t>>(); |
| bool assume_inbound = args[6].cast<bool>(); |
| if (IsConstIntArray(begin) && IsConstIntArray(end) && IsConstIntArray(strides) && |
| IsConstIntArray(x->shape)) { |
| ffi::Array<ffi::Optional<IntImm>> begin_static = |
| args[1].cast<ffi::Array<ffi::Optional<IntImm>>>(); |
| ffi::Array<ffi::Optional<IntImm>> end_static = |
| args[2].cast<ffi::Array<ffi::Optional<IntImm>>>(); |
| ffi::Array<IntImm> strides_static = args[3].cast<ffi::Array<IntImm>>(); |
| auto slice_mode = args[5].cast<std::string>(); |
| if (axes.size()) { |
| *rv = strided_slice_with_axes(x, begin_static, end_static, strides_static, axes, |
| slice_mode); |
| } else { |
| *rv = strided_slice(x, begin_static, end_static, strides_static, slice_mode); |
| } |
| } else { |
| if (axes.size()) { |
| *rv = dynamic_strided_slice_with_axes(x, begin, end, strides, axes, assume_inbound); |
| } else { |
| *rv = dynamic_strided_slice(x, begin, end, strides, assume_inbound); |
| } |
| } |
| }) |
| .def_packed("topi.dynamic_strided_slice", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| te::Tensor begin = args[1].cast<te::Tensor>(); |
| te::Tensor end = args[2].cast<te::Tensor>(); |
| te::Tensor strides = args[3].cast<te::Tensor>(); |
| *rv = dynamic_strided_slice(args[0].cast<te::Tensor>(), begin, end, strides); |
| }) |
| .def("topi.relax_dynamic_strided_slice", |
| [](te::Tensor x, te::Tensor begin, te::Tensor end, te::Tensor strides, |
| ffi::Array<PrimExpr> output_shape) { |
| return relax::dynamic_strided_slice(x, begin, end, strides, output_shape); |
| }) |
| .def_packed("topi.one_hot", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| int depth = args[3].cast<int>(); |
| int axis = args[4].cast<int>(); |
| PrimType dtype = args[5].cast<PrimType>(); |
| *rv = one_hot(args[0].cast<te::Tensor>(), args[1].cast<PrimExpr>(), |
| args[2].cast<PrimExpr>(), depth, axis, dtype); |
| }) |
| .def_packed("topi.matrix_set_diag", |
| [](ffi::PackedArgs args, ffi::Any* rv) { |
| int k1 = args[2].cast<int>(); |
| int k2 = args[3].cast<int>(); |
| bool super_diag_right_align = args[4].cast<bool>(); |
| bool sub_diag_right_align = args[5].cast<bool>(); |
| *rv = matrix_set_diag(args[0].cast<te::Tensor>(), args[1].cast<te::Tensor>(), |
| k1, k2, super_diag_right_align, sub_diag_right_align); |
| }) |
| .def("topi.adv_index", |
| [](te::Tensor x, ffi::Array<te::Tensor> indices) { return adv_index(x, indices); }); |
| } |
| |
| } // namespace topi |
| } // namespace tvm |