[ML][Common] Add TensorRawData and size/location validation on JS side 82/252482/2
authorRafal Walczyna <r.walczyna@samsung.com>
Thu, 28 Jan 2021 16:35:08 +0000 (17:35 +0100)
committerPiotr Kosko <p.kosko@samsung.com>
Fri, 29 Jan 2021 12:30:51 +0000 (12:30 +0000)
C++ validation will be added in future commit

Test code:
var ti = new tizen.ml.TensorsInfo();
ti.addTensorInfo("tensor1", "UINT8", [1, 1])
ti.addTensorInfo("tensor2", "INT16", [2, 4])
ti.addTensorInfo("tensor3", "FLOAT32", [2, 2])
var td = ti.getTensorsData();
console.log(td.getTensorRawData(0))
console.log(td.getTensorRawData(1))
console.log(td.getTensorRawData(2))

[Verification] Built successful. Tested in Chrome Dev console.

Change-Id: I14caa9a91b04ed2664cca241da54977a711b1abd
Signed-off-by: Rafal Walczyna <r.walczyna@samsung.com>
src/ml/js/ml_common.js
src/ml/ml_instance.cc
src/ml/ml_tensors_data_manager.cc
src/ml/ml_tensors_data_manager.h

index 0208213..699cddf 100755 (executable)
@@ -26,25 +26,22 @@ var MAX_TENSORS_INFO_COUNT = 16;
 
 // TensorRawData
 
-var TensorRawData = function() {
+var TensorRawData = function(data, size, shape) {
     Object.defineProperties(this, {
         data: {
             enumerable: true,
-            get: function() {
-                throw new WebAPIException(WebAPIException.ABORT_ERR, 'Not implemented');
-            }
+            writable: false,
+            value: data
         },
         size: {
             enumerable: true,
-            get: function() {
-                throw new WebAPIException(WebAPIException.ABORT_ERR, 'Not implemented');
-            }
+            writable: false,
+            value: size
         },
         shape: {
             enumerable: true,
-            get: function() {
-                throw new WebAPIException(WebAPIException.ABORT_ERR, 'Not implemented');
-            }
+            writable: false,
+            value: shape
         }
     });
 };
@@ -89,6 +86,21 @@ function _GetBufferTypeFromTensorType(tensorType) {
     return Uint8Array;
 }
 
+function _CheckIfArrayHasOnlyNumbersAndThrow(array, arrayName) {
+    if (xwalk.utils.type.isNullOrUndefined(array)) {
+        return;
+    }
+
+    array.forEach(function(d) {
+        if (Number.isInteger(d) == false) {
+            throw new WebAPIException(
+                WebAPIException.TYPE_MISMATCH_ERR,
+                arrayName + ' array has to contain only integers'
+            );
+        }
+    });
+}
+
 // TensorsData
 
 var _ValidTensorsDataIds = new Set();
@@ -149,7 +161,9 @@ TensorsData.prototype.getTensorRawData = function() {
             'Invalid parameter: index is undefined'
         );
     }
-    // TODO: validate location and size - will be done in future commit
+
+    _CheckIfArrayHasOnlyNumbersAndThrow(args.location, 'location');
+    _CheckIfArrayHasOnlyNumbersAndThrow(args.size, 'size');
 
     var callArgs = {
         tensorsDataId: this._id,
@@ -171,8 +185,8 @@ TensorsData.prototype.getTensorRawData = function() {
     // TODO: modify StringToArray to accept also float types, not only int
     var data = privUtils_.StringToArray(result.buffer, Uint8Array);
     var ArrayType = _GetBufferTypeFromTensorType(result.type);
-    // TODO: return TensorRawData
-    return new ArrayType(data.buffer);
+    var shape = result.shape;
+    return new TensorRawData(new ArrayType(data.buffer), data.byteLength, shape);
 };
 
 var TensorsDataSetTensorRawDataExceptions = [
@@ -246,7 +260,8 @@ TensorsData.prototype.setTensorRawData = function() {
     }
     var buffer = ValidateBufferForTensorsData(this, argsIndex.index, arguments[1]);
 
-    // TODO: validate location and size - will be done in future commit
+    _CheckIfArrayHasOnlyNumbersAndThrow(argsLocSize.location, 'location');
+    _CheckIfArrayHasOnlyNumbersAndThrow(argsLocSize.size, 'size');
 
     // TODO: modify ArrayToString to accept also float types, not only int
     var encodedData = privUtils_.ArrayToString(new Uint8Array(buffer.buffer));
@@ -369,14 +384,7 @@ TensorsInfo.prototype.addTensorInfo = function() {
         }
     ]);
 
-    args.dimensions.forEach(function(d) {
-        if (Number.isInteger(d) == false) {
-            throw new WebAPIException(
-                WebAPIException.TYPE_MISMATCH_ERR,
-                'dimensions array has to contain only integers'
-            );
-        }
-    });
+    _CheckIfArrayHasOnlyNumbersAndThrow(args.dimensions, 'dimensions');
 
     var callArgs = {
         name: args.name,
@@ -497,14 +505,7 @@ TensorsInfo.prototype.setDimensions = function() {
         }
     ]);
 
-    args.dimensions.forEach(function(d) {
-        if (Number.isInteger(d) == false) {
-            throw new WebAPIException(
-                WebAPIException.TYPE_MISMATCH_ERR,
-                'dimensions array has to contain only integers'
-            );
-        }
-    });
+    _CheckIfArrayHasOnlyNumbersAndThrow(args.dimensions, 'dimensions');
 
     var callArgs = {
         index: args.index,
index 3969f57..078b7b5 100644 (file)
@@ -48,6 +48,7 @@ const std::string kSTRING = "STRING";
 const std::string kBuffer = "buffer";
 const std::string kSize = "size";
 const std::string kLocation = "location";
+const std::string kShape = "shape";
 }  //  namespace
 
 using namespace common;
@@ -644,6 +645,11 @@ void MlInstance::MLTensorsDataGetTensorRawData(const picojson::value& args, pico
   common::encode_binary_in_string(out_data, out[kBuffer].get<std::string>());
 
   out[kType] = picojson::value(raw_data.type_str);
+  picojson::array shape = picojson::array{};
+  for (int i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
+    shape.push_back(picojson::value{static_cast<double>(raw_data.shape[i])});
+  }
+  out[kShape] = picojson::value{shape};
 
   ReportSuccess(out);
 }
index eff05da..410cd68 100644 (file)
@@ -79,8 +79,18 @@ PlatformResult TensorsData::GetTensorRawData(int index, int location[ML_TENSOR_R
   }
   // TODO: add support for location and size - will be done in future commit
 
-  PlatformResult result =
-      types::TensorTypeEnum.getName(this->GetTensorType(index), &tensor_raw_data->type_str);
+  // Dimensions of whole tensor
+  unsigned int dim[ML_TENSOR_RANK_LIMIT];
+  PlatformResult result = tensors_info_->NativeGetTensorDimensions(index, dim);
+  if (!result) {
+    return result;
+  }
+
+  for (int i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
+    tensor_raw_data->shape[i] = dim[i];
+  }
+
+  result = types::TensorTypeEnum.getName(this->GetTensorType(index), &tensor_raw_data->type_str);
   if (!result) {
     return result;
   }
index c8e4ca9..41db5e7 100644 (file)
@@ -36,6 +36,7 @@ struct TensorRawData {
   uint8_t* data;
   size_t size;
   std::string type_str;
+  unsigned int shape[ML_TENSOR_RANK_LIMIT];
 };
 
 class TensorsData {