aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Cheng <kevin.cheng@arm.com>2021-06-17 15:57:08 -0700
committerKevin Cheng <kevin.cheng@arm.com>2021-06-24 10:48:46 -0700
commit3bb1bc1189bfa14670d2f7839d708f443f5b5942 (patch)
treead0f72f278e0029c67d671cdbbe1d874230fba20
parenta8b4eafda31fe41b99a46c09c131ac7295382570 (diff)
downloadserialization_lib-3bb1bc1189bfa14670d2f7839d708f443f5b5942.tar.gz
Constant data is embedded in flatbuffer as u8 array instead of saving out as separate numpy files now.
Change-Id: I9d757ee3bdc637595732b06c5319d1dc957eaf96
-rw-r--r--include/tosa_generated.h25
-rw-r--r--include/tosa_serialization_handler.h29
-rw-r--r--python/tosa/TosaTensor.py29
-rw-r--r--schema/tosa.fbs8
-rw-r--r--src/tosa_serialization_handler.cpp268
5 files changed, 313 insertions, 46 deletions
diff --git a/include/tosa_generated.h b/include/tosa_generated.h
index 735aca8..0f73819 100644
--- a/include/tosa_generated.h
+++ b/include/tosa_generated.h
@@ -1951,7 +1951,7 @@ struct TosaTensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_NAME = 4,
VT_SHAPE = 6,
VT_TYPE = 8,
- VT_NPY_FILENAME = 10
+ VT_DATA = 10
};
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
@@ -1962,8 +1962,8 @@ struct TosaTensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
tosa::DType type() const {
return static_cast<tosa::DType>(GetField<uint32_t>(VT_TYPE, 0));
}
- const flatbuffers::String *npy_filename() const {
- return GetPointer<const flatbuffers::String *>(VT_NPY_FILENAME);
+ const flatbuffers::Vector<uint8_t> *data() const {
+ return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_DATA);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
@@ -1972,8 +1972,8 @@ struct TosaTensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_SHAPE) &&
verifier.VerifyVector(shape()) &&
VerifyField<uint32_t>(verifier, VT_TYPE) &&
- VerifyOffset(verifier, VT_NPY_FILENAME) &&
- verifier.VerifyString(npy_filename()) &&
+ VerifyOffset(verifier, VT_DATA) &&
+ verifier.VerifyVector(data()) &&
verifier.EndTable();
}
};
@@ -1991,8 +1991,8 @@ struct TosaTensorBuilder {
void add_type(tosa::DType type) {
fbb_.AddElement<uint32_t>(TosaTensor::VT_TYPE, static_cast<uint32_t>(type), 0);
}
- void add_npy_filename(flatbuffers::Offset<flatbuffers::String> npy_filename) {
- fbb_.AddOffset(TosaTensor::VT_NPY_FILENAME, npy_filename);
+ void add_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data) {
+ fbb_.AddOffset(TosaTensor::VT_DATA, data);
}
explicit TosaTensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
@@ -2011,9 +2011,9 @@ inline flatbuffers::Offset<TosaTensor> CreateTosaTensor(
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape = 0,
tosa::DType type = tosa::DType_UNKNOWN,
- flatbuffers::Offset<flatbuffers::String> npy_filename = 0) {
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0) {
TosaTensorBuilder builder_(_fbb);
- builder_.add_npy_filename(npy_filename);
+ builder_.add_data(data);
builder_.add_type(type);
builder_.add_shape(shape);
builder_.add_name(name);
@@ -2025,16 +2025,17 @@ inline flatbuffers::Offset<TosaTensor> CreateTosaTensorDirect(
const char *name = nullptr,
const std::vector<int32_t> *shape = nullptr,
tosa::DType type = tosa::DType_UNKNOWN,
- const char *npy_filename = nullptr) {
+ const std::vector<uint8_t> *data = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto shape__ = shape ? _fbb.CreateVector<int32_t>(*shape) : 0;
- auto npy_filename__ = npy_filename ? _fbb.CreateString(npy_filename) : 0;
+ if (data) { _fbb.ForceVectorAlignment(data->size(), sizeof(uint8_t), 8); }
+ auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
return tosa::CreateTosaTensor(
_fbb,
name__,
shape__,
type,
- npy_filename__);
+ data__);
}
struct TosaOperator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
diff --git a/include/tosa_serialization_handler.h b/include/tosa_serialization_handler.h
index 398590d..db9481b 100644
--- a/include/tosa_serialization_handler.h
+++ b/include/tosa_serialization_handler.h
@@ -26,6 +26,8 @@
#include <string>
#include <vector>
+#define TENSOR_BUFFER_FORCE_ALIGNMENT 8
+
namespace tosa
{
@@ -108,13 +110,13 @@ class TosaSerializationTensor
public:
// constructor and destructor
TosaSerializationTensor(const flatbuffers::String* name,
- const flatbuffers::Vector<int32_t>& shape,
+ const flatbuffers::Vector<int32_t>* shape,
DType dtype,
- const flatbuffers::String* npy_filename);
+ const flatbuffers::Vector<uint8_t>* data);
TosaSerializationTensor(std::string& name,
const std::vector<int32_t>& shape,
DType dtype,
- const std::string& npy_filename);
+ const std::vector<uint8_t>& data);
TosaSerializationTensor();
~TosaSerializationTensor();
@@ -131,9 +133,9 @@ public:
{
return _dtype;
}
- const std::string& GetNpyFilePtr() const
+ const std::vector<uint8_t>& GetData() const
{
- return _npy_filename;
+ return _data;
}
// modifier
@@ -150,7 +152,7 @@ private:
DType _dtype; /* data type enumeration, see tosa_isa_generated.h */
std::vector<int32_t> _shape; /* shape of the tensor */
std::string _name; /* name of the tensor, used for solving dependency */
- std::string _npy_filename; /* numpy array filename if not null. so null is the distinguisher */
+ std::vector<uint8_t> _data; /* data array */
};
class TosaSerializationOperator
@@ -283,6 +285,21 @@ public:
tosa_err_t SaveFileTosaFlatbuffer(const char* filename);
tosa_err_t LoadFileSchema(const char* schema_filename);
+ // data format conversion. little-endian.
+ static tosa_err_t ConvertF32toU8(const std::vector<float>& in, std::vector<uint8_t>& out);
+ static tosa_err_t ConvertI48toU8(const std::vector<int64_t>& in, std::vector<uint8_t>& out);
+ static tosa_err_t ConvertI32toU8(const std::vector<int32_t>& in, std::vector<uint8_t>& out);
+ static tosa_err_t ConvertI16toU8(const std::vector<int16_t>& in, std::vector<uint8_t>& out);
+ static tosa_err_t ConvertI8toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out);
+ static tosa_err_t ConvertBooltoU8(const std::vector<bool>& in, std::vector<uint8_t>& out);
+
+ static tosa_err_t ConvertU8toF32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<float>& out);
+ static tosa_err_t ConvertU8toI48(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int64_t>& out);
+ static tosa_err_t ConvertU8toI32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int32_t>& out);
+ static tosa_err_t ConvertU8toI16(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int16_t>& out);
+ static tosa_err_t ConvertU8toI8(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out);
+ static tosa_err_t ConvertU8toBool(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<bool>& out);
+
// version
const TosaVersion& GetTosaVersion() const
{
diff --git a/python/tosa/TosaTensor.py b/python/tosa/TosaTensor.py
index 760c091..9c0b3cf 100644
--- a/python/tosa/TosaTensor.py
+++ b/python/tosa/TosaTensor.py
@@ -81,16 +81,37 @@ class TosaTensor(object):
return 0
# TosaTensor
- def NpyFilename(self):
+ def Data(self, j):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
if o != 0:
- return self._tab.String(o + self._tab.Pos)
- return None
+ a = self._tab.Vector(o)
+ return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+ return 0
+
+ # TosaTensor
+ def DataAsNumpy(self):
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+ if o != 0:
+ return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+ return 0
+
+ # TosaTensor
+ def DataLength(self):
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+ if o != 0:
+ return self._tab.VectorLen(o)
+ return 0
+
+ # TosaTensor
+ def DataIsNone(self):
+ o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+ return o == 0
def TosaTensorStart(builder): builder.StartObject(4)
def TosaTensorAddName(builder, name): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
def TosaTensorAddShape(builder, shape): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(shape), 0)
def TosaTensorStartShapeVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def TosaTensorAddType(builder, type): builder.PrependUint32Slot(2, type, 0)
-def TosaTensorAddNpyFilename(builder, npyFilename): builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(npyFilename), 0)
+def TosaTensorAddData(builder, data): builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(data), 0)
+def TosaTensorStartDataVector(builder, numElems): return builder.StartVector(1, numElems, 1)
def TosaTensorEnd(builder): return builder.EndObject()
diff --git a/schema/tosa.fbs b/schema/tosa.fbs
index d64a50c..9c8add8 100644
--- a/schema/tosa.fbs
+++ b/schema/tosa.fbs
@@ -276,10 +276,10 @@ table Version {
}
table TosaTensor {
- name:string; // name of the tensor, used for solving dependency
- shape:[int32]; // shape of the tensor
- type:DType; // data type of the tensor
- npy_filename: string; // numpy array filename
+ name:string; // name of the tensor, used for solving dependency
+ shape:[int32]; // shape of the tensor
+ type:DType; // data type of the tensor
+ data: [ubyte] (force_align: 8); // raw data array if it's a constant tensor.
}
table TosaOperator {
diff --git a/src/tosa_serialization_handler.cpp b/src/tosa_serialization_handler.cpp
index 4fe152f..d153dc5 100644
--- a/src/tosa_serialization_handler.cpp
+++ b/src/tosa_serialization_handler.cpp
@@ -19,32 +19,32 @@
using namespace tosa;
TosaSerializationTensor::TosaSerializationTensor(const flatbuffers::String* name,
- const flatbuffers::Vector<int32_t>& shape,
+ const flatbuffers::Vector<int32_t>* shape,
DType dtype,
- const flatbuffers::String* npy_filename)
+ const flatbuffers::Vector<uint8_t>* data)
{
_dtype = dtype;
- std::copy(shape.begin(), shape.end(), std::back_inserter(_shape));
+ std::copy(shape->begin(), shape->end(), std::back_inserter(_shape));
assert(name);
_name = name->str();
- if (npy_filename)
+ if (data)
{
- _npy_filename = npy_filename->str();
+ std::copy(data->begin(), data->end(), std::back_inserter(_data));
}
}
TosaSerializationTensor::TosaSerializationTensor(std::string& name,
const std::vector<int32_t>& shape,
DType dtype,
- const std::string& npy_filename)
+ const std::vector<uint8_t>& data)
{
- _dtype = dtype;
- _shape = shape;
- _name = name;
- _npy_filename = npy_filename;
+ _dtype = dtype;
+ _shape = shape;
+ _name = name;
+ _data = data;
}
TosaSerializationTensor::TosaSerializationTensor()
@@ -483,12 +483,12 @@ tosa_err_t TosaSerializationHandler::InitWithBuf(const uint8_t* buf)
{
auto curr_tensor = fb_tosa_tensors->Get(j);
- auto tensor_name = curr_tensor->name();
- auto tensor_shape = curr_tensor->shape();
- auto tensor_type = curr_tensor->type();
- auto tensor_npy_filename = curr_tensor->npy_filename();
+ auto tensor_name = curr_tensor->name();
+ auto tensor_shape = curr_tensor->shape();
+ auto tensor_type = curr_tensor->type();
+ auto tensor_data = curr_tensor->data();
- new_tensor = new TosaSerializationTensor(tensor_name, *tensor_shape, tensor_type, tensor_npy_filename);
+ new_tensor = new TosaSerializationTensor(tensor_name, tensor_shape, tensor_type, tensor_data);
if (new_tensor)
{
block_tensors_container.push_back(new_tensor);
@@ -734,12 +734,9 @@ tosa_err_t TosaSerializationHandler::FreezeBuilder()
auto tensor_name = _builder.CreateString(tensor->GetName().c_str());
auto tensor_shape = _builder.CreateVector(tensor->GetShape());
auto tensor_dtype = tensor->GetDtype();
- flatbuffers::Offset<flatbuffers::String> tensor_npy_filename = 0;
- if (!tensor->GetNpyFilePtr().empty())
- tensor_npy_filename = _builder.CreateString(tensor->GetNpyFilePtr().c_str());
+ auto tensor_data = _builder.CreateVector(tensor->GetData());
- auto fboffset_tensor =
- CreateTosaTensor(_builder, tensor_name, tensor_shape, tensor_dtype, tensor_npy_filename);
+ auto fboffset_tensor = CreateTosaTensor(_builder, tensor_name, tensor_shape, tensor_dtype, tensor_data);
fboffset_block_tensors.push_back(fboffset_tensor);
}
@@ -760,3 +757,234 @@ tosa_err_t TosaSerializationHandler::FreezeBuilder()
return TOSA_OK;
}
+
+void zero_pad(std::vector<uint8_t>& buf)
+{
+ while ((buf.size() % TENSOR_BUFFER_FORCE_ALIGNMENT) != 0)
+ {
+ buf.push_back(0);
+ }
+}
+
+tosa_err_t TosaSerializationHandler::ConvertF32toU8(const std::vector<float>& in, std::vector<uint8_t>& out)
+{
+ out.clear();
+ for (auto val : in)
+ {
+ uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
+ out.push_back(*val_u32 & 0xFF);
+ out.push_back((*val_u32 >> 8) & 0xFF);
+ out.push_back((*val_u32 >> 16) & 0xFF);
+ out.push_back((*val_u32 >> 24) & 0xFF);
+ }
+ zero_pad(out);
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI48toU8(const std::vector<int64_t>& in, std::vector<uint8_t>& out)
+{
+ out.clear();
+ for (auto val : in)
+ {
+ uint64_t* val_u64 = reinterpret_cast<uint64_t*>(&val);
+ out.push_back(*val_u64 & 0xFF);
+ out.push_back((*val_u64 >> 8) & 0xFF);
+ out.push_back((*val_u64 >> 16) & 0xFF);
+ out.push_back((*val_u64 >> 24) & 0xFF);
+ out.push_back((*val_u64 >> 32) & 0xFF);
+ out.push_back((*val_u64 >> 40) & 0xFF);
+ }
+ zero_pad(out);
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI32toU8(const std::vector<int32_t>& in, std::vector<uint8_t>& out)
+{
+ out.clear();
+ for (auto val : in)
+ {
+ uint32_t* val_u32 = reinterpret_cast<uint32_t*>(&val);
+ out.push_back(*val_u32 & 0xFF);
+ out.push_back((*val_u32 >> 8) & 0xFF);
+ out.push_back((*val_u32 >> 16) & 0xFF);
+ out.push_back((*val_u32 >> 24) & 0xFF);
+ }
+ zero_pad(out);
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI16toU8(const std::vector<int16_t>& in, std::vector<uint8_t>& out)
+{
+ out.clear();
+ for (auto val : in)
+ {
+ uint16_t* val_u16 = reinterpret_cast<uint16_t*>(&val);
+ out.push_back(*val_u16 & 0xFF);
+ out.push_back((*val_u16 >> 8) & 0xFF);
+ }
+ zero_pad(out);
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertI8toU8(const std::vector<int8_t>& in, std::vector<uint8_t>& out)
+{
+ out.clear();
+ for (auto val : in)
+ {
+ uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
+ out.push_back(*val_u8);
+ }
+ zero_pad(out);
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertBooltoU8(const std::vector<bool>& in, std::vector<uint8_t>& out)
+{
+ out.clear();
+ for (auto val : in)
+ {
+ uint8_t* val_u8 = reinterpret_cast<uint8_t*>(&val);
+ out.push_back(*val_u8);
+ }
+ zero_pad(out);
+ return TOSA_OK;
+}
+
+tosa_err_t
+ TosaSerializationHandler::ConvertU8toF32(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<float>& out)
+{
+ out.clear();
+ if (in.size() < out_size * sizeof(float))
+ {
+ printf("TosaSerializationHandler::ConvertU8toF32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+ out_size * sizeof(float));
+ return TOSA_USER_ERROR;
+ }
+ for (int i = 0; i < out_size; i++)
+ {
+ uint32_t byte0 = in[i * sizeof(float)];
+ uint32_t byte1 = in[i * sizeof(float) + 1];
+ uint32_t byte2 = in[i * sizeof(float) + 2];
+ uint32_t byte3 = in[i * sizeof(float) + 3];
+ uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
+ float* val_fp32 = reinterpret_cast<float*>(&val_u32);
+ out.push_back(*val_fp32);
+ }
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertU8toI48(const std::vector<uint8_t>& in,
+ uint32_t out_size,
+ std::vector<int64_t>& out)
+{
+ out.clear();
+ if (in.size() < out_size * 6 /* sizeof(int48) */)
+ {
+ printf("TosaSerializationHandler::ConvertU8toI48(): uint8 buffer size %ld must >= target size %d\n", in.size(),
+ out_size * 6);
+ return TOSA_USER_ERROR;
+ }
+ for (int i = 0; i < out_size; i++)
+ {
+ uint64_t byte0 = in[i * 6];
+ uint64_t byte1 = in[i * 6 + 1];
+ uint64_t byte2 = in[i * 6 + 2];
+ uint64_t byte3 = in[i * 6 + 3];
+ uint64_t byte4 = in[i * 6 + 4];
+ uint64_t byte5 = in[i * 6 + 5];
+ bool sign = ((byte5 >> 7) & 1) == 1 ? true : false;
+ uint64_t val_u64 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24) + (byte4 << 32) + (byte5 << 40);
+ if (sign)
+ {
+ uint64_t sext_mask = (0xFFFFUL << 48);
+ val_u64 |= sext_mask;
+ }
+ int64_t* val_i64 = reinterpret_cast<int64_t*>(&val_u64);
+ out.push_back(*val_i64);
+ }
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertU8toI32(const std::vector<uint8_t>& in,
+ uint32_t out_size,
+ std::vector<int32_t>& out)
+{
+ out.clear();
+ if (in.size() < out_size * sizeof(int32_t))
+ {
+ printf("TosaSerializationHandler::ConvertU8toI32(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+ out_size * sizeof(int32_t));
+ return TOSA_USER_ERROR;
+ }
+ for (int i = 0; i < out_size; i++)
+ {
+ uint32_t byte0 = in[i * sizeof(int32_t)];
+ uint32_t byte1 = in[i * sizeof(int32_t) + 1];
+ uint32_t byte2 = in[i * sizeof(int32_t) + 2];
+ uint32_t byte3 = in[i * sizeof(int32_t) + 3];
+ uint32_t val_u32 = byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24);
+ int32_t* val_i32 = reinterpret_cast<int32_t*>(&val_u32);
+ out.push_back(*val_i32);
+ }
+ return TOSA_OK;
+}
+
+tosa_err_t TosaSerializationHandler::ConvertU8toI16(const std::vector<uint8_t>& in,
+ uint32_t out_size,
+ std::vector<int16_t>& out)
+{
+ out.clear();
+ if (in.size() < out_size * sizeof(int16_t))
+ {
+ printf("TosaSerializationHandler::ConvertU8toI16(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+ out_size * sizeof(int16_t));
+ return TOSA_USER_ERROR;
+ }
+ for (int i = 0; i < out_size; i++)
+ {
+ uint16_t byte0 = in[i * sizeof(int16_t)];
+ uint16_t byte1 = in[i * sizeof(int16_t) + 1];
+ uint16_t val_u16 = byte0 + (byte1 << 8);
+ int16_t* val_i16 = reinterpret_cast<int16_t*>(&val_u16);
+ out.push_back(*val_i16);
+ }
+ return TOSA_OK;
+}
+
+tosa_err_t
+ TosaSerializationHandler::ConvertU8toI8(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<int8_t>& out)
+{
+ out.clear();
+ if (in.size() < out_size * sizeof(int8_t))
+ {
+ printf("TosaSerializationHandler::ConvertU8toI8(): uint8 buffer size %ld must >= target size %ld\n", in.size(),
+ out_size * sizeof(bool));
+ return TOSA_USER_ERROR;
+ }
+ for (int i = 0; i < out_size; i++)
+ {
+ uint8_t val_u8 = in[i];
+ int8_t* val_i8 = reinterpret_cast<int8_t*>(&val_u8);
+ out.push_back(*val_i8);
+ }
+ return TOSA_OK;
+}
+
+tosa_err_t
+ TosaSerializationHandler::ConvertU8toBool(const std::vector<uint8_t>& in, uint32_t out_size, std::vector<bool>& out)
+{
+ out.clear();
+ if (in.size() < out_size * sizeof(bool))
+ {
+ printf("TosaSerializationHandler::ConvertU8toBool(): uint8 buffer size %ld must >= target size %ld\n",
+ in.size(), out_size * sizeof(bool));
+ return TOSA_USER_ERROR;
+ }
+ for (int i = 0; i < out_size; i++)
+ {
+ uint8_t val_u8 = in[i];
+ bool* val_bool = reinterpret_cast<bool*>(&val_u8);
+ out.push_back(*val_bool);
+ }
+ return TOSA_OK;
+}