/* * 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 namespace executorch { namespace extension { namespace { template < typename INT_T, typename std::enable_if< std::is_integral::value && !std::is_same::value, bool>::type = true> bool extract_scalar(executorch::aten::Scalar scalar, INT_T* out_val) { if (!scalar.isIntegral(/*includeBool=*/false)) { return false; } int64_t val = scalar.to(); if (val < std::numeric_limits::lowest() || val > std::numeric_limits::max()) { return false; } *out_val = static_cast(val); return true; } template < typename FLOAT_T, typename std::enable_if< std::is_floating_point_v || std::is_same_v || std::is_same_v, bool>::type = true> bool extract_scalar(executorch::aten::Scalar scalar, FLOAT_T* out_val) { double val; if (scalar.isFloatingPoint()) { val = scalar.to(); if (std::isfinite(val) && (val < std::numeric_limits::lowest() || val > std::numeric_limits::max())) { return false; } } else if (scalar.isIntegral(/*includeBool=*/false)) { val = static_cast(scalar.to()); } else { return false; } *out_val = static_cast(val); return true; } template < typename BOOL_T, typename std::enable_if::value, bool>::type = true> bool extract_scalar(executorch::aten::Scalar scalar, BOOL_T* out_val) { if (scalar.isIntegral(/*includeBool=*/false)) { *out_val = static_cast(scalar.to()); return true; } if (scalar.isBoolean()) { *out_val = scalar.to(); return true; } return false; } #define ET_EXTRACT_SCALAR(scalar, out_val) \ ET_CHECK_MSG( \ extract_scalar(scalar, &out_val), \ #scalar " could not be extracted: wrong type or out of range"); template TensorPtr random_strided( std::vector sizes, std::vector strides, executorch::aten::ScalarType type, executorch::aten::TensorShapeDynamism dynamism, Distribution&& distribution) { auto tensor = empty_strided(std::move(sizes), std::move(strides), type, dynamism); std::default_random_engine gen{std::random_device{}()}; ET_SWITCH_REALHBBF16_TYPES(type, nullptr, "random_strided", CTYPE, [&] { std::generate_n(tensor->mutable_data_ptr(), tensor->numel(), [&]() { return static_cast(distribution(gen)); }); }); return tensor; } } // namespace TensorPtr empty_strided( std::vector sizes, std::vector strides, executorch::aten::ScalarType type, executorch::aten::TensorShapeDynamism dynamism) { std::vector data( executorch::aten::compute_numel(sizes.data(), sizes.size()) * executorch::aten::elementSize(type)); return make_tensor_ptr( std::move(sizes), std::move(data), {}, std::move(strides), type, dynamism); } TensorPtr full_strided( std::vector sizes, std::vector strides, executorch::aten::Scalar fill_value, executorch::aten::ScalarType type, executorch::aten::TensorShapeDynamism dynamism) { auto tensor = empty_strided(std::move(sizes), std::move(strides), type, dynamism); ET_SWITCH_REALHBBF16_TYPES(type, nullptr, "full_strided", CTYPE, [&] { CTYPE value; ET_EXTRACT_SCALAR(fill_value, value); std::fill( tensor->mutable_data_ptr(), tensor->mutable_data_ptr() + tensor->numel(), value); }); return tensor; } TensorPtr rand_strided( std::vector sizes, std::vector strides, executorch::aten::ScalarType type, executorch::aten::TensorShapeDynamism dynamism) { auto upper_bound = 1.0f; // Adjusts the upper bound to prevent rounding to 1.0 when converting to // lower-precision types. if (type == executorch::aten::ScalarType::Half) { upper_bound -= float(std::numeric_limits::epsilon()) / 2; } else if (type == executorch::aten::ScalarType::BFloat16) { upper_bound -= float(std::numeric_limits::epsilon()) / 2; } return random_strided( std::move(sizes), std::move(strides), type, dynamism, std::uniform_real_distribution(0.0f, upper_bound)); } TensorPtr randn_strided( std::vector sizes, std::vector strides, executorch::aten::ScalarType type, executorch::aten::TensorShapeDynamism dynamism) { return random_strided( std::move(sizes), std::move(strides), type, dynamism, std::normal_distribution(0.0f, 1.0f)); } TensorPtr randint_strided( int64_t low, int64_t high, std::vector sizes, std::vector strides, executorch::aten::ScalarType type, executorch::aten::TensorShapeDynamism dynamism) { return random_strided( std::move(sizes), std::move(strides), type, dynamism, std::uniform_int_distribution(low, high - 1)); } } // namespace extension } // namespace executorch