53c718f632b28ea85069c575dba6b76b58765c99
[platform/core/csapi/tizenfx.git] / src / Tizen.MachineLearning.Inference / Tizen.MachineLearning.Inference / TensorsInfo.cs
1 /*
2 * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 using System;
18 using System.Collections.Generic;
19 using Log = Tizen.Log;
20
21 namespace Tizen.MachineLearning.Inference
22 {
23     /// <summary>
24     /// The TensorsInfo class manages each Tensor information such as Name, Type and Dimension.
25     /// </summary>
26     /// <since_tizen> 6 </since_tizen>
27     public class TensorsInfo : IDisposable
28     {
29         private List<TensorInfo> _infoList;
30         private IntPtr _handle = IntPtr.Zero;
31         private bool _disposed = false;
32
33         /// <summary>
34         /// Get the number of Tensor information which is added.
35         /// </summary>
36         /// <since_tizen> 6 </since_tizen>
37         public int Count => _infoList.Count;
38
39         /// <summary>
40         /// Creates a TensorsInfo instance.
41         /// </summary>
42         /// <feature>http://tizen.org/feature/machine_learning.inference</feature>
43         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
44         /// <since_tizen> 6 </since_tizen>
45         public TensorsInfo()
46         {
47             NNStreamer.CheckNNStreamerSupport();
48
49             Log.Info(NNStreamer.TAG, "TensorsInfo is created");
50             _infoList = new List<TensorInfo>();
51         }
52
53         /// <summary>
54         /// Destroys the TensorsInfo resource.
55         /// </summary>
56         /// <since_tizen> 6 </since_tizen>
57         ~TensorsInfo()
58         {
59             Dispose(false);
60         }
61
62         /// <summary>
63         /// Add a Tensor information to the TensorsInfo instance. Note that we support up to 16 tensors in TensorsInfo.
64         /// </summary>
65         /// <param name="type">Data element type of Tensor.</param>
66         /// <param name="dimension">Dimension of Tensor. Note that we support up to 4th ranks.</param>
67         /// <feature>http://tizen.org/feature/machine_learning.inference</feature>
68         /// <exception cref="IndexOutOfRangeException">Thrown when the number of Tensor already exceeds the size limits (i.e. Tensor.SlzeLimit)</exception>
69         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
70         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
71         /// <since_tizen> 6 </since_tizen>
72         public void AddTensorInfo(TensorType type, int[] dimension)
73         {
74             NNStreamer.CheckNNStreamerSupport();
75
76             AddTensorInfo(null, type, dimension);
77         }
78
79         /// <summary>
80         /// Add a Tensor information to the TensorsInfo instance. Note that we support up to 16 tensors in TensorsInfo.
81         /// </summary>
82         /// <param name="name">Name of Tensor.</param>
83         /// <param name="type">Data element type of Tensor.</param>
84         /// <param name="dimension">Dimension of Tensor. Note that we support up to 4th ranks.</param>
85         /// <feature>http://tizen.org/feature/machine_learning.inference</feature>
86         /// <exception cref="IndexOutOfRangeException">Thrown when the number of Tensor already exceeds the size limits (i.e. Tensor.SlzeLimit)</exception>
87         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
88         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
89         /// <since_tizen> 6 </since_tizen>
90         public void AddTensorInfo(string name, TensorType type, int[] dimension)
91         {
92             NNStreamer.CheckNNStreamerSupport();
93
94             int idx = _infoList.Count;
95             if (idx >= Tensor.SizeLimit) {
96                 throw new IndexOutOfRangeException("Max size of the tensors is " + Tensor.SizeLimit);
97             }
98             _infoList.Add(new TensorInfo(name, type, dimension));
99
100             if (_handle != IntPtr.Zero)
101             {
102                 NNStreamerError ret = NNStreamerError.None;
103
104                 ret = Interop.Util.SetTensorsCount(_handle, _infoList.Count);
105                 NNStreamer.CheckException(ret, "unable to set the number of tensors");
106
107                 ret = Interop.Util.SetTensorType(_handle, idx, type);
108                 NNStreamer.CheckException(ret, "fail to set TensorsInfo type");
109
110                 ret = Interop.Util.SetTensorDimension(_handle, idx, dimension);
111                 NNStreamer.CheckException(ret, "fail to set TensorsInfo dimension");
112             }
113         }
114
115         /// <summary>
116         /// Sets the tensor name with given index.
117         /// </summary>
118         /// <param name="idx">The index of the tensor to be updated.</param>
119         /// <param name="name">The tensor name to be set.</param>
120         /// <feature>http://tizen.org/feature/machine_learning.inference</feature>
121         /// <exception cref="IndexOutOfRangeException">Thrown when the index is greater than the number of Tensor.</exception>
122         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
123         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
124         /// <since_tizen> 6 </since_tizen>
125         public void SetTensorName(int idx, string name)
126         {
127             NNStreamer.CheckNNStreamerSupport();
128
129             CheckIndexBoundary(idx);
130             _infoList[idx].Name = name;
131
132             if (_handle != IntPtr.Zero)
133             {
134                 NNStreamerError ret = NNStreamerError.None;
135                 ret = Interop.Util.SetTensorName(_handle, idx, name);
136                 NNStreamer.CheckException(ret, "unable to set the name of tensor: " + idx.ToString());
137             }
138         }
139
140         /// <summary>
141         /// Gets the tensor name with given index.
142         /// </summary>
143         /// <param name="idx">The index of the tensor.</param>
144         /// <returns>The tensor name.</returns>
145         /// <exception cref="IndexOutOfRangeException">Thrown when the index is greater than the number of Tensor.</exception>
146         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
147         /// <since_tizen> 6 </since_tizen>
148         public string GetTensorName(int idx)
149         {
150             NNStreamer.CheckNNStreamerSupport();
151
152             CheckIndexBoundary(idx);
153             return _infoList[idx].Name;
154         }
155
156         /// <summary>
157         /// Sets the tensor type with given index and its type.
158         /// </summary>
159         /// <param name="idx">The index of the tensor to be updated.</param>
160         /// <param name="type">The tensor type to be set.</param>
161         /// <feature>http://tizen.org/feature/machine_learning.inference</feature>
162         /// <exception cref="IndexOutOfRangeException">Thrown when the index is greater than the number of Tensor.</exception>
163         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
164         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
165         /// <since_tizen> 6 </since_tizen>
166         public void SetTensorType(int idx, TensorType type)
167         {
168             NNStreamer.CheckNNStreamerSupport();
169
170             CheckIndexBoundary(idx);
171             _infoList[idx].Type = type;
172
173             if (_handle != IntPtr.Zero)
174             {
175                 NNStreamerError ret = NNStreamerError.None;
176                 ret = Interop.Util.SetTensorType(_handle, idx, type);
177                 NNStreamer.CheckException(ret, "unable to set the type of tensor: " + idx.ToString());
178             }
179         }
180
181         /// <summary>
182         /// Gets the tensor type with given index.
183         /// </summary>
184         /// <param name="idx">The index of the tensor.</param>
185         /// <returns>The tensor type</returns>
186         /// <exception cref="IndexOutOfRangeException">Thrown when the index is greater than the number of Tensor.</exception>
187         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
188         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
189         /// <since_tizen> 6 </since_tizen>
190         public TensorType GetTensorType(int idx)
191         {
192             NNStreamer.CheckNNStreamerSupport();
193
194             CheckIndexBoundary(idx);
195             return _infoList[idx].Type;
196         }
197
198         /// <summary>
199         /// Sets the tensor dimension with given index and dimension.
200         /// </summary>
201         /// <param name="idx">The index of the tensor to be updated.</param>
202         /// <param name="dimension">The tensor dimension to be set.</param>
203         /// <feature>http://tizen.org/feature/machine_learning.inference</feature>
204         /// <exception cref="IndexOutOfRangeException">Thrown when the index is greater than the number of Tensor.</exception>
205         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
206         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
207         /// <since_tizen> 6 </since_tizen>
208         public void SetDimension(int idx, int[] dimension)
209         {
210             NNStreamer.CheckNNStreamerSupport();
211
212             CheckIndexBoundary(idx);
213             _infoList[idx].SetDimension(dimension);
214
215             if (_handle != IntPtr.Zero)
216             {
217                 NNStreamerError ret = NNStreamerError.None;
218                 ret = Interop.Util.SetTensorDimension(_handle, idx, dimension);
219                 NNStreamer.CheckException(ret, "unable to set the dimension of tensor: " + idx.ToString());
220             }
221         }
222
223         /// <summary>
224         /// Gets the tensor dimension with given index.
225         /// </summary>
226         /// <param name="idx">The index of the tensor.</param>
227         /// <returns>The tensor dimension.</returns>
228         /// <exception cref="IndexOutOfRangeException">Thrown when the index is greater than the number of Tensor.</exception>
229         /// <exception cref="ArgumentException">Thrown when the method failed due to an invalid parameter.</exception>
230         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
231         /// <since_tizen> 6 </since_tizen>
232         public int[] GetDimension(int idx)
233         {
234             NNStreamer.CheckNNStreamerSupport();
235
236             CheckIndexBoundary(idx);
237             return _infoList[idx].Dimension;
238         }
239
240         /// <summary>
241         /// Creates a TensorsData instance based on informations of TensorsInfo
242         /// </summary>
243         /// <returns>TensorsData instance</returns>
244         /// <feature>http://tizen.org/feature/machine_learning.inference</feature>
245         /// <exception cref="ArgumentException">Thrown when the method failed due to TensorsInfo's information is invalid.</exception>
246         /// <exception cref="NotSupportedException">Thrown when the feature is not supported.</exception>
247         /// <since_tizen> 6 </since_tizen>
248         public TensorsData GetTensorsData()
249         {
250             IntPtr tensorsData_h = IntPtr.Zero;
251             TensorsData retTensorData;
252             NNStreamerError ret = NNStreamerError.None;
253
254             NNStreamer.CheckNNStreamerSupport();
255
256             if (_handle == IntPtr.Zero)
257             {
258                 Log.Info(NNStreamer.TAG, "_handle is IntPtr.Zero\n" + "  GetTensorsInfoHandle() is called");
259                 GetTensorsInfoHandle();
260             }
261
262             ret = Interop.Util.CreateTensorsData(_handle, out tensorsData_h);
263             NNStreamer.CheckException(ret, "unable to create the tensorsData object");
264
265             retTensorData = TensorsData.CreateFromNativeHandle(tensorsData_h);
266
267             return retTensorData;
268         }
269
270         internal IntPtr GetTensorsInfoHandle()
271         {
272             NNStreamerError ret = NNStreamerError.None;
273             IntPtr ret_handle = IntPtr.Zero;
274             int idx;
275
276             /* Already created */
277             if (_handle != IntPtr.Zero)
278                 return _handle;
279
280             /* Check required parameters */
281             int num = _infoList.Count;
282             if (num <= 0 || num > Tensor.SizeLimit)
283                 ret = NNStreamerError.InvalidParameter;
284             NNStreamer.CheckException(ret, "number of Tensor in TensorsInfo is invalid: " + _infoList.Count);
285
286             /* Create TensorsInfo object */
287             ret = Interop.Util.CreateTensorsInfo(out ret_handle);
288             NNStreamer.CheckException(ret, "fail to create TensorsInfo object");
289
290             /* Set the number of tensors */
291             ret = Interop.Util.SetTensorsCount(ret_handle, _infoList.Count);
292             NNStreamer.CheckException(ret, "unable to set the number of tensors");
293
294             /* Set each Tensor info */
295             idx = 0;
296             foreach (TensorInfo t in _infoList)
297             {
298                 ret = Interop.Util.SetTensorType(ret_handle, idx, t.Type);
299                 NNStreamer.CheckException(ret, "fail to set the type of tensor" + idx.ToString());
300
301                 ret = Interop.Util.SetTensorDimension(ret_handle, idx, t.Dimension);
302                 NNStreamer.CheckException(ret, "fail to set the dimension of tensor: " + idx.ToString());
303
304                 idx += 1;
305             }
306
307             _handle = ret_handle;
308             return ret_handle;
309         }
310
311         /// <summary>
312         /// Releases any unmanaged resources used by this object.
313         /// </summary>
314         /// <since_tizen> 6 </since_tizen>
315         public void Dispose()
316         {
317             Dispose(true);
318             GC.SuppressFinalize(this);
319         }
320
321         /// <summary>
322         /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
323         /// </summary>
324         /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
325         protected virtual void Dispose(bool disposing)
326         {
327             if (_disposed)
328                 return;
329
330             if (disposing)
331             {
332                 // release managed objects
333                 _infoList.Clear();
334             }
335
336             // release unmanaged objects
337             if (_handle != IntPtr.Zero)
338             {
339                 NNStreamerError ret = Interop.Util.DestroyTensorsInfo(_handle);
340
341                 if (ret != NNStreamerError.None)
342                 {
343                     Log.Error(NNStreamer.TAG, "failed to destroy TensorsInfo object");
344                 }
345             }
346             _disposed = true;
347         }
348         
349         private void CheckIndexBoundary(int idx)
350         {
351             if (idx < 0 || idx >= _infoList.Count) {
352                 throw new IndexOutOfRangeException("Invalid index [" + idx + "] of the tensors");
353             }
354         }
355
356         private class TensorInfo
357         {
358             public TensorInfo(TensorType type, int[] dimension)
359             {
360                 Type = type;
361                 SetDimension(dimension);
362             }
363
364             public TensorInfo(string name, TensorType type, int[] dimension)
365             {
366                 Name = name;
367                 Type = type;
368                 SetDimension(dimension);
369             }
370
371             public void SetDimension(int[] dimension)
372             {
373                 if (dimension == null) {
374                     throw new ArgumentException("Max size of the tensor rank is" + Tensor.RankLimit);
375                 }
376
377                 if (dimension.Length > Tensor.RankLimit) {
378                     throw new ArgumentException("Max size of the tensor rank is" + Tensor.RankLimit);
379                 }
380                 Dimension = (int[])dimension.Clone();
381             }
382
383             public string Name { get; set; } = null;
384
385             public TensorType Type { get; set; } = TensorType.Int32;
386
387             public int[] Dimension { get; private set; } = new int[Tensor.RankLimit];
388         }
389     }
390 }