/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #include #include #include #include #include #include namespace torch { namespace executor { namespace native { using executorch::aten::optional; using executorch::aten::Tensor; Tensor& argmax_out( KernelRuntimeContext& ctx, const Tensor& in, optional dim, bool keepdim, Tensor& out) { (void)ctx; ET_KERNEL_CHECK( ctx, check_argmin_argmax_args(in, dim, keepdim, out), InvalidArgument, out); ET_KERNEL_CHECK( ctx, resize_reduction_out(in, dim, keepdim, out) == Error::Ok, InvalidArgument, out); ET_KERNEL_CHECK( ctx, tensors_have_same_dim_order(in, out), InvalidArgument, out); ET_SWITCH_REALHBF16_TYPES(in.scalar_type(), ctx, "argmax.out", CTYPE, [&] { long* out_data = out.mutable_data_ptr(); const bool success = parallel_for_each_reduce_over_dim_output_index( in, dim, out, [&](const auto begin, const auto end) { for (const auto out_ix : c10::irange(begin, end)) { std::tuple acc = reduce_over_dim( [](CTYPE v, long ix, CTYPE acc_val, long acc_ix) { // the below condition as written is equivalent to // !isnan(accval) && (isnan(v) || v > acc_val). See // argument in op_argmin.cpp. if (!std::isnan(acc_val) && !(v <= acc_val)) { acc_val = v; acc_ix = ix; } return std::tuple{acc_val, acc_ix}; }, in, dim, out_ix); out_data[out_ix] = std::get<1>(acc); } }); ET_KERNEL_CHECK_MSG(ctx, success, Internal, , "parallel_for failed"); }); return out; } } // namespace native } // namespace executor } // namespace torch