blob: 692746852694efeb00b07f991cc2cfc43788c537 [file]
/*
* 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.
*/
/*!
* \file src/support/scalars.cc
* \brief Helpers for converting between scalars in native, text, TIR immediate and Tensor forms.
*/
#include "./scalars.h"
#include "tvm/runtime/builtin_fp16.h"
namespace tvm {
namespace support {
/*! \brief The standard scalar dtypes. */
static const DataType kInt16 = DataType::Int(16);
static const DataType kInt32 = DataType::Int(32);
static const DataType kInt64 = DataType::Int(64);
static const DataType kFloat16 = DataType::Float(16);
static const DataType kFloat32 = DataType::Float(32);
static const DataType kFloat64 = DataType::Float(64);
static const DataType kBool = DataType::Bool();
runtime::Tensor IntImmToTensor(const IntImm& int_imm) {
DLDevice dev = {DLDeviceType::kDLCPU, 0};
auto data = runtime::Tensor::Empty({}, int_imm->dtype, dev);
if (int_imm.dtype() == kInt16) {
auto* array = reinterpret_cast<int16_t*>(data->data);
array[0] = static_cast<int16_t>(int_imm->value);
} else if (int_imm.dtype() == kInt32) {
auto* array = reinterpret_cast<int32_t*>(data->data);
array[0] = static_cast<int32_t>(int_imm->value);
} else if (int_imm.dtype() == kInt64) {
auto* array = reinterpret_cast<int64_t*>(data->data);
array[0] = int_imm->value;
} else {
LOG(FATAL) << "Unrecognized numeric literal dtype: " << DLDataTypeToString(int_imm.dtype());
}
return data;
}
runtime::Tensor FloatImmToTensor(const FloatImm& float_imm) {
DLDevice dev = {DLDeviceType::kDLCPU, 0};
auto data = runtime::Tensor::Empty({}, float_imm->dtype, dev);
if (float_imm.dtype() == kFloat16) {
auto* array = reinterpret_cast<uint16_t*>(data->data);
array[0] = __gnu_f2h_ieee(static_cast<float>(float_imm->value));
} else if (float_imm.dtype() == kFloat32) {
auto* array = reinterpret_cast<float*>(data->data);
array[0] = static_cast<float>(float_imm->value);
} else if (float_imm.dtype() == kFloat64) {
auto* array = reinterpret_cast<double*>(data->data);
array[0] = float_imm->value;
} else {
LOG(FATAL) << "Unrecognized numeric literal dtype: " << DLDataTypeToString(float_imm.dtype());
}
return data;
}
runtime::Tensor BoolToTensor(bool value) {
DLDevice dev = {DLDeviceType::kDLCPU, 0};
auto data = runtime::Tensor::Empty({}, kBool, dev);
auto array = reinterpret_cast<bool*>(data->data);
array[0] = value;
return data;
}
std::string TensorScalarToString(const runtime::Tensor& data) {
std::ostringstream os;
DataType dtype(data->dtype);
ICHECK_EQ(data->device.device_type, kDLCPU) << "Scalars must reside on the CPU to be printed";
if (dtype == kInt16) {
auto value = static_cast<const int16_t*>(data->data)[0];
os << value << "i16";
} else if (dtype == kInt32) {
auto value = static_cast<const int32_t*>(data->data)[0];
os << value;
} else if (dtype == kInt64) {
auto value = static_cast<const int64_t*>(data->data)[0];
os << value << "i64";
} else if (dtype == kFloat16) {
auto value = __gnu_h2f_ieee(static_cast<const uint16_t*>(data->data)[0]);
os << value << "f16";
} else if (dtype == kFloat32) {
auto value = static_cast<const float*>(data->data)[0];
os << value << "f";
} else if (dtype == kFloat64) {
auto value = static_cast<const double*>(data->data)[0];
os << value << "f64";
} else if (dtype == kBool) {
auto value = static_cast<const uint8_t*>(data->data)[0];
os << (value ? "True" : "False");
} else {
LOG(FATAL) << "Unrecognized Tensor scalar dtype: " << DLDataTypeToString(dtype);
}
return os.str();
}
std::string IntImmToString(const IntImm& int_imm) {
std::ostringstream os;
if (int_imm->dtype == kInt16) {
os << int_imm->value << "i16";
} else if (int_imm->dtype == kInt32) {
os << int_imm->value;
} else if (int_imm->dtype == kInt64) {
os << int_imm->value << "i64";
} else if (int_imm->dtype == kBool) {
os << (int_imm->value ? "True" : "False");
} else {
LOG(FATAL) << "Unrecognised IntImm dtype: " << DLDataTypeToString(int_imm->dtype);
}
return os.str();
}
std::string FloatImmToString(const FloatImm& float_imm) {
std::ostringstream os;
if (float_imm->dtype == kFloat16) {
os << float_imm->value << "f16";
} else if (float_imm->dtype == kFloat32) {
os << float_imm->value << "f";
} else if (float_imm->dtype == kFloat64) {
os << float_imm->value << "f64";
} else {
LOG(FATAL) << "Unrecognised FloatImm dtype: " << DLDataTypeToString(float_imm->dtype);
}
return os.str();
}
IntImm ValueToIntImm(int64_t value, int width) {
if (width == 16) {
if (value < std::numeric_limits<int16_t>::min() ||
value > std::numeric_limits<int16_t>::max()) {
return {};
}
return IntImm(kInt16, value);
} else if (width == 32) {
if (value < std::numeric_limits<int32_t>::min() ||
value > std::numeric_limits<int32_t>::max()) {
return {};
}
return IntImm(kInt32, value);
} else if (width == 64) {
return IntImm(kInt64, value);
} else {
LOG(FATAL) << "Unrecognized int scalar width: " << width;
}
}
FloatImm ValueToFloatImm(double value, int width) {
if (width == 16) {
if (!std::isinf(value) && (value < -kMaxFloat16 || value > kMaxFloat16)) {
return {};
}
return FloatImm(kFloat16, value);
} else if (width == 32) {
if (!std::isinf(value) &&
(value < -std::numeric_limits<float>::max() || value > std::numeric_limits<float>::max())) {
return {};
}
return FloatImm(kFloat32, value);
} else if (width == 64) {
return FloatImm(kFloat64, value);
} else {
LOG(FATAL) << "Unrecognized float scalar width: " << width;
}
}
} // namespace support
} // namespace tvm