// // CPUAsString.cpp // MNN // // Created by MNN on 2018/08/05. // Copyright © 2018, Alibaba Group Holding Limited // #include "backend/cpu/CPUAsString.hpp" #include #include #include "core/Macro.h" #include "core/TensorUtils.hpp" namespace MNN { #define INT_CAPACITY 10 #define FLOAT_CAPACITY 30 inline std::string _int2String(int number) { char result[INT_CAPACITY]; snprintf(result, INT_CAPACITY, "%d", number); return std::string(result); } class AsStringExecutor : public Execution { public: AsStringExecutor(Backend* backend, const AsString* op) : Execution(backend) { mWidth = op->width(); mPrecision = op->precision(); mScientific = op->scientific(); if (nullptr != op->fillString()) { mFillString = op->fillString()->str(); } mSourceType = op->T(); mShortest = op->shortest(); } virtual ~AsStringExecutor() = default; virtual ErrorCode onExecute(const std::vector& inputs, const std::vector& outputs) override { auto inputTensor = inputs[0]; auto outputTensor = outputs[0]; TensorUtils::clearHandleData(outputTensor); std::string format = "%"; if (mWidth >= 0) { format = format + mFillString + _int2String(mWidth); } if (mPrecision >= 0) { format = format + "." + _int2String(mPrecision); } switch (mSourceType) { case DataType_DT_INT8: case DataType_DT_INT32: format = format + "d"; break; case DataType_DT_INT64: format = format + "lld"; break; case DataType_DT_FLOAT: case DataType_DT_DOUBLE: case DataType_DT_COMPLEX64: { if (mShortest) { format += "g"; } else if (mScientific) { format += "e"; } else { format += "f"; } } default: break; } if (mSourceType == DataType_DT_COMPLEX64) { format = std::string("(") + format + "," + format + ")"; } auto size = inputTensor->size() / inputTensor->buffer().type.bytes(); auto outputData = outputTensor->host(); MNN_ASSERT(mSourceType == DataType_DT_FLOAT || mSourceType == DataType_DT_BOOL); switch (mSourceType) { case DataType_DT_FLOAT: { auto data = inputTensor->host(); for (int i = 0; i < size; i++) { auto tempData = (char*)::malloc(FLOAT_CAPACITY + 1); snprintf(tempData, FLOAT_CAPACITY, format.c_str(), data[i]); tempData[FLOAT_CAPACITY] = 0; outputData[i] = ::strdup(tempData); ::free(tempData); } break; } case DataType_DT_BOOL: { auto data = inputTensor->host(); for (int i = 0; i < size; i++) { if (data[i] > 0) { outputData[i] = ::strdup("true"); } else { outputData[i] = ::strdup("false"); } } break; } default: return NOT_SUPPORT; } return NO_ERROR; } private: int mWidth; int mPrecision; bool mScientific; bool mShortest; std::string mFillString; DataType mSourceType; }; Execution* CPUAsStringCreator::onCreate(const std::vector& inputs, const std::vector& outputs, const MNN::Op* op, Backend* backend) const { return new AsStringExecutor(backend, op->main_as_AsString()); } REGISTER_CPU_OP_CREATOR(CPUAsStringCreator, OpType_AsString); } // namespace MNN