[ Mixed Tensor ] Enable FP32 unittest cases
authorjijoong.moon <jijoong.moon@samsung.com>
Mon, 24 Jul 2023 22:47:33 +0000 (07:47 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Mon, 21 Aug 2023 06:29:23 +0000 (15:29 +0900)
This PR enables the FP32 unittest cases. It includes various fixes and
adding compiler preprocessor pragmas.

**Self evaluation:**
1. Build test:  [X]Passed [ ]Failed [ ]Skipped
2. Run test:  [X]Passed [ ]Failed [ ]Skipped

Signed-off-by: jijoong.moon <jijoong.moon@samsung.com>
20 files changed:
meson.build
nntrainer/graph/network_graph.h
nntrainer/layers/loss/loss_layer.h
nntrainer/models/model_loader.cpp
nntrainer/tensor/blas_interface.cpp
nntrainer/tensor/blas_interface.h
nntrainer/tensor/memory_data.h
nntrainer/tensor/tensor.cpp
nntrainer/tensor/tensor.h
nntrainer/tensor/tensor_dim.cpp
nntrainer/tensor/tensor_pool.cpp
nntrainer/tensor/tensor_pool.h
nntrainer/utils/base_properties.h
test/jni/Android.mk
test/unittest/jni/tests/nntrainer_test_util.cpp [deleted file]
test/unittest/jni/tests/nntrainer_test_util.h [deleted file]
test/unittest/jni/tests/unittest_nntrainer_tensor.cpp [deleted file]
test/unittest/jni/tests/unittest_nntrainer_tensor_fp16.cpp [deleted file]
test/unittest/meson.build
test/unittest/unittest_nntrainer_tensor_pool.cpp

index 0f43512..8559247 100644 (file)
@@ -72,6 +72,10 @@ warning_c_flags = [
 #    endforeach
 # enfif
 
+if get_option('enable-fp16')
+  extra_defines += '-DENABLE_FP16=1'
+endif
+
 foreach extra_arg : warning_flags
   if cc.has_argument (extra_arg)
     add_project_arguments([extra_arg], language: 'c')
index d3a3459..34292e5 100644 (file)
@@ -377,7 +377,7 @@ public:
    * @return TensorDim::Format NCHW or NHWC
    */
   std::array<const std::string, 2> getTensorType() {
-    return {std::move(tensor_format), std::move(tensor_dtype)};
+    return {tensor_format, tensor_dtype};
   };
 
   /**
index 00b520f..0307f5c 100644 (file)
@@ -52,6 +52,28 @@ public:
    */
   bool requireLabel() const override { return true; }
 
+  /**
+   * @brief set the Tensor Type for the layer
+   * @param     Tensor Type : NCHW or NHWC
+   */
+  void setTensorType(std::array<const std::string, 2> t_type) {
+    if (t_type[0].compare("NCHW") == 0 || t_type[0].compare("nchw") == 0) {
+      tensor_format = ml::train::TensorDim::Format::NCHW;
+    } else {
+      tensor_format = ml::train::TensorDim::Format::NHWC;
+    }
+
+    nntrainer::props::TensorDataType type_;
+
+    from_string(t_type[1], type_);
+
+    tensor_dtype = type_;
+  }
+
+private:
+  ml::train::TensorDim::Format tensor_format;
+  ml::train::TensorDim::DataType tensor_dtype;
+
 protected:
   /**
    * @brief     update loss
index 6d438f4..286ed17 100644 (file)
@@ -121,10 +121,10 @@ int ModelLoader::loadModelConfigIni(dictionary *ini, NeuralNetwork &model) {
     return ML_ERROR_INVALID_PARAMETER;
   }
 
-  std::vector<std::string> properties =
-    parseProperties(ini, "Model",
-                    {"optimizer", "learning_rate", "decay_steps", "decay_rate",
-                     "beta1", "beta2", "epsilon", "type", "save_path"});
+  std::vector<std::string> properties = parseProperties(
+    ini, "Model",
+    {"optimizer", "learning_rate", "decay_steps", "decay_rate", "beta1",
+     "beta2", "epsilon", "type", "save_path", "tensor_type", "tensor_format"});
   try {
     model.setProperty(properties);
   } catch (std::exception &e) {
index e88b8ce..764eaea 100644 (file)
     }                                        \
   } while (0);
 
-// #define sgemv_loop_fp16(ci, cj, cM, cN)      \
-//   do {                                       \
-//     __fp16 y0;                               \
-//     unsigned int i, j;                       \
-//     for (ci = 0; ci != cM; ci++) {           \
-//       y0 = Y[ci * incy] * beta;              \
-//       for (cj = 0; cj != cN; cj++)           \
-//         y0 += A[i + j * lda] * X[cj * incx]; \
-//       Y[ci * incy] = y0;                     \
-//     }                                        \
-//   } while (0);
-
 namespace nntrainer {
 
-#ifndef USE_BLAS
-
-static void saxpy_raw(const unsigned int N, const float alpha, const float *X,
-                      const int incX, float *Y, const int incY) {
-  if (incX < 0 or incY < 0)
-    throw std::invalid_argument(
-      "Error: negative inc not supported without cblas");
-  for (unsigned int i = 0; i < N; ++i)
-    Y[i * incY] = Y[i * incY] + X[i * incX] * alpha;
-}
-
+#ifdef ENABLE_FP16
 static void saxpy_FP16(const unsigned int N, const float alpha, const __fp16 *X,
                        const int incX, __fp16 *Y, const int incY) {
   if (incX < 0 or incY < 0)
@@ -63,22 +41,6 @@ static void saxpy_FP16(const unsigned int N, const float alpha, const __fp16 *X,
     Y[i * incY] = Y[i * incY] + alpha * X[i * incX];
 }
 
-static void sgemv_raw(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA,
-                      const unsigned int M, const unsigned int N,
-                      const float alpha, const float *A, const unsigned int lda,
-                      const float *X, const int incX, const float beta,
-                      float *Y, const int incY) {
-
-  unsigned int incy = abs(incY);
-  unsigned int incx = abs(incX);
-
-  if (TransA == CblasTrans) {
-    sgemv_loop(i, j, N, M);
-  } else {
-    sgemv_loop(j, i, M, N);
-  }
-}
-
 static void sgemv_FP16(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA,
                        const unsigned int M, const unsigned int N,
                        const float alpha, const __fp16 *A,
@@ -95,16 +57,6 @@ static void sgemv_FP16(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA,
   }
 }
 
-static float sdot_raw(const unsigned int N, const float *X,
-                      const unsigned int incX, const float *Y,
-                      const unsigned int incY) {
-  float ret = 0;
-  for (unsigned int i = 0; i < N; ++i) {
-    ret += X[i * incX] * Y[i * incY];
-  }
-  return ret;
-}
-
 static __fp16 sdot_FP16(const unsigned int N, const __fp16 *X,
                         const unsigned int incX, const __fp16 *Y,
                         const unsigned int incY) {
@@ -115,15 +67,6 @@ static __fp16 sdot_FP16(const unsigned int N, const __fp16 *X,
   return ret;
 }
 
-static void scopy_raw(const unsigned int N, const float *X, const int incX,
-                      float *Y, const int incY) {
-  unsigned int incy = abs(incY);
-  unsigned int incx = abs(incX);
-
-  for (unsigned int i = 0; i < N; ++i)
-    Y[i * incy] = X[i * incx];
-}
-
 static void scopy_FP16(const unsigned int N, const __fp16 *X, const int incX,
                        __fp16 *Y, const int incY) {
   unsigned int incy = abs(incY);
@@ -133,65 +76,165 @@ static void scopy_FP16(const unsigned int N, const __fp16 *X, const int incX,
     Y[i * incy] = X[i * incx];
 }
 
-static void sscal_raw(const unsigned int N, const float alpha, float *X,
-                      const int incX) {
+void sscal(const unsigned int N, const float alpha, __fp16 *X, const int incX) {
   unsigned int incx = abs(incX);
 
   for (unsigned int i = 0; i < N; ++i)
     X[i * incx] = alpha * X[i * incx];
 }
 
-void sscal(const unsigned int N, const float alpha, __fp16 *X, const int incX) {
+static float snrm2_FP16(const unsigned int N, const __fp16 *X, const int incX) {
   unsigned int incx = abs(incX);
+  __fp16 sum = 0.0f;
+  __fp16 tmp;
+#pragma omp parallel for private(tmp) reduction(+ : sum)
+  for (unsigned int i = 0; i < N; i++) {
+    tmp = X[i * incx];
+    sum += tmp * tmp;
+  }
+  return sqrt(sum);
+}
+static void sgemm_FP16(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA,
+                       CBLAS_TRANSPOSE TransB, const unsigned int M,
+                       const unsigned int N, const unsigned int K,
+                       const float alpha, const __fp16 *A,
+                       const unsigned int lda, const __fp16 *B,
+                       const unsigned int ldb, const float beta, __fp16 *C,
+                       const unsigned int ldc) {
 
-  for (unsigned int i = 0; i < N; ++i)
-    X[i * incx] = alpha * X[i * incx];
+  for (unsigned int m = 0; m < M; ++m) {
+    for (unsigned int n = 0; n < N; ++n) {
+      __fp16 c = 0.0;
+      __fp16 c_old = C[m * ldc + n];
+      for (unsigned int k = 0; k < K; ++k) {
+        __fp16 a, b;
+        a = ((TransA == CblasTrans) ? A[k * lda + m] : A[m * lda + k]);
+        b = ((TransB == CblasTrans) ? B[n * ldb + k] : B[k * ldb + n]);
+        c += a * b;
+      }
+      C[m * ldc + n] = alpha * c;
+      if (beta != 0.0)
+        C[m * ldc + n] += beta * c_old;
+    }
+  }
 }
 
-void sscal(const unsigned int N, const float alpha, void *X, const int incX,
-           ml::train::TensorDim::DataType d_type) {
-#ifdef USE_BLAS
-#ifdef BLAS_NUM_THREADS
-  openblas_set_num_threads(BLAS_NUM_THREADS);
-#endif
-  if (d_type == ml::train::TensorDim::DataType::FP32)
-    cblas_sscal(N, alpha, (float *)X, incX);
-#else
-  if (d_type == ml::train::TensorDim::DataType::FP32) {
-    sscal_raw(N, alpha, (float *)X, incX);
-  } else if (d_type == ml::train::TensorDim::DataType::FP16) {
-    sscal(N, alpha, (__fp16 *)X, incX);
+static unsigned int isamax_FP16(const unsigned int N, const __fp16 *X,
+                                const int incX) {
+
+  unsigned int max_idx = 0;
+  __fp16 max_val = X[0];
+  for (unsigned int n = 1; n < N; n += incX) {
+    __fp16 cur_val = abs(X[n]);
+    if (cur_val > max_val) {
+      max_val = cur_val;
+      max_idx = n;
+    }
   }
-#endif
+
+  return max_idx;
+}
+
+void saxpy(const unsigned int N, const float alpha, const __fp16 *X,
+           const int incX, __fp16 *Y, const int incY) {
+  saxpy_FP16(N, alpha, X, incX, Y, incY);
+}
+
+void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
+           const unsigned int M, const unsigned int N, const unsigned int K,
+           const float alpha, const __fp16 *A, const unsigned int lda,
+           const __fp16 *B, const unsigned int ldb, const float beta, __fp16 *C,
+           const unsigned int ldc) {
+  sgemm_FP16(order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C,
+             ldc);
+}
+
+void scopy(const unsigned int N, const __fp16 *X, const int incX, __fp16 *Y,
+           const int incY) {
+  scopy_FP16(N, X, incX, Y, incY);
+
+} // namespace nntrainer
+
+__fp16 snrm2(const int N, const __fp16 *X, const int incX) {
+  return snrm2_FP16(N, X, incX);
+}
+
+__fp16 sdot(const unsigned int N, const __fp16 *X, const unsigned int incX,
+            const __fp16 *Y, const unsigned int incY) {
+  return sdot_FP16(N, X, incX, Y, incY);
+}
+
+void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
+           const unsigned int N, const float alpha, const __fp16 *A,
+           const unsigned int lda, const __fp16 *X, const int incX,
+           const float beta, __fp16 *Y, const int incY) {
+  sgemv_FP16(order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY);
+}
+
+unsigned int isamax(const unsigned int N, const __fp16 *X, const int incX) {
+  /// @todo isamax_FP16 for BLAS_NUM_THREADS
+  return isamax_FP16(N, X, incX);
 }
 
-void sscal(const unsigned int N, const float alpha, float *X, const int incX) {
-#ifdef USE_BLAS
-#ifdef BLAS_NUM_THREADS
-  openblas_set_num_threads(BLAS_NUM_THREADS);
-#endif
-  cblas_sscal(N, alpha, (float *)X, incX);
-#else
-  sscal_raw(N, alpha, (float *)X, incX);
 #endif
+
+#ifndef USE_BLAS
+static void saxpy_raw(const unsigned int N, const float alpha, const float *X,
+                      const int incX, float *Y, const int incY) {
+  if (incX < 0 or incY < 0)
+    throw std::invalid_argument(
+      "Error: negative inc not supported without cblas");
+  for (unsigned int i = 0; i < N; ++i)
+    Y[i * incY] = Y[i * incY] + X[i * incX] * alpha;
 }
 
-static float snrm2_raw(const unsigned int N, const float *X, const int incX) {
+static void sgemv_raw(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA,
+                      const unsigned int M, const unsigned int N,
+                      const float alpha, const float *A, const unsigned int lda,
+                      const float *X, const int incX, const float beta,
+                      float *Y, const int incY) {
+
+  unsigned int incy = abs(incY);
   unsigned int incx = abs(incX);
-  float sum = 0.0f;
-  float tmp;
-#pragma omp parallel for private(tmp) reduction(+ : sum)
-  for (unsigned int i = 0; i < N; i++) {
-    tmp = X[i * incx];
-    sum += tmp * tmp;
+
+  if (TransA == CblasTrans) {
+    sgemv_loop(i, j, N, M);
+  } else {
+    sgemv_loop(j, i, M, N);
   }
-  return sqrt(sum);
 }
 
-static float snrm2_FP16(const unsigned int N, const __fp16 *X, const int incX) {
+static float sdot_raw(const unsigned int N, const float *X,
+                      const unsigned int incX, const float *Y,
+                      const unsigned int incY) {
+  float ret = 0;
+  for (unsigned int i = 0; i < N; ++i) {
+    ret += X[i * incX] * Y[i * incY];
+  }
+  return ret;
+}
+
+static void scopy_raw(const unsigned int N, const float *X, const int incX,
+                      float *Y, const int incY) {
+  unsigned int incy = abs(incY);
   unsigned int incx = abs(incX);
-  __fp16 sum = 0.0f;
-  __fp16 tmp;
+
+  for (unsigned int i = 0; i < N; ++i)
+    Y[i * incy] = X[i * incx];
+}
+
+static void sscal_raw(const unsigned int N, const float alpha, float *X,
+                      const int incX) {
+  unsigned int incx = abs(incX);
+
+  for (unsigned int i = 0; i < N; ++i)
+    X[i * incx] = alpha * X[i * incx];
+}
+
+static float snrm2_raw(const unsigned int N, const float *X, const int incX) {
+  unsigned int incx = abs(incX);
+  float sum = 0.0f;
+  float tmp;
 #pragma omp parallel for private(tmp) reduction(+ : sum)
   for (unsigned int i = 0; i < N; i++) {
     tmp = X[i * incx];
@@ -224,31 +267,6 @@ static void sgemm_raw(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA,
   }
 }
 
-static void sgemm_FP16(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA,
-                       CBLAS_TRANSPOSE TransB, const unsigned int M,
-                       const unsigned int N, const unsigned int K,
-                       const float alpha, const __fp16 *A,
-                       const unsigned int lda, const __fp16 *B,
-                       const unsigned int ldb, const float beta, __fp16 *C,
-                       const unsigned int ldc) {
-
-  for (unsigned int m = 0; m < M; ++m) {
-    for (unsigned int n = 0; n < N; ++n) {
-      __fp16 c = 0.0;
-      __fp16 c_old = C[m * ldc + n];
-      for (unsigned int k = 0; k < K; ++k) {
-        __fp16 a, b;
-        a = ((TransA == CblasTrans) ? A[k * lda + m] : A[m * lda + k]);
-        b = ((TransB == CblasTrans) ? B[n * ldb + k] : B[k * ldb + n]);
-        c += a * b;
-      }
-      C[m * ldc + n] = alpha * c;
-      if (beta != 0.0)
-        C[m * ldc + n] += beta * c_old;
-    }
-  }
-}
-
 static unsigned int isamax_raw(const unsigned int N, const float *X,
                                const int incX) {
 
@@ -265,23 +283,39 @@ static unsigned int isamax_raw(const unsigned int N, const float *X,
   return max_idx;
 }
 
-static unsigned int isamax_FP16(const unsigned int N, const __fp16 *X,
-                                const int incX) {
+#endif
 
-  unsigned int max_idx = 0;
-  __fp16 max_val = X[0];
-  for (unsigned int n = 1; n < N; n += incX) {
-    __fp16 cur_val = abs(X[n]);
-    if (cur_val > max_val) {
-      max_val = cur_val;
-      max_idx = n;
-    }
+void sscal(const unsigned int N, const float alpha, void *X, const int incX,
+           ml::train::TensorDim::DataType d_type) {
+#ifdef USE_BLAS
+#ifdef BLAS_NUM_THREADS
+  openblas_set_num_threads(BLAS_NUM_THREADS);
+#endif
+  if (d_type == ml::train::TensorDim::DataType::FP32)
+    cblas_sscal(N, alpha, (float *)X, incX);
+#else
+  if (d_type == ml::train::TensorDim::DataType::FP32) {
+    sscal_raw(N, alpha, (float *)X, incX);
+  } else if (d_type == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
+    sscal(N, alpha, (__fp16 *)X, incX);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
-
-  return max_idx;
+#endif
 }
 
+void sscal(const unsigned int N, const float alpha, float *X, const int incX) {
+#ifdef USE_BLAS
+#ifdef BLAS_NUM_THREADS
+  openblas_set_num_threads(BLAS_NUM_THREADS);
 #endif
+  cblas_sscal(N, alpha, X, incX);
+#else
+  sscal_raw(N, alpha, X, incX);
+#endif
+}
 
 void saxpy(const unsigned int N, const float alpha, const void *X,
            const int incX, void *Y, const int incY,
@@ -290,12 +324,19 @@ void saxpy(const unsigned int N, const float alpha, const void *X,
 #ifdef BLAS_NUM_THREADS
   openblas_set_num_threads(BLAS_NUM_THREADS);
 #endif
-  cblas_saxpy(N, alpha, X, incX, Y, incY);
+  cblas_saxpy(N, alpha, static_cast<const float *>(X), incX,
+              static_cast<float *>(Y), incY);
 #else
   if (d_type == ml::train::TensorDim::DataType::FP32) {
-    saxpy_raw(N, alpha, (float *)X, incX, (float *)Y, incY);
+    saxpy_raw(N, alpha, static_cast<const float *>(X), incX,
+              static_cast<float *>(Y), incY);
   } else if (d_type == ml::train::TensorDim::DataType::FP16) {
-    saxpy_FP16(N, alpha, (__fp16 *)X, incX, (__fp16 *)Y, incY);
+#ifdef ENABLE_FP16
+    saxpy_FP16(N, alpha, static_cast<const __fp16 *>(X), incX,
+               static_cast<__fp16 *>(Y), incY);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 #endif
 }
@@ -312,11 +353,6 @@ void saxpy(const unsigned int N, const float alpha, const float *X,
 #endif
 }
 
-void saxpy(const unsigned int N, const float alpha, const __fp16 *X,
-           const int incX, __fp16 *Y, const int incY) {
-  saxpy_FP16(N, alpha, X, incX, Y, incY);
-}
-
 void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
            const unsigned int M, const unsigned int N, const unsigned int K,
            const float alpha, const void *A, const unsigned int lda,
@@ -352,15 +388,23 @@ void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
 #ifdef BLAS_NUM_THREADS
   openblas_set_num_threads(BLAS_NUM_THREADS);
 #endif
-  cblas_sgemm(order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C,
-              ldc);
+  cblas_sgemm(order, TransA, TransB, M, N, K, alpha,
+              static_cast<const float *>(A), lda, static_cast<const float *>(B),
+              ldb, beta, static_cast<float *>(C), ldc);
 #else
   if (d_type == ml::train::TensorDim::DataType::FP32) {
-    sgemm_raw(order, TransA, TransB, M, N, K, alpha, (float *)A, lda,
-              (float *)B, ldb, beta, (float *)C, ldc);
+    sgemm_raw(order, TransA, TransB, M, N, K, alpha,
+              static_cast<const float *>(A), lda, static_cast<const float *>(B),
+              ldb, beta, static_cast<float *>(C), ldc);
   } else if (d_type == ml::train::TensorDim::DataType::FP16) {
-    sgemm_FP16(order, TransA, TransB, M, N, K, alpha, (__fp16 *)A, lda,
-               (__fp16 *)B, ldb, beta, (__fp16 *)C, ldc);
+#ifdef ENABLE_FP16
+    sgemm_FP16(order, TransA, TransB, M, N, K, alpha,
+               static_cast<const __fp16 *>(A), lda,
+               static_cast<const __fp16 *>(B), ldb, beta,
+               static_cast<__fp16 *>(C), ldc);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 #endif
 }
@@ -409,15 +453,6 @@ void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
 #endif
 }
 
-void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
-           const unsigned int M, const unsigned int N, const unsigned int K,
-           const float alpha, const __fp16 *A, const unsigned int lda,
-           const __fp16 *B, const unsigned int ldb, const float beta, __fp16 *C,
-           const unsigned int ldc) {
-  sgemm_FP16(order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C,
-             ldc);
-}
-
 void scopy(const unsigned int N, const void *X, const int incX, void *Y,
            const int incY, ml::train::TensorDim::DataType d_type) {
 #ifdef USE_BLAS
@@ -431,7 +466,11 @@ void scopy(const unsigned int N, const void *X, const int incX, void *Y,
   if (d_type == ml::train::TensorDim::DataType::FP32) {
     scopy_raw(N, (float *)X, incX, (float *)Y, incY);
   } else if (d_type == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     scopy_FP16(N, (__fp16 *)X, incX, (__fp16 *)Y, incY);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 #endif
 } // namespace nntrainer
@@ -448,12 +487,6 @@ void scopy(const unsigned int N, const float *X, const int incX, float *Y,
 #endif
 } // namespace nntrainer
 
-void scopy(const unsigned int N, const __fp16 *X, const int incX, __fp16 *Y,
-           const int incY) {
-  scopy_FP16(N, X, incX, Y, incY);
-
-} // namespace nntrainer
-
 float snrm2(const int N, const float *X, const int incX) {
 #ifdef USE_BLAS
 #ifdef BLAS_NUM_THREADS
@@ -465,10 +498,6 @@ float snrm2(const int N, const float *X, const int incX) {
 #endif
 }
 
-__fp16 snrm2(const int N, const __fp16 *X, const int incX) {
-  return snrm2_FP16(N, X, incX);
-}
-
 float sdot(const unsigned int N, const float *X, const unsigned int incX,
            const float *Y, const unsigned int incY) {
 #ifdef USE_BLAS
@@ -481,11 +510,6 @@ float sdot(const unsigned int N, const float *X, const unsigned int incX,
 #endif
 }
 
-__fp16 sdot(const unsigned int N, const __fp16 *X, const unsigned int incX,
-            const __fp16 *Y, const unsigned int incY) {
-  return sdot_FP16(N, X, incX, Y, incY);
-}
-
 void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
            const unsigned int N, const float alpha, const void *A,
            const unsigned int lda, const void *X, const int incX,
@@ -495,15 +519,23 @@ void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
 #ifdef BLAS_NUM_THREADS
   openblas_set_num_threads(BLAS_NUM_THREADS);
 #endif
-  return cblas_sgemv(order, TransA, M, N, alpha, A, lda, X, incX, beta, Y,
-                     incY);
+  return cblas_sgemv(order, TransA, M, N, alpha, static_cast<const float *>(A),
+                     lda, static_cast<const float *>(X), incX, beta,
+                     static_cast<float *>(Y), incY);
 #else
   if (d_type == ml::train::TensorDim::DataType::FP32) {
-    return sgemv_raw(order, TransA, M, N, alpha, (float *)A, lda, (float *)X,
-                     incX, beta, (float *)Y, incY);
+    return sgemv_raw(order, TransA, M, N, alpha, static_cast<const float *>(A),
+                     lda, static_cast<const float *>(X), incX, beta,
+                     static_cast<float *>(Y), incY);
   } else if (d_type == ml::train::TensorDim::DataType::FP16) {
-    return sgemv_FP16(order, TransA, M, N, alpha, (__fp16 *)A, lda, (__fp16 *)X,
-                      incX, beta, (__fp16 *)Y, incY);
+#ifdef ENABLE_FP16
+    return sgemv_FP16(order, TransA, M, N, alpha,
+                      static_cast<const __fp16 *>(A), lda,
+                      static_cast<const __fp16 *>(X), incX, beta,
+                      static_cast<__fp16 *>(Y), incY);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 #endif
 }
@@ -523,13 +555,6 @@ void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
 #endif
 }
 
-void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
-           const unsigned int N, const float alpha, const __fp16 *A,
-           const unsigned int lda, const __fp16 *X, const int incX,
-           const float beta, __fp16 *Y, const int incY) {
-  sgemv_FP16(order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY);
-}
-
 unsigned int isamax(const unsigned int N, const float *X, const int incX) {
 #ifdef USE_BLAS
 #ifdef BLAS_NUM_THREADS
@@ -541,9 +566,4 @@ unsigned int isamax(const unsigned int N, const float *X, const int incX) {
 #endif
 }
 
-unsigned int isamax(const unsigned int N, const __fp16 *X, const int incX) {
-  /// @todo isamax_FP16 for BLAS_NUM_THREADS
-  return isamax_FP16(N, X, incX);
-}
-
 } // namespace nntrainer
index 63274a9..1aff5b5 100644 (file)
@@ -39,42 +39,48 @@ enum CBLAS_TRANSPOSE {
 
 namespace nntrainer {
 
+#ifdef ENABLE_FP16
+void sscal(const unsigned int N, const float alpha, __fp16 *X, const int incX);
+__fp16 snrm2(const int N, const __fp16 *X, const int incX);
+void scopy(const unsigned int N, const __fp16 *X, const int incX, __fp16 *Y,
+           const int intY);
+__fp16 sdot(const unsigned int N, const __fp16 *X, const unsigned int incX,
+            const __fp16 *Y, const unsigned int incY);
+void saxpy(const unsigned int N, const float alpha, const __fp16 *X,
+           const int incX, __fp16 *Y, const int incY);
+void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
+           const unsigned int M, const unsigned int N, const unsigned int K,
+           const float alpha, const __fp16 *A, const unsigned int lda,
+           const __fp16 *B, const unsigned int ldb, const float beta, __fp16 *C,
+           const unsigned int ldc);
+void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
+           const unsigned int N, const float alpha, const __fp16 *A,
+           const unsigned int lda, const __fp16 *X, const int incX,
+           const float beta, __fp16 *Y, const int incY);
+unsigned int isamax(const unsigned int N, const __fp16 *X, const int incX);
+#endif
+
 void sscal(const unsigned int N, const float alpha, void *X, const int incX,
            ml::train::TensorDim::DataType d_type);
 
 void sscal(const unsigned int N, const float alpha, float *X, const int incX);
 
-void sscal(const unsigned int N, const float alpha, __fp16 *X, const int incX);
-
 float snrm2(const int N, const float *X, const int incX);
 
-__fp16 snrm2(const int N, const __fp16 *X, const int incX);
-
 void scopy(const unsigned int N, const void *X, const int incX, void *Y,
            const int incY, ml::train::TensorDim::DataType d_type);
-
 void scopy(const unsigned int N, const float *X, const int incX, float *Y,
            const int intY);
 
-void scopy(const unsigned int N, const __fp16 *X, const int incX, __fp16 *Y,
-           const int intY);
-
 float sdot(const unsigned int N, const float *X, const unsigned int incX,
            const float *Y, const unsigned int incY);
 
-__fp16 sdot(const unsigned int N, const __fp16 *X, const unsigned int incX,
-            const __fp16 *Y, const unsigned int incY);
-
 void saxpy(const unsigned int N, const float alpha, const void *X,
            const int incX, void *Y, const int incY,
            ml::train::TensorDim::DataType d_type);
-
 void saxpy(const unsigned int N, const float alpha, const float *X,
            const int incX, float *Y, const int incY);
 
-void saxpy(const unsigned int N, const float alpha, const __fp16 *X,
-           const int incX, __fp16 *Y, const int incY);
-
 void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
            const unsigned int M, const unsigned int N, const unsigned int K,
            const float alpha, const void *A, const unsigned int lda,
@@ -87,12 +93,6 @@ void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
            const float *B, const unsigned int ldb, const float beta, float *C,
            const unsigned int ldc);
 
-void sgemm(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB,
-           const unsigned int M, const unsigned int N, const unsigned int K,
-           const float alpha, const __fp16 *A, const unsigned int lda,
-           const __fp16 *B, const unsigned int ldb, const float beta, __fp16 *C,
-           const unsigned int ldc);
-
 void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
            const unsigned int N, const float alpha, const void *A,
            const unsigned int lda, const void *X, const int incX,
@@ -104,15 +104,8 @@ void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
            const unsigned int lda, const float *X, const int incX,
            const float beta, float *Y, const int incY);
 
-void sgemv(CBLAS_ORDER order, CBLAS_TRANSPOSE TransA, const unsigned int M,
-           const unsigned int N, const float alpha, const __fp16 *A,
-           const unsigned int lda, const __fp16 *X, const int incX,
-           const float beta, __fp16 *Y, const int incY);
-
 unsigned int isamax(const unsigned int N, const float *X, const int incX);
 
-unsigned int isamax(const unsigned int N, const __fp16 *X, const int incX);
-
 } /* namespace nntrainer */
 #endif /* __cplusplus */
 #endif /* __BLAS_INTERFACE_H__ */
index 47bc9be..834d351 100644 (file)
@@ -79,7 +79,9 @@ public:
   /**
    * @brief  Get address
    */
-  template <typename T = float> T *getAddr() const { return (T *)address; }
+  template <typename T = float> T *getAddr() const {
+    return static_cast<T *>(address);
+  }
 
   /**
    * @brief  Validate memory data
index 0bf5290..86a81d3 100644 (file)
@@ -36,7 +36,6 @@
 #include <stdio.h>
 
 #include <lazy_tensor.h>
-#include <nntrainer_log.h>
 #include <tensor.h>
 #include <util_func.h>
 
@@ -93,7 +92,7 @@ struct Tensor::BroadcastInfo {
   int buffer_axis;          /**< the smallest axis that should be looped.
                                  -1 means no loop needed*/
   std::array<unsigned int, TensorDim::MAXDIM>
-    strides;                /**< modified strides for the loop */
+    strides; /**< modified strides for the loop */
   nntrainer::TensorDim::TensorType tensor_type;
 };
 
@@ -128,7 +127,8 @@ public:
   SrcSharedTensor() : src(nullptr), off(0) {}
 
   SrcSharedTensor(const Tensor *tensor, size_t offset) :
-    src(tensor), off(offset) {}
+    src(tensor),
+    off(offset) {}
 
   /**
    * @brief   Get the allocated src tensor
@@ -168,16 +168,20 @@ void Tensor::allocate() {
     if (getDataType() == ml::train::TensorDim::DataType::FP32) {
       mem_data = new MemoryData((void *)(new float[dim.getDataLen()]()));
       data = std::shared_ptr<MemoryData>(mem_data, [](auto *mem_data) {
-        delete[] (float *)mem_data->getAddr();
+        delete[](float *) mem_data->getAddr();
         delete mem_data;
       });
 
     } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       mem_data = new MemoryData((void *)(new __fp16[dim.getDataLen()]()));
       data = std::shared_ptr<MemoryData>(mem_data, [](auto *mem_data) {
-        delete[] (__fp16 *)mem_data->getAddr();
+        delete[](__fp16 *) mem_data->getAddr();
         delete mem_data;
       });
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
     offset = 0;
     initialize();
@@ -211,6 +215,7 @@ bool Tensor::operator==(const Tensor &rhs) const {
         return false;
     }
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *_data = getData<__fp16>();
     const __fp16 *_rdata = rhs.getData<__fp16>();
     for (size_t i = 0; i < len; ++i) {
@@ -219,6 +224,9 @@ bool Tensor::operator==(const Tensor &rhs) const {
           std::fabs(_data[i] - _rdata[i]) > epsilon)
         return false;
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 
   return true;
@@ -249,8 +257,12 @@ void Tensor::setRandBernoulli(float probability) {
     setDist<float, std::bernoulli_distribution>(
       std::bernoulli_distribution(probability));
   } else if (this->getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     setDist<__fp16, std::bernoulli_distribution>(
       std::bernoulli_distribution((__fp16)probability));
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -345,12 +357,16 @@ Tensor &Tensor::multiply_strided(Tensor const &m, Tensor &output,
     NNTR_THROW_IF(output.getData<float>() == nullptr, std::invalid_argument)
       << output.getName() << " is not allocated";
   } else if (getDataType() == Tdatatype::FP16) {
+#ifdef ENABLE_FP16
     NNTR_THROW_IF(getData<__fp16>() == nullptr, std::invalid_argument)
       << getName() << " is not allocated";
     NNTR_THROW_IF(m.getData<__fp16>() == nullptr, std::invalid_argument)
       << m.getName() << " is not allocated";
     NNTR_THROW_IF(output.getData<__fp16>() == nullptr, std::invalid_argument)
       << output.getName() << " is not allocated";
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 
   // Format NCHW Case
@@ -386,6 +402,7 @@ Tensor &Tensor::multiply_strided(Tensor const &m, Tensor &output,
         }
       }
     } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       if (strides[3] != 1 || m.strides[3] != 1 || output.strides[3] != 1 ||
           beta != 0.0) {
         for (unsigned int b = 0; b < batch(); ++b) {
@@ -413,6 +430,9 @@ Tensor &Tensor::multiply_strided(Tensor const &m, Tensor &output,
           }
         }
       }
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
   } else { // Format NHWC Case
     if (getDataType() == Tdatatype::FP32) {
@@ -446,6 +466,7 @@ Tensor &Tensor::multiply_strided(Tensor const &m, Tensor &output,
         }
       }
     } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       if (strides[3] != 1 || m.strides[3] != 1 || output.strides[3] != 1 ||
           beta != 0.0) {
         for (unsigned int b = 0; b < batch(); ++b) {
@@ -475,6 +496,9 @@ Tensor &Tensor::multiply_strided(Tensor const &m, Tensor &output,
           }
         }
       }
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
   }
 
@@ -514,12 +538,16 @@ Tensor &Tensor::add_strided(Tensor const &m, Tensor &output,
     NNTR_THROW_IF(output.getData<float>() == nullptr, std::invalid_argument)
       << output.getName() << " is not allocated";
   } else if (getDataType() == Tdatatype::FP16) {
+#ifdef ENABLE_FP16
     NNTR_THROW_IF(getData<__fp16>() == nullptr, std::invalid_argument)
       << getName() << " is not allocated";
     NNTR_THROW_IF(m.getData<__fp16>() == nullptr, std::invalid_argument)
       << m.getName() << " is not allocated";
     NNTR_THROW_IF(output.getData<__fp16>() == nullptr, std::invalid_argument)
       << output.getName() << " is not allocated";
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 
   // Format NCHW Case
@@ -553,6 +581,7 @@ Tensor &Tensor::add_strided(Tensor const &m, Tensor &output,
         }
       }
     } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       if (strides[3] != 1 || m.strides[3] != 1 || output.strides[3] != 1 ||
           beta != 0.0) {
         for (unsigned int b = 0; b < batch(); ++b) {
@@ -579,6 +608,9 @@ Tensor &Tensor::add_strided(Tensor const &m, Tensor &output,
           }
         }
       }
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
   } else { // Format NHWC Case
     if (getDataType() == Tdatatype::FP32) {
@@ -611,6 +643,7 @@ Tensor &Tensor::add_strided(Tensor const &m, Tensor &output,
         }
       }
     } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       if (strides[3] != 1 || m.strides[3] != 1 || output.strides[3] != 1 ||
           beta != 0.0) {
         for (unsigned int b = 0; b < batch(); ++b) {
@@ -639,6 +672,9 @@ Tensor &Tensor::add_strided(Tensor const &m, Tensor &output,
           }
         }
       }
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
   }
   return output;
@@ -656,9 +692,13 @@ int Tensor::multiply_i(float const &value) {
 
     sscal(len, value, data, 1);
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     __fp16 *data = getData<__fp16>();
     unsigned int len = size();
     sscal(len, value, data, 1);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
   return ML_ERROR_NONE;
 }
@@ -674,8 +714,12 @@ Tensor &Tensor::multiply(float const &value, Tensor &out) const {
     auto f = std::bind(std::multiplies<float>(), std::placeholders::_1, value);
     return apply(f, out);
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = std::bind(std::multiplies<__fp16>(), std::placeholders::_1, value);
     return apply(f, out);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
   return out;
 }
@@ -736,6 +780,7 @@ Tensor &Tensor::multiply(Tensor const &m, Tensor &output,
     return output;
 
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = [&](const BroadcastInfo &e, const __fp16 *buf, const __fp16 *m_buf,
                  __fp16 *out_buf) {
       if (e.strides[3] == 1 && output.strides[3] == 1 && strides[3] == 1 &&
@@ -763,6 +808,9 @@ Tensor &Tensor::multiply(Tensor const &m, Tensor &output,
 
     apply_broadcast(m, f, output);
     return output;
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
   return output;
 }
@@ -830,6 +878,7 @@ Tensor &Tensor::divide(Tensor const &m, Tensor &output) const {
 
     apply_broadcast(m, f, output);
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = [&](const BroadcastInfo &e, const __fp16 *buf, const __fp16 *m_buf,
                  __fp16 *out_buf) {
       if (e.strides[3] == 1 && output.strides[3] == 1 && strides[3] == 1) {
@@ -850,6 +899,9 @@ Tensor &Tensor::divide(Tensor const &m, Tensor &output) const {
       << getName() << " is not contiguous, cannot divide";
 
     apply_broadcast(m, f, output);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
   return output;
 }
@@ -870,8 +922,12 @@ Tensor &Tensor::add(float const &value, Tensor &out) const {
     auto f = std::bind(std::plus<float>(), std::placeholders::_1, value);
     return apply(f, out);
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = std::bind(std::plus<__fp16>(), std::placeholders::_1, value);
     return apply(f, out);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
   return out;
 }
@@ -896,8 +952,8 @@ int Tensor::add_i(Tensor const &m, float const alpha) {
       return ML_ERROR_INVALID_PARAMETER;
     }
 
-    return ML_ERROR_NONE;
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = [&](const BroadcastInfo &e, const __fp16 *buf, const __fp16 *m_buf,
                  __fp16 *out_buf) {
       saxpy(e.buffer_size, alpha, m_buf, e.strides[3], out_buf, strides[3]);
@@ -915,8 +971,12 @@ int Tensor::add_i(Tensor const &m, float const alpha) {
       return ML_ERROR_INVALID_PARAMETER;
     }
 
-    return ML_ERROR_NONE;
+#else
+    ml_loge("%s", "Error: enable-fp16 is not enabled");
+    return ML_ERROR_INVALID_PARAMETER;
+#endif
   }
+  return ML_ERROR_NONE;
 }
 
 Tensor Tensor::add(Tensor const &m, float const alpha) const {
@@ -947,6 +1007,7 @@ Tensor &Tensor::add(Tensor const &m, Tensor &output, float const alpha) const {
     };
     apply_broadcast(m, f, output);
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = [&](const BroadcastInfo &e, const __fp16 *buf, const __fp16 *m_buf,
                  __fp16 *out_buf) {
       if (e.strides[3] == 1 && strides[3] == 1 && strides[3] == 1 &&
@@ -963,6 +1024,9 @@ Tensor &Tensor::add(Tensor const &m, Tensor &output, float const alpha) const {
       }
     };
     apply_broadcast(m, f, output);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
   return output;
 }
@@ -983,9 +1047,14 @@ Tensor &Tensor::subtract(float const &value, Tensor &out) const {
     auto f = std::bind(std::minus<float>(), std::placeholders::_1, value);
     return apply(f, out);
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = std::bind(std::minus<__fp16>(), std::placeholders::_1, value);
     return apply(f, out);
+#else
+    ml_loge("%s", "Error: enable-fp16 is not enabled");
+#endif
   }
+  return out; // shouldn't reach
 }
 
 int Tensor::subtract_i(Tensor const &m) { return add_i(m, -1); }
@@ -1012,9 +1081,14 @@ Tensor &Tensor::pow(float exponent, Tensor &out) const {
     return apply(f, out);
   }
   if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto f = [exponent](__fp16 in) { return powf(in, exponent); };
     return apply(f, out);
+#else
+    ml_loge("%s", "Error: enable-fp16 is not enabled");
+#endif
   }
+  return out;
 }
 
 Tensor Tensor::getBatchSlice(size_t offset, unsigned int size) const {
@@ -1135,7 +1209,8 @@ std::vector<Tensor> Tensor::split(std::vector<size_t> sizes, int axis) {
     ret_dims[i].setTensorDim(axis, sizes[i]);
   }
 
-  bool is_format_nchw = (dim.getFormat() == Tformat::NCHW);
+  bool is_format_nchw = (dim.getFormat() == Tformat::NCHW) ? true : false;
+  std::vector<Tensor> ret;
 
   if (getDataType() == ml::train::TensorDim::DataType::FP32) {
     auto iter_value = [this, is_format_nchw](
@@ -1155,7 +1230,6 @@ std::vector<Tensor> Tensor::split(std::vector<size_t> sizes, int axis) {
       return value;
     };
 
-    std::vector<Tensor> ret;
     ret.reserve(num_size);
 
     unsigned int accumulated_size = 0;
@@ -1214,10 +1288,9 @@ std::vector<Tensor> Tensor::split(std::vector<size_t> sizes, int axis) {
         return iter_value(loc, end_loc, reset_dim_arr);
       });
     }
-
-    return ret;
   }
   if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto iter_value =
       [this, is_format_nchw](
         std::array<size_t, 4> &loc, const std::array<size_t, 4> &end_loc,
@@ -1236,7 +1309,6 @@ std::vector<Tensor> Tensor::split(std::vector<size_t> sizes, int axis) {
       return value;
     };
 
-    std::vector<Tensor> ret;
     ret.reserve(num_size);
 
     unsigned int accumulated_size = 0;
@@ -1296,8 +1368,12 @@ std::vector<Tensor> Tensor::split(std::vector<size_t> sizes, int axis) {
       });
     }
 
-    return ret;
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
+
+  return ret;
 }
 
 Tensor Tensor::cat(const std::vector<Tensor> &tensors, int axis) {
@@ -1312,6 +1388,7 @@ Tensor Tensor::cat(const std::vector<Tensor> &tensors, int axis) {
   NNTR_THROW_IF(tensors.empty(), std::invalid_argument)
     << "given tensor vector is empty";
 
+  Tensor ret;
   auto ref_dim = tensors.front().getDim();
   bool is_format_nchw = (ref_dim.getFormat() == Tformat::NCHW);
   ref_dim.setTensorDim(axis, 1);
@@ -1352,7 +1429,7 @@ Tensor Tensor::cat(const std::vector<Tensor> &tensors, int axis) {
     auto ret_dim = ref_dim;
     ret_dim.setTensorDim(axis, axis_dim);
 
-    auto ret = Tensor(ret_dim);
+    ret = Tensor(ret_dim);
 
     std::array<unsigned, 4> loc = {0, 0, 0, 0};
     for (auto &t : tensors) {
@@ -1387,8 +1464,9 @@ Tensor Tensor::cat(const std::vector<Tensor> &tensors, int axis) {
       }
     }
 
-    return ret;
+    // return ret;
   } else if (ref_dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     auto iter_value =
       [is_format_nchw](std::array<unsigned, 4> &loc,
                        const std::array<unsigned, 4> &start_loc, Tensor &t,
@@ -1411,7 +1489,7 @@ Tensor Tensor::cat(const std::vector<Tensor> &tensors, int axis) {
     auto ret_dim = ref_dim;
     ret_dim.setTensorDim(axis, axis_dim);
 
-    auto ret = Tensor(ret_dim);
+    ret = Tensor(ret_dim);
 
     std::array<unsigned, 4> loc = {0, 0, 0, 0};
     for (auto &t : tensors) {
@@ -1446,8 +1524,11 @@ Tensor Tensor::cat(const std::vector<Tensor> &tensors, int axis) {
       }
     }
 
-    return ret;
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
+  return ret;
 }
 
 void Tensor::makeSharedDataTensor(const Tensor &src, size_t offset) {
@@ -1496,6 +1577,7 @@ void Tensor::apply_broadcast(
   return apply_broadcast_util(m, v_func, output, this->computeBroadcastInfo(m));
 }
 
+#ifdef ENABLE_FP16
 void Tensor::apply_broadcast(
   Tensor const &m,
   std::function<void(const BroadcastInfo &e, const __fp16 *, const __fp16 *,
@@ -1527,15 +1609,15 @@ void Tensor::apply_broadcast(
 
 void Tensor::apply_broadcast_util(
   Tensor const &m,
-  std::function<void(const BroadcastInfo &e, const float *, const float *,
-                     float *)>
+  std::function<void(const BroadcastInfo &e, const __fp16 *, const __fp16 *,
+                     __fp16 *)>
     v_func,
   Tensor &output, const BroadcastInfo &e, int cur_axis, size_t offset,
   size_t m_offset) const {
 
-  const float *buf = this->getData();
-  const float *m_buf = m.getData();
-  float *out_buf = output.getData();
+  const __fp16 *buf = this->getData<__fp16>();
+  const __fp16 *m_buf = m.getData<__fp16>();
+  __fp16 *out_buf = output.getData<__fp16>();
 
   if (e.buffer_axis == cur_axis) {
     v_func(e, buf + offset, m_buf + m_offset, out_buf + offset);
@@ -1543,13 +1625,7 @@ void Tensor::apply_broadcast_util(
   }
 
   cur_axis++;
-  uint continuity[4] = {0, 1, 2, 3};
-  if (getFormat() == Tformat::NHWC) {
-    continuity[1] = 2;
-    continuity[2] = 3;
-    continuity[3] = 1;
-  }
-  for (unsigned int i = 0; i < dim.getTensorDim(continuity[cur_axis]); ++i) {
+  for (unsigned int i = 0; i < dim.getTensorDim(cur_axis); ++i) {
     size_t next_offset = offset + i * strides[cur_axis];
     size_t next_m_offset = m_offset + i * e.strides[cur_axis];
     apply_broadcast_util(m, v_func, output, e, cur_axis, next_offset,
@@ -1557,17 +1633,19 @@ void Tensor::apply_broadcast_util(
   }
 }
 
+#endif
+
 void Tensor::apply_broadcast_util(
   Tensor const &m,
-  std::function<void(const BroadcastInfo &e, const __fp16 *, const __fp16 *,
-                     __fp16 *)>
+  std::function<void(const BroadcastInfo &e, const float *, const float *,
+                     float *)>
     v_func,
   Tensor &output, const BroadcastInfo &e, int cur_axis, size_t offset,
   size_t m_offset) const {
 
-  const __fp16 *buf = this->getData<__fp16>();
-  const __fp16 *m_buf = m.getData<__fp16>();
-  __fp16 *out_buf = output.getData<__fp16>();
+  const float *buf = this->getData();
+  const float *m_buf = m.getData();
+  float *out_buf = output.getData();
 
   if (e.buffer_axis == cur_axis) {
     v_func(e, buf + offset, m_buf + m_offset, out_buf + offset);
@@ -1575,7 +1653,13 @@ void Tensor::apply_broadcast_util(
   }
 
   cur_axis++;
-  for (unsigned int i = 0; i < dim.getTensorDim(cur_axis); ++i) {
+  uint continuity[4] = {0, 1, 2, 3};
+  if (getFormat() == Tformat::NHWC) {
+    continuity[1] = 2;
+    continuity[2] = 3;
+    continuity[3] = 1;
+  }
+  for (unsigned int i = 0; i < dim.getTensorDim(continuity[cur_axis]); ++i) {
     size_t next_offset = offset + i * strides[cur_axis];
     size_t next_m_offset = m_offset + i * e.strides[cur_axis];
     apply_broadcast_util(m, v_func, output, e, cur_axis, next_offset,
@@ -1604,6 +1688,7 @@ Tensor Tensor::sum_by_batch() const {
     sgemv(CblasRowMajor, CblasNoTrans, batch, feat_len, 1, data, feat_len,
           ones.getData<float>(), 1, 0.0, rdata, 1);
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
     __fp16 *rdata = ret.getData<__fp16>();
 
@@ -1611,6 +1696,9 @@ Tensor Tensor::sum_by_batch() const {
     ones.setValue((__fp16)1.0);
     sgemv(CblasRowMajor, CblasNoTrans, batch, feat_len, 1, data, feat_len,
           ones.getData<__fp16>(), 1, 0.0, rdata, 1);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 
   return ret;
@@ -1734,8 +1822,8 @@ Tensor &Tensor::sum(unsigned int axis, Tensor &ret, float alpha,
     default:
       throw std::out_of_range("Error: Dimension cannot exceed 3");
     }
-    return ret;
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
 
     NNTR_THROW_IF(!contiguous, std::invalid_argument)
@@ -1841,8 +1929,11 @@ Tensor &Tensor::sum(unsigned int axis, Tensor &ret, float alpha,
     default:
       throw std::out_of_range("Error: Dimension cannot exceed 3");
     }
-    return ret;
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
+  return ret;
 }
 
 Tensor Tensor::sum(const std::vector<unsigned int> &axes, float alpha) const {
@@ -2123,6 +2214,7 @@ Tensor &Tensor::dot(Tensor const &m, Tensor &result, bool trans, bool trans_m,
             ldb, beta, rdata, ldc);
     }
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
     const __fp16 *mdata = m.getData<__fp16>();
     __fp16 *rdata = result.getData<__fp16>();
@@ -2158,6 +2250,9 @@ Tensor &Tensor::dot(Tensor const &m, Tensor &result, bool trans, bool trans_m,
       sgemm(CblasRowMajor, transA, transB, M, N, K, alpha, data, lda, mdata,
             ldb, beta, rdata, ldc);
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 
   return result;
@@ -2233,7 +2328,8 @@ Tensor &Tensor::transpose(const std::string &direction, Tensor &out) const {
       }
       break;
     }
-  } else {
+  } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *inptr = getData<__fp16>();
     __fp16 *outptr = out.getData<__fp16>();
     switch (indexI) {
@@ -2283,6 +2379,9 @@ Tensor &Tensor::transpose(const std::string &direction, Tensor &out) const {
       }
       break;
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 
   return out;
@@ -2312,6 +2411,7 @@ void Tensor::dropout_mask(float dropout) {
         data_[i] = 0.0;
     }
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     __fp16 scale = 1.0 / (1 - dropout);
     __fp16 *data_ = getData<__fp16>();
     for (unsigned int i = 0; i < size(); ++i) {
@@ -2320,6 +2420,9 @@ void Tensor::dropout_mask(float dropout) {
       else
         data_[i] = 0.0;
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -2342,11 +2445,15 @@ void Tensor::filter_mask(const Tensor &mask_len, bool reverse) {
       std::fill(addr, addr + (*mask_len_val), en_mask_val);
     }
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     for (unsigned int b = 0; b < batch(); b++) {
       __fp16 *addr = getAddress<__fp16>(b, 0, 0, 0);
       const uint *mask_len_val = mask_len.getAddress<uint>(b, 0, 0, 0);
       std::fill(addr, addr + (*mask_len_val), (__fp16)en_mask_val);
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -2376,6 +2483,7 @@ void Tensor::zoneout_mask(Tensor &opposite, float zoneout) {
       }
     }
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     __fp16 zoneout_fp16 = (__fp16)zoneout;
     opposite.setRandBernoulli(zoneout_fp16);
 
@@ -2389,6 +2497,9 @@ void Tensor::zoneout_mask(Tensor &opposite, float zoneout) {
         data[i] = (__fp16)1.0;
       }
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -2498,6 +2609,7 @@ void Tensor::print(std::ostream &out) const {
       out.copyfmt(init);
     }
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
     unsigned int len = size();
     out << "data addr: " << data << '\n';
@@ -2542,6 +2654,9 @@ void Tensor::print(std::ostream &out) const {
       }
       out.copyfmt(init);
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -2641,19 +2756,29 @@ void Tensor::copy(const void *buf) {
   NNTR_THROW_IF(!contiguous, std::invalid_argument)
     << getName() << "Tensor is not contiguous, cannot copy.";
 
-  if (getDataType() == ml::train::TensorDim::DataType::FP16 &&
-      buf == getData<__fp16>()) {
-    return;
-  } else if (getDataType() == ml::train::TensorDim::DataType::FP32 &&
-             buf == getData()) {
-    return;
+  if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
+    if (buf == getData<__fp16>()) {
+      return;
+    }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
+  } else if (getDataType() == ml::train::TensorDim::DataType::FP32) {
+    if (buf == getData()) {
+      return;
+    }
   }
   // std::string type_ =
   //   (getDataType() == ml::train::TensorDim::DataType::FP16) ? "FP16" : "NO";
   // std::cout << type_ << std::endl;
 
   if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     scopy(size(), (__fp16 *)buf, 1, getData<__fp16>(), 1);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   } else if (getDataType() == ml::train::TensorDim::DataType::FP32) {
     scopy(size(), (float *)buf, 1, getData<float>(), 1);
   }
@@ -2672,7 +2797,8 @@ void Tensor::copy_with_stride(const Tensor &from) {
           }
         }
       }
-    } else {
+    } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       for (unsigned int b = 0; b < batch(); ++b) {
         for (unsigned int c = 0; c < channel(); ++c) {
           for (unsigned int h = 0; h < height(); ++h) {
@@ -2682,6 +2808,9 @@ void Tensor::copy_with_stride(const Tensor &from) {
           }
         }
       }
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
   } else {
     Tensor t = Tensor(from.getDim(), true);
@@ -2695,7 +2824,8 @@ void Tensor::copy_with_stride(const Tensor &from) {
           }
         }
       }
-    } else {
+    } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       for (unsigned int b = 0; b < batch(); ++b) {
         for (unsigned int c = 0; c < channel(); ++c) {
           for (unsigned int h = 0; h < height(); ++h) {
@@ -2705,6 +2835,9 @@ void Tensor::copy_with_stride(const Tensor &from) {
           }
         }
       }
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
     swap(t, *this);
   }
@@ -2722,7 +2855,11 @@ void Tensor::copy(const Tensor &from) {
     if (getDataType() == ml::train::TensorDim::DataType::FP32) {
       copy(from.getData());
     } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
       copy(from.getData<__fp16>());
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
 
   } else {
@@ -2898,8 +3035,12 @@ void Tensor::setValue(float val) {
     float *data = getData<float>();
     std::fill(data, data + size(), val);
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     __fp16 *data = getData<__fp16>();
     std::fill(data, data + size(), (__fp16)val);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -2910,10 +3051,14 @@ void Tensor::setZero() {
     else
       apply_i([](float val) -> float { return 0; });
   } else if (dim.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     if (contiguous)
       sscal(size(), 0, getData<__fp16>(), 1);
     else
       apply_i([](__fp16 val) -> __fp16 { return 0; });
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -2936,6 +3081,7 @@ std::vector<unsigned int> Tensor::argmax() const {
     }
   }
   if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
     size_t batch_size = batch();
     size_t feature_len = dim.getFeatureLen();
@@ -2947,6 +3093,9 @@ std::vector<unsigned int> Tensor::argmax() const {
         std::max_element(data + b * feature_len, data + (b + 1) * feature_len);
       result[b] = std::distance(data, max_iter) - (b * feature_len);
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 
   return result;
@@ -2955,15 +3104,20 @@ std::vector<unsigned int> Tensor::argmax() const {
 float Tensor::l2norm() const {
   NNTR_THROW_IF(!contiguous, std::invalid_argument)
     << getName() << " is not contiguous, cannot get l2norm.";
-
+  float ret;
   unsigned int len = size();
   if (getDataType() == ml::train::TensorDim::DataType::FP32) {
     const float *data = getData<float>();
-    return snrm2(len, data, 1);
+    ret = snrm2(len, data, 1);
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
-    return snrm2(len, data, 1);
+    ret = snrm2(len, data, 1);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
+  return ret;
 }
 
 float Tensor::max_abs() const {
@@ -2971,18 +3125,24 @@ float Tensor::max_abs() const {
     << getName() << " is not contiguous, cannot get max_abs.";
 
   unsigned int len = size();
+  float ret;
   if (getDataType() == ml::train::TensorDim::DataType::FP32) {
     const float *data = getData<float>();
 
     unsigned int idx = isamax(len, data, 1);
-    return *(data + idx);
+    ret = *(data + idx);
 
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
 
     unsigned int idx = isamax(len, data, 1);
-    return *(data + idx);
+    ret = *(data + idx);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
+  return ret;
 }
 
 Tensor &Tensor::normalization(Tensor &output) const {
@@ -3014,6 +3174,7 @@ void Tensor::normalization_i() {
       this->divide_i(max - min);
     }
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     const __fp16 *data = getData<__fp16>();
 
     auto bounds = std::minmax_element(data, data + size());
@@ -3027,6 +3188,9 @@ void Tensor::normalization_i() {
       this->subtract_i(min);
       this->divide_i(max - min);
     }
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -3060,6 +3224,7 @@ void Tensor::standardization_i() {
     std_dev_by_batch.divide_i(dim.getFeatureLen());
     this->divide_i(std_dev_by_batch);
   } else if (getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     Tensor std_dev_by_batch(dim.batch(), 1, 1, 1);
     std_dev_by_batch.setZero();
     __fp16 *std_dev = std_dev_by_batch.getData<__fp16>();
@@ -3071,6 +3236,9 @@ void Tensor::standardization_i() {
 
     std_dev_by_batch.divide_i(dim.getFeatureLen());
     this->divide_i(std_dev_by_batch);
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
 }
 
@@ -3166,8 +3334,8 @@ Tensor Tensor::rotate_180(Tensor in) {
         }
       }
     }
-    return output;
   } else if (in.getDataType() == ml::train::TensorDim::DataType::FP16) {
+#ifdef ENABLE_FP16
     output.setZero();
     for (unsigned int i = 0; i < in.batch(); ++i) {
       for (unsigned int j = 0; j < in.channel(); ++j) {
@@ -3180,8 +3348,11 @@ Tensor Tensor::rotate_180(Tensor in) {
         }
       }
     }
-    return output;
+#else
+    throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
   }
+  return output;
 }
 
 } /* namespace nntrainer */
index eb1279f..887ea73 100644 (file)
@@ -37,6 +37,7 @@
 #include <iostream>
 #include <memory_data.h>
 #include <nntrainer_error.h>
+#include <nntrainer_log.h>
 #include <tensor_dim.h>
 #include <util_func.h>
 
@@ -267,6 +268,7 @@ public:
          ml::train::TensorDim::TensorType t_type) :
     Tensor(std::vector<std::decay<decltype(d)>::type>{d}, t_type){};
 
+#ifdef ENABLE_FP16
   Tensor(std::vector<std::vector<std::vector<std::vector<__fp16>>>> const &d,
          ml::train::TensorDim::TensorType t_type) {
 
@@ -337,6 +339,8 @@ public:
          ml::train::TensorDim::TensorType t_type) :
     Tensor(std::vector<std::decay<decltype(d)>::type>{d}, t_type){};
 
+#endif
+
   /**
    *  @brief  Copy constructor of Tensor.
    *  @param[in] Tensor &
@@ -1202,6 +1206,7 @@ public:
         }
       }
     } else if (dim.getDataType() == Tdatatype::FP16) {
+#ifdef ENABLE_FP16
       if (contiguous && output.contiguous) {
         const __fp16 *data = (getData<__fp16>());
         __fp16 *rdata = (output.getData<__fp16>());
@@ -1230,8 +1235,10 @@ public:
           }
         }
       }
+#else
+      throw std::invalid_argument("Error: enable-fp16 is not enabled");
+#endif
     }
-
     return output;
   };
 
@@ -1298,7 +1305,11 @@ public:
     if (getDataType() == Tdatatype::FP32) {
       getData<float>()[getIndex(batch, c, h, w)] = value;
     } else if (getDataType() == Tdatatype::FP16) {
+#ifdef ENABLE_FP16
       getData<__fp16>()[getIndex(batch, c, h, w)] = value;
+#else
+      ml_loge("%s", "Error: enable-fp16 is not enabled");
+#endif
     }
   }
 
@@ -1318,8 +1329,12 @@ public:
       getData<float>()[idx] *= beta;
       getData<float>()[idx] += value;
     } else if (dim.getDataType() == Tdatatype::FP16) {
+#ifdef ENABLE_FP16
       getData<__fp16>()[idx] *= beta;
       getData<__fp16>()[idx] += value;
+#else
+      ml_loge("%s", "Error: enable-fp16 is not enabled");
+#endif
     }
   }
 
@@ -1613,7 +1628,7 @@ public:
       return nullptr;
 
     data->validate();
-    return (T *)((data->getAddr<T>()) + offset);
+    return data->getAddr<T>() + offset;
   }
 
   /**
@@ -1625,7 +1640,7 @@ public:
       return nullptr;
 
     data->validate();
-    return (T *)(data->getAddr<T>() + offset);
+    return data->getAddr<T>() + offset;
   }
 
   /**
@@ -1636,10 +1651,10 @@ public:
     if (!data)
       return nullptr;
 
-    size_t index = idx * sizeof(T);
+    size_t index = idx;
 
     data->validate();
-    return (T *)(data->getAddr<T>() + offset + index);
+    return data->getAddr<T>() + offset + index;
   }
 
   void setDataType(Tdatatype d_type) { dim.setDataType(d_type); }
@@ -1669,7 +1684,7 @@ public:
   /**
    * @brief     return offset
    */
-  unsigned int getOffset() const { return offset; }
+  size_t getOffset() const { return offset; }
 
   /**
    * @brief     i data index
@@ -1750,7 +1765,7 @@ public:
    * @param buf the memory buffer
    * @param init intialize the buffer
    */
-  void setData(const std::shared_ptr<MemoryData> buf, unsigned int off = 0,
+  void setData(const std::shared_ptr<MemoryData> buf, size_t off = 0,
                bool init = false) {
     if (buf) {
       data = buf;
@@ -1794,7 +1809,7 @@ private:
   Tensor::Initializer initializer;
   std::string name; /**< name of the tensor */
   std::shared_ptr<MemoryData> data;
-  unsigned int offset;
+  size_t offset;
 
   /**<
    * When using shared_data with tensor, this stores the ptr of the source
@@ -1826,14 +1841,6 @@ private:
                        int cur_axis = -1, size_t offset = 0,
                        size_t m_offset = 0) const;
 
-  void apply_broadcast_util(
-    Tensor const &m,
-    std::function<void(const BroadcastInfo &e, const __fp16 *, const __fp16 *,
-                       __fp16 *)>
-      v_func,
-    Tensor &output, const BroadcastInfo &e, int cur_axis = -1,
-    size_t offset = 0, size_t m_offset = 0) const;
-
   /**
    * @brief Applies the given operator to the tensor with the passed argument
    *
@@ -1847,6 +1854,14 @@ private:
                                           const float *, float *)>
                          v_func,
                        Tensor &output) const;
+#ifdef ENABLE_FP16
+  void apply_broadcast_util(
+    Tensor const &m,
+    std::function<void(const BroadcastInfo &e, const __fp16 *, const __fp16 *,
+                       __fp16 *)>
+      v_func,
+    Tensor &output, const BroadcastInfo &e, int cur_axis = -1,
+    size_t offset = 0, size_t m_offset = 0) const;
 
   void
   apply_broadcast(Tensor const &m,
@@ -1854,7 +1869,7 @@ private:
                                      const __fp16 *, __fp16 *)>
                     v_func,
                   Tensor &output) const;
-
+#endif
   /**
    * @brief compute Loop info for broadcasting and vectorization
    *
index 90825d5..eff8159 100644 (file)
@@ -117,7 +117,11 @@ TensorDim &TensorDim::operator=(TensorDim &&rhs) noexcept {
 uint TensorDim::getDataTypeSize() const {
   switch (t_type.data_type) {
   case TensorDim::DataType::FP16:
+#ifdef ENABLE_FP16
     return sizeof(__fp16);
+#else
+    return 2;
+#endif
   case TensorDim::DataType::FP32:
     return sizeof(float);
   default:
index a1ec348..ba1021c 100644 (file)
@@ -60,7 +60,7 @@ Tensor *TensorPool::placeholder(const std::string &name, const TensorDim &dim) {
 Tensor *TensorPool::view(const std::string &name, const std::string &reference,
                          const TensorDim &dim,
                          const std::vector<unsigned int> &exec_order,
-                         TensorLifespan lifespan, const unsigned int offset) {
+                         TensorLifespan lifespan, const size_t offset) {
   auto &spec = getSourceSpec(reference);
   unsigned adjusted_offset = std::visit(
     [](const auto &s) {
index 25cb270..abd4a2f 100644 (file)
@@ -197,7 +197,7 @@ public:
   Tensor *view(const std::string &name, const std::string &reference,
                const TensorDim &dim,
                const std::vector<unsigned int> &exec_order,
-               TensorLifespan lifespan, const unsigned int offset = 0);
+               TensorLifespan lifespan, const size_t offset = 0);
 
   /**
    * @brief extend a tensor life as tensor is being shared.
index 8f1905a..117b02b 100644 (file)
@@ -650,7 +650,7 @@ struct TensorDataTypeInfo {
   static constexpr std::initializer_list<Enum> EnumList = {Enum::FP16,
                                                            Enum::FP32};
 
-  static constexpr const char *EnumStr[] = {"fp16", "fp32"};
+  static constexpr const char *EnumStr[] = {"FP16", "FP32"};
 };
 
 namespace props {
@@ -663,6 +663,10 @@ class TensorDataType final : public EnumProperty<TensorDataTypeInfo> {
 public:
   using prop_tag = enum_class_prop_tag;
   static constexpr const char *key = "tensor_type";
+  TensorDataType(
+    TensorDataTypeInfo::Enum value = TensorDataTypeInfo::Enum::FP32) {
+    set(value);
+  };
 };
 
 /**
@@ -682,7 +686,7 @@ public:
    */
   TensorFormat(const std::string &value = "NCHW") { set(value); };
 };
-  }
+} // namespace props
 
 } // namespace nntrainer
 
index daeae45..a22202c 100644 (file)
@@ -52,7 +52,7 @@ include $(BUILD_STATIC_LIBRARY)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := test_util
-LOCAL_CFLAGS := -Igoogletest/include -I../include -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti
+LOCAL_CFLAGS := -Igoogletest/include -I../include -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti -DENABLE_FP16=1
 LOCAL_CXXFLAGS      += -std=c++17 -frtti -fexceptions
 LOCAL_LDLIBS        := -llog -landroid -fopenmp -static-openmp
 
@@ -66,7 +66,7 @@ include $(BUILD_STATIC_LIBRARY)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := unittest_nntrainer_tensor
-LOCAL_CFLAGS := -Igoogletest/include -I../include -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti
+LOCAL_CFLAGS := -Igoogletest/include -I../include -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti  -DENABLE_FP16=1
 LOCAL_CXXFLAGS      += -std=c++17 -frtti -fexceptions
 LOCAL_LDLIBS        := -llog -landroid -fopenmp -static-openmp 
 
@@ -82,7 +82,7 @@ include $(BUILD_EXECUTABLE)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := unittest_nntrainer_tensor_fp16
-LOCAL_CFLAGS := -Igoogletest/include -I../include -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti
+LOCAL_CFLAGS := -Igoogletest/include -I../include -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti -DENABLE_FP16=1
 LOCAL_CXXFLAGS      += -std=c++17 -frtti -fexceptions
 LOCAL_LDLIBS        := -llog -landroid -fopenmp -static-openmp 
 
@@ -114,19 +114,19 @@ include $(BUILD_EXECUTABLE)
 
 # include $(CLEAR_VARS)
 
-LOCAL_MODULE := unittest_compiler
-# LOCAL_CFLAGS := -Igoogletest/include -I../include -I../unittest/compiler -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti -DNDK_BUILD=1
-LOCAL_CXXFLAGS      += -std=c++17 -frtti -fexceptions
-# LOCAL_LDLIBS        := -llog -landroid -fopenmp -static-openmp 
+LOCAL_MODULE := unittest_compiler
+LOCAL_CFLAGS := -Igoogletest/include -I../include -I../unittest/compiler -pthread -fexceptions -fopenmp -static-openmp -DMIN_CPP_VERSION=201703L -DNNTR_NUM_THREADS=1 -D__LOGGING__=1 -DENABLE_TEST=1 -DREDUCE_TOLERANCE=1 -march=armv8.2-a+fp16 -mfpu=neon-fp16 -mfloat-abi=softfp -O3 -frtti -DNDK_BUILD=1 -DENABLE_FP16=1
+LOCAL_CXXFLAGS      += -std=c++17 -frtti -fexceptions
+LOCAL_LDLIBS        := -llog -landroid -fopenmp -static-openmp
 
-LOCAL_SRC_FILES := \
-#     ../unittest/compiler/compiler_test_util.cpp \
-#     ../unittest/compiler/unittest_compiler.cpp \
-#     ../unittest/compiler/unittest_realizer.cpp \
+LOCAL_SRC_FILES := \
+     ../unittest/compiler/compiler_test_util.cpp \
+     ../unittest/compiler/unittest_compiler.cpp \
+     ../unittest/compiler/unittest_realizer.cpp \
 
-LOCAL_C_INCLUDES += $(NNTRAINER_INCLUDES)
+LOCAL_C_INCLUDES += $(NNTRAINER_INCLUDES)
 
-LOCAL_SHARED_LIBRARIES := nntrainer ccapi-nntrainer
-LOCAL_STATIC_LIBRARIES := googletest_main test_util
-include $(BUILD_EXECUTABLE)
+LOCAL_SHARED_LIBRARIES := nntrainer ccapi-nntrainer
+LOCAL_STATIC_LIBRARIES := googletest_main test_util
+include $(BUILD_EXECUTABLE)
 
diff --git a/test/unittest/jni/tests/nntrainer_test_util.cpp b/test/unittest/jni/tests/nntrainer_test_util.cpp
deleted file mode 100644 (file)
index 790616e..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/**
- * Copyright (C) 2019 Samsung Electronics Co., Ltd. All Rights Reserved.
- *
- * Licensed 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       nntrainer_test_util.cpp
- * @date       28 April 2020
- * @brief      This is util functions for test
- * @see                https://github.com/nnstreamer/nntrainer
- * @author     Jijoong Moon <jijoong.moon@samsung.com>
- * @bug                No known bugs except for NYI items
- *
- */
-
-#include "nntrainer_test_util.h"
-#include <app_context.h>
-#include <climits>
-#include <iostream>
-#include <layer_node.h>
-#include <multiout_realizer.h>
-#include <nntrainer_error.h>
-#include <random>
-#include <regex>
-#include <tensor.h>
-
-#define num_class 10
-#define batch_size 16
-#define feature_size 62720
-
-static std::mt19937 rng(0);
-
-/**
- * @brief replace string and save it in file
- * @param[in] from string to be replaced
- * @param[in] to string to be replaced to
- * @param[in] file file to perform the action on
- * @param[in] init_config file contents to be initialized with if file not found
- */
-void replaceString(const std::string &from, const std::string &to,
-                   const std::string file, std::string init_config) {
-  size_t start_pos = 0;
-  std::string s;
-  std::ifstream file_stream(file.c_str(), std::ifstream::in);
-  if (file_stream.good()) {
-    s.assign((std::istreambuf_iterator<char>(file_stream)),
-             std::istreambuf_iterator<char>());
-    file_stream.close();
-  } else {
-    s = init_config;
-  }
-  while ((start_pos = s.find(from, start_pos)) != std::string::npos) {
-    s.replace(start_pos, from.size(), to);
-    start_pos += to.size();
-  }
-
-  std::ofstream data_file(file.c_str());
-  data_file << s;
-  data_file.close();
-}
-
-/**
- * @brief     load data at specific position of file
- * @param[in] F  ifstream (input file)
- * @param[out] outVec
- * @param[out] outLabel
- * @param[in] id th data to get
- * @retval true/false false : end of data
- */
-static bool getData(std::ifstream &F, float *outVec, float *outLabel,
-                    unsigned int id) {
-  F.clear();
-  F.seekg(0, std::ios_base::end);
-  uint64_t file_length = F.tellg();
-
-  uint64_t position =
-    (uint64_t)((feature_size + num_class) * (uint64_t)id * sizeof(float));
-
-  if (position > file_length) {
-    return false;
-  }
-  F.seekg(position, std::ios::beg);
-  F.read((char *)outVec, sizeof(float) * feature_size);
-  F.read((char *)outLabel, sizeof(float) * num_class);
-
-  return true;
-}
-
-DataInformation::DataInformation(unsigned int num_samples,
-                                 const std::string &filename) :
-  count(0),
-  num_samples(num_samples),
-  file(filename, std::ios::in | std::ios::binary),
-  idxes(num_samples) {
-  std::iota(idxes.begin(), idxes.end(), 0);
-  std::shuffle(idxes.begin(), idxes.end(), rng);
-  rng.seed(0);
-  if (!file.good()) {
-    throw std::invalid_argument("given file is not good, filename: " +
-                                filename);
-  }
-}
-
-static auto getDataSize = [](const std::string &file_name) {
-  std::ifstream f(file_name, std::ios::in | std::ios::binary);
-  NNTR_THROW_IF(!f.good(), std::invalid_argument)
-    << "cannot find " << file_name;
-  f.seekg(0, std::ios::end);
-  long file_size = f.tellg();
-  return static_cast<unsigned int>(
-    file_size / ((num_class + feature_size) * sizeof(float)));
-};
-
-std::string train_filename = getResPath("trainingSet.dat", {"test"});
-std::string valid_filename = getResPath("trainingSet.dat", {"test"});
-
-DataInformation createTrainData() {
-  return DataInformation(getDataSize(train_filename), train_filename);
-}
-
-DataInformation createValidData() {
-  return DataInformation(getDataSize(valid_filename), valid_filename);
-}
-
-/**
- * @brief      get data which size is batch for train
- * @param[out] outVec
- * @param[out] outLabel
- * @param[out] last if the data is finished
- * @param[in] user_data private data for the callback
- * @retval status for handling error
- */
-int getSample(float **outVec, float **outLabel, bool *last, void *user_data) {
-  auto data = reinterpret_cast<DataInformation *>(user_data);
-
-  getData(data->file, *outVec, *outLabel, data->idxes.at(data->count));
-  data->count++;
-  if (data->count < data->num_samples) {
-    *last = false;
-  } else {
-    *last = true;
-    data->count = 0;
-    std::shuffle(data->idxes.begin(), data->idxes.end(), data->rng);
-  }
-
-  return ML_ERROR_NONE;
-}
-
-/**
- * @brief return a tensor filled with contant value with dimension
- */
-nntrainer::Tensor constant(float value, unsigned int batch,
-                           unsigned int channel, unsigned int height,
-                           unsigned int width) {
-  nntrainer::Tensor t(batch, channel, height, width);
-  t.setValue(value);
-
-  return t;
-}
-
-nntrainer::Tensor ranged(unsigned int batch, unsigned int channel,
-                         unsigned int height, unsigned int width,
-                         nntrainer::Tformat fm, nntrainer::DataType d_type) {
-  nntrainer::Tensor t(batch, channel, height, width, fm, d_type);
-  unsigned int i = 0;
-  if (d_type == nntrainer::DataType::FP32)
-    return t.apply([&](float in) { return i++; });
-  else if (d_type == nntrainer::DataType::FP16)
-    return t.apply([&](__fp16 in) { return i++; });
-}
-
-nntrainer::Tensor randUniform(unsigned int batch, unsigned int channel,
-                              unsigned int height, unsigned int width,
-                              float min, float max) {
-  nntrainer::Tensor t(batch, channel, height, width);
-  t.setRandUniform(min, max);
-  return t;
-}
-
-const std::string
-getResPath(const std::string &filename,
-           const std::initializer_list<const char *> fallback_base) {
-  static const char *prefix = std::getenv("NNTRAINER_RESOURCE_PATH");
-  static const char *fallback_prefix = "./res";
-
-  std::stringstream ss;
-  if (prefix != nullptr) {
-    ss << prefix << '/' << filename;
-    return ss.str();
-  }
-
-  ss << fallback_prefix;
-  for (auto &folder : fallback_base) {
-    ss << '/' << folder;
-  }
-
-  ss << '/' << filename;
-
-  return ss.str();
-}
-
-nntrainer::GraphRepresentation
-makeGraph(const std::vector<LayerRepresentation> &layer_reps) {
-  static auto &ac = nntrainer::AppContext::Global();
-  nntrainer::GraphRepresentation graph_rep;
-
-  for (const auto &layer_representation : layer_reps) {
-    /// @todo Use unique_ptr here
-    std::shared_ptr<nntrainer::LayerNode> layer = nntrainer::createLayerNode(
-      ac.createObject<nntrainer::Layer>(layer_representation.first),
-      layer_representation.second);
-    graph_rep.push_back(layer);
-  }
-
-  return graph_rep;
-}
-
-nntrainer::GraphRepresentation makeCompiledGraph(
-  const std::vector<LayerRepresentation> &layer_reps,
-  std::vector<std::unique_ptr<nntrainer::GraphRealizer>> &realizers,
-  const std::string &loss_layer) {
-  static auto &ac = nntrainer::AppContext::Global();
-
-  nntrainer::GraphRepresentation graph_rep;
-  auto model_graph = nntrainer::NetworkGraph();
-
-  for (auto &layer_representation : layer_reps) {
-    std::shared_ptr<nntrainer::LayerNode> layer = nntrainer::createLayerNode(
-      ac.createObject<nntrainer::Layer>(layer_representation.first),
-      layer_representation.second);
-    graph_rep.push_back(layer);
-  }
-
-  for (auto &realizer : realizers) {
-    graph_rep = realizer->realize(graph_rep);
-  }
-
-  for (auto &layer : graph_rep) {
-    model_graph.addLayer(layer);
-  }
-
-  model_graph.compile(loss_layer);
-
-  graph_rep.clear();
-  for (auto &node : model_graph.getLayerNodes()) {
-    graph_rep.push_back(node);
-  }
-
-  return graph_rep;
-}
-
-void sizeCheckedReadTensor(nntrainer::Tensor &t, std::ifstream &file,
-                           const std::string &error_msg) {
-  unsigned int sz = 0;
-  nntrainer::checkedRead(file, (char *)&sz, sizeof(unsigned));
-  NNTR_THROW_IF(t.getDim().getDataLen() != sz, std::invalid_argument)
-    << "[ReadFail] dimension does not match at " << error_msg << " sz: " << sz
-    << " dimsize: " << t.getDim().getDataLen() << '\n';
-  t.read(file);
-}
diff --git a/test/unittest/jni/tests/nntrainer_test_util.h b/test/unittest/jni/tests/nntrainer_test_util.h
deleted file mode 100644 (file)
index 3a5767c..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/**
- * Copyright (C) 2019 Samsung Electronics Co., Ltd. All Rights Reserved.
- *
- * Licensed 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       nntrainer_test_util.h
- * @date       28 April 2020
- * @brief      This is util functions for test
- * @see                https://github.com/nnstreamer/nntrainer
- * @author     Jijoong Moon <jijoong.moon@samsung.com>
- * @bug                No known bugs except for NYI items
- *
- */
-
-#ifndef __NNTRAINER_TEST_UTIL_H__
-#define __NNTRAINER_TEST_UTIL_H__
-#ifdef __cplusplus
-
-#include <errno.h>
-#include <fstream>
-#include <string.h>
-#include <unordered_map>
-#include <utility>
-
-#include <compiler_fwd.h>
-#include <ini_wrapper.h>
-#include <neuralnet.h>
-#include <nntrainer_error.h>
-#include <nntrainer_log.h>
-#include <realizer.h>
-#include <tensor.h>
-
-/** tolerance is reduced for packaging, but CI runs at full tolerance */
-#ifdef REDUCE_TOLERANCE
-#define tolerance 1.0e-4
-#else
-#define tolerance 1.0e-5
-#endif
-
-/** Enum values to get model accuracy and loss. Sync with internal CAPI header
- */
-#define ML_TRAIN_SUMMARY_MODEL_TRAIN_LOSS 101
-#define ML_TRAIN_SUMMARY_MODEL_VALID_LOSS 102
-#define ML_TRAIN_SUMMARY_MODEL_VALID_ACCURACY 103
-
-/** Gtest compatibility for parameterize google test API  */
-#ifdef GTEST_BACKPORT
-#define GTEST_PARAMETER_TEST INSTANTIATE_TEST_CASE_P
-#else
-#define GTEST_PARAMETER_TEST INSTANTIATE_TEST_SUITE_P
-#endif
-
-/**
- * @brief This class wraps IniWrapper. This generates real ini file when
- * construct, and remove real ini file when destroy
- *
- */
-class ScopedIni {
-public:
-  /**
-   * @brief Construct a new Scoped Ini object
-   *
-   * @param ini_ ini wrapper
-   */
-  ScopedIni(const nntrainer::IniWrapper &ini_) : ini(ini_) { ini.save_ini(); }
-
-  /**
-   * @brief Construct a new Scoped Ini object
-   *
-   * @param name_ name
-   * @param sections_ sequenes of sections to save
-   */
-  ScopedIni(const std::string &name_,
-            const nntrainer::IniWrapper::Sections &sections_) :
-    ini(name_, sections_) {
-    ini.save_ini();
-  }
-
-  /**
-   * @brief Get the Ini Name object
-   *
-   * @return std::string ini name
-   */
-  std::string getIniName() { return ini.getIniName(); }
-
-  /**
-   * @brief Destroy the Scoped Ini object
-   *
-   */
-  ~ScopedIni() { ini.erase_ini(); }
-
-private:
-  nntrainer::IniWrapper ini;
-};
-
-#define GEN_TEST_INPUT(input, eqation_i_j_k_l) \
-  do {                                         \
-    for (int i = 0; i < batch; ++i) {          \
-      for (int j = 0; j < channel; ++j) {      \
-        for (int k = 0; k < height; ++k) {     \
-          for (int l = 0; l < width; ++l) {    \
-            float val = eqation_i_j_k_l;       \
-            input.setValue(i, j, k, l, val);   \
-          }                                    \
-        }                                      \
-      }                                        \
-    }                                          \
-  } while (0)
-
-/**
- * @brief return a tensor filled with contant value with dimension
- */
-nntrainer::Tensor constant(float value, unsigned int batch, unsigned channel,
-                           unsigned height, unsigned width);
-
-/**
- * @brief return a tensor filled with ranged value with given dimension
- */
-nntrainer::Tensor
-ranged(unsigned int batch, unsigned channel, unsigned height, unsigned width,
-       nntrainer::Tformat fm = nntrainer::Tformat::NCHW,
-       nntrainer::DataType d_type = nntrainer::DataType::FP32);
-
-/**
- * @brief return a tensor filled with random value with given dimension
- */
-nntrainer::Tensor randUniform(unsigned int batch, unsigned channel,
-                              unsigned height, unsigned width, float min = -1,
-                              float max = 1);
-
-/**
- * @brief replace string and save in file
- * @param[in] from string to be replaced
- * @param[in] to string to repalce with
- * @param[in] n file name to save
- * @retval void
- */
-void replaceString(const std::string &from, const std::string &to,
-                   const std::string n, std::string str);
-
-/**
- * @brief UserData which stores information used to feed data from data callback
- *
- */
-class DataInformation {
-public:
-  /**
-   * @brief Construct a new Data Information object
-   *
-   * @param num_samples number of data
-   * @param filename file name to read from
-   */
-  DataInformation(unsigned int num_samples, const std::string &filename);
-  unsigned int count;
-  unsigned int num_samples;
-  std::ifstream file;
-  std::vector<unsigned int> idxes;
-  std::mt19937 rng;
-};
-
-/**
- * @brief Create a user data for training
- *
- * @return DataInformation
- */
-DataInformation createTrainData();
-
-/**
- * @brief Create a user data for validataion
- *
- * @return DataInformation
- */
-DataInformation createValidData();
-
-/**
- * @brief      get data which size is batch
- * @param[out] outVec
- * @param[out] outLabel
- * @param[out] last if the data is finished
- * @param[in] user_data private data for the callback
- * @retval status for handling error
- */
-int getSample(float **outVec, float **outLabel, bool *last, void *user_data);
-
-/**
- * @brief Get the Res Path object
- * @note if NNTRAINER_RESOURCE_PATH environment variable is given, @a
- * fallback_base is ignored and NNTRINAER_RESOURCE_PATH is directly used as a
- * base
- *
- * @param filename filename if omitted, ${prefix}/${base} will be returned
- * @param fallback_base list of base to attach when NNTRAINER_RESOURCE_PATH is
- * not given
- * @return const std::string path,
- */
-const std::string
-getResPath(const std::string &filename,
-           const std::initializer_list<const char *> fallback_base = {});
-
-using LayerRepresentation = std::pair<std::string, std::vector<std::string>>;
-
-/**
- * @brief make graph of a representation
- *
- * @param layer_reps layer representation (pair of type, properties)
- * @return nntrainer::GraphRepresentation synthesized graph representation
- */
-nntrainer::GraphRepresentation
-makeGraph(const std::vector<LayerRepresentation> &layer_reps);
-
-/**
- * @brief make graph of a representation after compile
- *
- * @param layer_reps layer representation (pair of type, properties)
- * @param realizers GraphRealizers to modify graph before compile
- * @param loss_layer loss layer to compile with
- * @return nntrainer::GraphRepresentation synthesized graph representation
- */
-nntrainer::GraphRepresentation makeCompiledGraph(
-  const std::vector<LayerRepresentation> &layer_reps,
-  std::vector<std::unique_ptr<nntrainer::GraphRealizer>> &realizers,
-  const std::string &loss_layer = "");
-
-/**
- * @brief read tensor after reading tensor size
- *
- * @param t tensor to fill
- * @param file file name
- * @param error_msg error msg
- */
-void sizeCheckedReadTensor(nntrainer::Tensor &t, std::ifstream &file,
-                           const std::string &error_msg = "");
-
-#endif /* __cplusplus */
-#endif /* __NNTRAINER_TEST_UTIL_H__ */
diff --git a/test/unittest/jni/tests/unittest_nntrainer_tensor.cpp b/test/unittest/jni/tests/unittest_nntrainer_tensor.cpp
deleted file mode 100644 (file)
index 0773e30..0000000
+++ /dev/null
@@ -1,4067 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-/**
- * Copyright (C) 2020 Jijoong Moon <jijoong.moon@samsung.com>
- *
- * @file        unittest_nntrainer_tensor.cpp
- * @date        03 June 2020
- * @brief       Unit test utility for tensor.
- * @see         https://github.com/nnstreamer/nntrainer
- * @author      Jijoong Moon <jijoong.moon@samsung.com>
- * @bug         No known bugs
- */
-#include <gtest/gtest.h>
-
-#include "nntrainer_test_util.h"
-#include "util_func.h"
-#include <fstream>
-#include <nntrainer_error.h>
-#include <tensor.h>
-#include <tensor_dim.h>
-#include <iostream>
-
-TEST(nntrainer_TensorDim, ctor_initializer_p) {
-  unsigned int b = 3;
-  unsigned int c = 2;
-  unsigned int h = 4;
-  unsigned int w = 5;
-
-  nntrainer::TensorDim t = {w};
-  EXPECT_EQ(nntrainer::TensorDim(1, 1, 1, w), t);
-
-  t = {h, w};
-  EXPECT_EQ(nntrainer::TensorDim(1, 1, h, w), t);
-
-  t = {c, h, w};
-  EXPECT_EQ(nntrainer::TensorDim(1, c, h, w), t);
-
-  t = {b, c, h, w};
-  EXPECT_EQ(nntrainer::TensorDim(b, c, h, w), t);
-}
-
-TEST(nntrainer_TensorDim, ctor_initializer_nhwc_p) {
-  unsigned int b = 3;
-  unsigned int c = 2;
-  unsigned int h = 4;
-  unsigned int w = 5;
-
-  nntrainer::TensorDim t = {c};
-  EXPECT_EQ(nntrainer::TensorDim(1, 1, 1, c), t);
-
-  t = {w, c};
-  EXPECT_EQ(nntrainer::TensorDim(1, 1, w, c), t);
-
-  t = {h, w, c};
-  EXPECT_EQ(nntrainer::TensorDim(1, h, w, c), t);
-
-  t = {b, h, w, c};
-  EXPECT_EQ(nntrainer::TensorDim(b, h, w, c), t);
-}
-
-TEST(nntrianer_TensorDim, effective_dimension_p) {
-  nntrainer::TensorDim t(3, 2, 4, 5, nntrainer::Tformat::NCHW);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2, 4, 5}));
-
-  t.setEffDimFlag(0b1101);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2, 5}));
-
-  t.setEffDimFlag(0b0011);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({4, 5}));
-
-  t.setEffDimFlag(0b1111);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2, 4, 5}));
-
-  t.setEffDimFlag(0b1100);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2}));
-
-  t.setDynDimFlag(0b1100);
-  EXPECT_EQ(t.getEffectiveDimension(true), std::vector<int>({-1, -1}));
-
-  auto copied_t = t;
-  EXPECT_EQ(copied_t.getEffectiveDimension(), std::vector<int>({3, 2}));
-  EXPECT_EQ(copied_t.getEffectiveDimension(true), std::vector<int>({-1, -1}));
-
-  auto moved_t = std::move(copied_t);
-  EXPECT_EQ(moved_t.getEffectiveDimension(), std::vector<int>({3, 2}));
-  EXPECT_EQ(moved_t.getEffectiveDimension(true), std::vector<int>({-1, -1}));
-}
-
-TEST(nntrianer_TensorDim, effective_dimension_nhwc_p) {
-  nntrainer::TensorDim t(3, 2, 4, 5, nntrainer::Tformat::NHWC);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2, 4, 5}));
-
-  t.setEffDimFlag(0b1101);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2, 5}));
-
-  t.setEffDimFlag(0b0011);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({4, 5}));
-
-  t.setEffDimFlag(0b1111);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2, 4, 5}));
-
-  t.setEffDimFlag(0b1100);
-  EXPECT_EQ(t.getEffectiveDimension(), std::vector<int>({3, 2}));
-
-  t.setDynDimFlag(0b1100);
-  EXPECT_EQ(t.getEffectiveDimension(true), std::vector<int>({-1, -1}));
-
-  auto copied_t = t;
-  EXPECT_EQ(copied_t.getEffectiveDimension(), std::vector<int>({3, 2}));
-  EXPECT_EQ(copied_t.getEffectiveDimension(true), std::vector<int>({-1, -1}));
-
-  auto moved_t = std::move(copied_t);
-  EXPECT_EQ(moved_t.getEffectiveDimension(), std::vector<int>({3, 2}));
-  EXPECT_EQ(moved_t.getEffectiveDimension(true), std::vector<int>({-1, -1}));
-}
-
-TEST(nntrainer_TensorDim, ctor_initializer_n) {
-  EXPECT_THROW(nntrainer::TensorDim t({1, 2, 3, 4, 5}), std::invalid_argument);
-}
-
-TEST(nntrainer_TensorDim, ctor_initializer_nhwc_n) {
-  EXPECT_THROW(
-    nntrainer::TensorDim t({1, 2, 3, 4, 5}, nntrainer::Tformat::NHWC),
-    std::invalid_argument);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_01_p) {
-  int status = ML_ERROR_NONE;
-
-  nntrainer::TensorDim tensor_dim;
-  status = tensor_dim.setTensorDim("1:2:3:4");
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_01_nhwc_p) {
-  int status = ML_ERROR_NONE;
-
-  nntrainer::TensorDim tensor_dim;
-  status = tensor_dim.setTensorDim("1:2:3:4", nntrainer::Tformat::NHWC);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_02_n) {
-  int status = ML_ERROR_NONE;
-
-  nntrainer::TensorDim tensor_dim;
-  status = tensor_dim.setTensorDim("1:2:3:4:5");
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_02__nhwc_n) {
-  int status = ML_ERROR_NONE;
-
-  nntrainer::TensorDim tensor_dim;
-  status = tensor_dim.setTensorDim("1:2:3:4:5", nntrainer::Tformat::NHWC);
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_03_n) {
-  nntrainer::TensorDim d;
-
-  EXPECT_THROW(d.setTensorDim(0, 0), std::invalid_argument);
-  EXPECT_THROW(d.setTensorDim(1, 0), std::invalid_argument);
-  EXPECT_THROW(d.setTensorDim(2, 0), std::invalid_argument);
-  EXPECT_THROW(d.setTensorDim(3, 0), std::invalid_argument);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_03_nhwc_n) {
-  nntrainer::TensorDim d(nntrainer::Tformat::NHWC);
-
-  EXPECT_THROW(d.setTensorDim(0, 0), std::invalid_argument);
-  EXPECT_THROW(d.setTensorDim(1, 0), std::invalid_argument);
-  EXPECT_THROW(d.setTensorDim(2, 0), std::invalid_argument);
-  EXPECT_THROW(d.setTensorDim(3, 0), std::invalid_argument);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_04_p) {
-  nntrainer::TensorDim d;
-
-  d.setTensorDim(0, 4);
-  d.setTensorDim(1, 5);
-  d.setTensorDim(2, 6);
-  d.setTensorDim(3, 7);
-
-  EXPECT_EQ(d.batch(), 4u);
-  EXPECT_EQ(d.channel(), 5u);
-  EXPECT_EQ(d.height(), 6u);
-  EXPECT_EQ(d.width(), 7u);
-}
-
-TEST(nntrainer_TensorDim, setTensorDim_04_nhwc_p) {
-  nntrainer::TensorDim d(nntrainer::Tformat::NHWC);
-
-  d.setTensorDim(0, 4);
-  d.setTensorDim(1, 5);
-  d.setTensorDim(2, 6);
-  d.setTensorDim(3, 7);
-
-  EXPECT_EQ(d.batch(), 4u);
-  EXPECT_EQ(d.height(), 5u);
-  EXPECT_EQ(d.width(), 6u);
-  EXPECT_EQ(d.channel(), 7u);
-}
-
-TEST(nntrainer_Tensor, Tensor_01_p) {
-  int status = ML_ERROR_NONE;
-  nntrainer::Tensor tensor = nntrainer::Tensor(1, 2, 3);
-  tensor.setZero();
-  ASSERT_NE(nullptr, tensor.getData());
-  if (tensor.getValue(0, 0, 0, 0) != 0.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, Tensor_01_nhwc_p) {
-  int status = ML_ERROR_NONE;
-  nntrainer::Tensor tensor =
-    nntrainer::Tensor(1, 2, 3, nntrainer::Tformat::NHWC);
-  tensor.setZero();
-  ASSERT_NE(nullptr, tensor.getData());
-  if (tensor.getValue(0, 0, 0, 0) != 0.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, Tensor_02_p) {
-  int status = ML_ERROR_NONE;
-  int height = 3;
-  int width = 10;
-  std::vector<std::vector<float>> in;
-  for (int i = 0; i < height; ++i) {
-    std::vector<float> tv;
-    for (int j = 0; j < width; ++j) {
-      tv.push_back(i * 2.0 + j);
-    }
-    in.push_back(tv);
-  }
-
-  nntrainer::Tensor tensor = nntrainer::Tensor(in);
-  ASSERT_NE(nullptr, tensor.getData<float>());
-
-  if (tensor.getValue<float>(0, 0, 0, 1) != 1.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, Tensor_03_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  std::vector<std::vector<std::vector<float>>> in;
-  for (int k = 0; k < batch; ++k) {
-    std::vector<std::vector<float>> ttv;
-    for (int i = 0; i < height; ++i) {
-      std::vector<float> tv;
-      for (int j = 0; j < width; ++j) {
-        tv.push_back(k * height * width + i * width + j);
-      }
-      ttv.push_back(tv);
-    }
-    in.push_back(ttv);
-  }
-
-  nntrainer::Tensor tensor = nntrainer::Tensor(in);
-  ASSERT_NE(nullptr, tensor.getData());
-
-  if (tensor.getValue(0, 0, 0, 1) != 1.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, multiply_i_01_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor original;
-  original.copy(input);
-
-  status = input.multiply_i(2.0);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  float *data = original.getData();
-  ASSERT_NE(nullptr, data);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width * channel; ++i) {
-    EXPECT_FLOAT_EQ(data[i] + data[i], indata[i]);
-  }
-}
-
-TEST(nntrainer_Tensor, multiply_i_02_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor original;
-  original.copy(input);
-
-  status = input.multiply_i(input);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  float *data = original.getData();
-  ASSERT_NE(nullptr, data);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width * channel; ++i) {
-    EXPECT_FLOAT_EQ(data[i] * data[i], indata[i]);
-  }
-}
-
-TEST(nntrainer_Tensor, multiply_i_03_n) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor target2(batch, channel, height - 2, width - 1);
-  status = input.multiply_i(target2);
-
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, multiply_i_broadcast_01_p) {
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 2, 4, 5);
-    float answer_data[] = {
-      0,    1,    4,    9,    16,   25,   36,   49,   64,   81,   100,  121,
-      144,  169,  196,  225,  256,  289,  324,  361,  400,  441,  484,  529,
-      576,  625,  676,  729,  784,  841,  900,  961,  1024, 1089, 1156, 1225,
-      1296, 1369, 1444, 1521, 0,    41,   84,   129,  176,  225,  276,  329,
-      384,  441,  500,  561,  624,  689,  756,  825,  896,  969,  1044, 1121,
-      1200, 1281, 1364, 1449, 1536, 1625, 1716, 1809, 1904, 2001, 2100, 2201,
-      2304, 2409, 2516, 2625, 2736, 2849, 2964, 3081, 0,    81,   164,  249,
-      336,  425,  516,  609,  704,  801,  900,  1001, 1104, 1209, 1316, 1425,
-      1536, 1649, 1764, 1881, 2000, 2121, 2244, 2369, 2496, 2625, 2756, 2889,
-      3024, 3161, 3300, 3441, 3584, 3729, 3876, 4025, 4176, 4329, 4484, 4641};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 4, 5);
-    float answer_data[] = {
-      0,    1,    4,    9,    16,   25,   36,   49,   64,   81,   100,  121,
-      144,  169,  196,  225,  256,  289,  324,  361,  0,    21,   44,   69,
-      96,   125,  156,  189,  224,  261,  300,  341,  384,  429,  476,  525,
-      576,  629,  684,  741,  800,  861,  924,  989,  1056, 1125, 1196, 1269,
-      1344, 1421, 1500, 1581, 1664, 1749, 1836, 1925, 2016, 2109, 2204, 2301,
-      1200, 1281, 1364, 1449, 1536, 1625, 1716, 1809, 1904, 2001, 2100, 2201,
-      2304, 2409, 2516, 2625, 2736, 2849, 2964, 3081, 3200, 3321, 3444, 3569,
-      3696, 3825, 3956, 4089, 4224, 4361, 4500, 4641, 4784, 4929, 5076, 5225,
-      5376, 5529, 5684, 5841, 4000, 4141, 4284, 4429, 4576, 4725, 4876, 5029,
-      5184, 5341, 5500, 5661, 5824, 5989, 6156, 6325, 6496, 6669, 6844, 7021};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 2, 4, 1);
-    float answer_data[] = {
-      0,    0,    0,    0,    0,    5,    6,    7,    8,    9,    20,   22,
-      24,   26,   28,   45,   48,   51,   54,   57,   80,   84,   88,   92,
-      96,   125,  130,  135,  140,  145,  180,  186,  192,  198,  204,  245,
-      252,  259,  266,  273,  320,  328,  336,  344,  352,  405,  414,  423,
-      432,  441,  500,  510,  520,  530,  540,  605,  616,  627,  638,  649,
-      720,  732,  744,  756,  768,  845,  858,  871,  884,  897,  980,  994,
-      1008, 1022, 1036, 1125, 1140, 1155, 1170, 1185, 1280, 1296, 1312, 1328,
-      1344, 1445, 1462, 1479, 1496, 1513, 1620, 1638, 1656, 1674, 1692, 1805,
-      1824, 1843, 1862, 1881, 2000, 2020, 2040, 2060, 2080, 2205, 2226, 2247,
-      2268, 2289, 2420, 2442, 2464, 2486, 2508, 2645, 2668, 2691, 2714, 2737};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 1, 5);
-    float answer_data[] = {
-      0,    1,    4,    9,    16,   0,    6,    14,   24,   36,   0,    11,
-      24,   39,   56,   0,    16,   34,   54,   76,   0,    21,   44,   69,
-      96,   0,    26,   54,   84,   116,  0,    31,   64,   99,   136,  0,
-      36,   74,   114,  156,  200,  246,  294,  344,  396,  225,  276,  329,
-      384,  441,  250,  306,  364,  424,  486,  275,  336,  399,  464,  531,
-      300,  366,  434,  504,  576,  325,  396,  469,  544,  621,  350,  426,
-      504,  584,  666,  375,  456,  539,  624,  711,  800,  891,  984,  1079,
-      1176, 850,  946,  1044, 1144, 1246, 900,  1001, 1104, 1209, 1316, 950,
-      1056, 1164, 1274, 1386, 1000, 1111, 1224, 1339, 1456, 1050, 1166, 1284,
-      1404, 1526, 1100, 1221, 1344, 1469, 1596, 1150, 1276, 1404, 1534, 1666};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 2, 1, 5);
-    float answer_data[] = {
-      0,   1,   4,    9,   16,  0,   6,   14,  24,  36,  0,   11,  24,  39,
-      56,  0,   16,   34,  54,  76,  100, 126, 154, 184, 216, 125, 156, 189,
-      224, 261, 150,  186, 224, 264, 306, 175, 216, 259, 304, 351, 0,   41,
-      84,  129, 176,  0,   46,  94,  144, 196, 0,   51,  104, 159, 216, 0,
-      56,  114, 174,  236, 300, 366, 434, 504, 576, 325, 396, 469, 544, 621,
-      350, 426, 504,  584, 666, 375, 456, 539, 624, 711, 0,   81,  164, 249,
-      336, 0,   86,   174, 264, 356, 0,   91,  184, 279, 376, 0,   96,  194,
-      294, 396, 500,  606, 714, 824, 936, 525, 636, 749, 864, 981, 550, 666,
-      784, 904, 1026, 575, 696, 819, 944, 1071};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 4, 1);
-    float answer_data[] = {
-      0,    0,    0,    0,    0,    5,    6,    7,    8,    9,    20,   22,
-      24,   26,   28,   45,   48,   51,   54,   57,   0,    0,    0,    0,
-      0,    25,   26,   27,   28,   29,   60,   62,   64,   66,   68,   105,
-      108,  111,  114,  117,  160,  164,  168,  172,  176,  225,  230,  235,
-      240,  245,  300,  306,  312,  318,  324,  385,  392,  399,  406,  413,
-      240,  244,  248,  252,  256,  325,  330,  335,  340,  345,  420,  426,
-      432,  438,  444,  525,  532,  539,  546,  553,  640,  648,  656,  664,
-      672,  765,  774,  783,  792,  801,  900,  910,  920,  930,  940,  1045,
-      1056, 1067, 1078, 1089, 800,  808,  816,  824,  832,  945,  954,  963,
-      972,  981,  1100, 1110, 1120, 1130, 1140, 1265, 1276, 1287, 1298, 1309};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 1, 1, 5);
-    float answer_data[] = {
-      0, 1,   4,   9,   16,  0, 6,   14,  24,  36,  0, 11,  24,  39,  56,
-      0, 16,  34,  54,  76,  0, 21,  44,  69,  96,  0, 26,  54,  84,  116,
-      0, 31,  64,  99,  136, 0, 36,  74,  114, 156, 0, 41,  84,  129, 176,
-      0, 46,  94,  144, 196, 0, 51,  104, 159, 216, 0, 56,  114, 174, 236,
-      0, 61,  124, 189, 256, 0, 66,  134, 204, 276, 0, 71,  144, 219, 296,
-      0, 76,  154, 234, 316, 0, 81,  164, 249, 336, 0, 86,  174, 264, 356,
-      0, 91,  184, 279, 376, 0, 96,  194, 294, 396, 0, 101, 204, 309, 416,
-      0, 106, 214, 324, 436, 0, 111, 224, 339, 456, 0, 116, 234, 354, 476};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 2, 1, 1);
-    float answer_data[] = {
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   20,  21,  22,  23,  24,  25,  26,  27,
-      28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-      70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-      112, 113, 114, 115, 116, 117, 118, 119};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 1, 1);
-    float answer_data[] = {
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   40,  41,
-      42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-      56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-      70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  160, 162, 164, 166,
-      168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194,
-      196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222,
-      224, 226, 228, 230, 232, 234, 236, 238};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 5, 1, 4);
-    nntrainer::Tensor t = ranged(3, 5, 1, 4);
-    nntrainer::Tensor m = ranged(3, 1, 1, 4);
-    float answer_data[] = {0,   1,   4,   9,   0,   5,   12,  21,  0,   9,
-                           20,  33,  0,   13,  28,  45,  0,   17,  36,  57,
-                           80,  105, 132, 161, 96,  125, 156, 189, 112, 145,
-                           180, 217, 128, 165, 204, 245, 144, 185, 228, 273,
-                           320, 369, 420, 473, 352, 405, 460, 517, 384, 441,
-                           500, 561, 416, 477, 540, 605, 448, 513, 580, 649};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.multiply_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-}
-
-TEST(nntrainer_Tensor, multiply_i_broadcast_not_supported_01_n) {
-  nntrainer::Tensor target(3, 1, 3, 1);
-  nntrainer::Tensor target2(3, 1, 3, 3);
-
-  EXPECT_EQ(target.multiply_i(target2), ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, multiply_i_broadcast_not_broadcastable_02_n) {
-  nntrainer::Tensor target(3, 2, 4, 5);
-  nntrainer::Tensor target2(3, 2, 3, 1);
-
-  EXPECT_EQ(target.multiply_i(target2), ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, multiply_01_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor result = input.multiply(0.0);
-  if (result.getValue(0, 0, 1, 1) != 0.0)
-    status = ML_ERROR_RESULT_OUT_OF_RANGE;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, multiply_02_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor result = input.multiply(input);
-
-  float *data = result.getData();
-  ASSERT_NE(nullptr, data);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    if (data[i] != indata[i] * indata[i]) {
-      status = ML_ERROR_RESULT_OUT_OF_RANGE;
-      break;
-    }
-  }
-
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, multiply_03_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor test(batch - 1, height - 1, width - 1);
-
-  EXPECT_THROW({ input.multiply(test); }, std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, multiply_04_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-  nntrainer::Tensor test(dim);
-
-  EXPECT_THROW(shared_input.multiply(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, multiply_05_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  nntrainer::Tensor test(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-  EXPECT_THROW(input.multiply(shared_test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, multiply_06_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim, false);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-  EXPECT_THROW(input.multiply(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, multiply_07_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim, false);
-
-  EXPECT_THROW(input.multiply(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, multiply_08_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-  nntrainer::Tensor output(dim, false);
-
-  EXPECT_THROW(input.multiply(test, output), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, multiply_float_01_p) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor expected(batch, channel, height, width);
-  GEN_TEST_INPUT(expected, (i * (batch * height) + j * (width) + k + 1) * 2);
-
-  nntrainer::Tensor result = input.multiply(2.0);
-
-  EXPECT_EQ(result, expected);
-}
-
-TEST(nntrainer_Tensor, divide_i_01_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor original;
-  original.copy(input);
-
-  status = input.divide_i((float)2.0);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  float *data = original.getData();
-  ASSERT_NE(nullptr, data);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width * channel; ++i) {
-    EXPECT_FLOAT_EQ(data[i], indata[i] + indata[i]);
-  }
-}
-
-TEST(nntrainer_Tensor, divide_i_02_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  status = input.divide_i(input);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width * channel; ++i) {
-    EXPECT_FLOAT_EQ(indata[i], float(1.0));
-  }
-}
-
-TEST(nntrainer_Tensor, divide_i_01_n) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  status = input.divide_i((float)0);
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, divide_i_02_n) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor original(batch, channel, height - 2, width - 1);
-
-  status = input.divide_i(original);
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, divide_01_p) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor result = input.divide(1.0);
-
-  float *previous = input.getData();
-  ASSERT_NE(nullptr, previous);
-  float *data = result.getData();
-  ASSERT_NE(nullptr, data);
-
-  for (int i = 0; i < batch * height * width * channel; ++i) {
-    EXPECT_FLOAT_EQ(data[i], previous[i]);
-  }
-}
-
-TEST(nntrainer_Tensor, divide_02_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  EXPECT_THROW({ input.divide(0.0); }, std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, divide_03_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor test(batch - 1, channel, height - 1, width - 1);
-
-  EXPECT_THROW({ input.divide(test); }, std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, divide_04_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-  nntrainer::Tensor test(dim);
-
-  EXPECT_THROW(shared_input.divide(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, divide_05_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  nntrainer::Tensor test(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-  EXPECT_THROW(input.divide(shared_test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, divide_06_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim, false);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-  EXPECT_THROW(input.divide(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, divide_07_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim, false);
-
-  EXPECT_THROW(input.divide(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, divide_08_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-  nntrainer::Tensor output(dim, false);
-
-  EXPECT_THROW(input.divide(test, output), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, divide_i_broadcast_01_p) {
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(1, 2, 4, 5);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       41.0,      21.0,
-      14.333333, 11.0,      9.0,       7.6666665, 6.714286,  6.0,
-      5.4444447, 5.0,       4.6363635, 4.3333335, 4.076923,  3.857143,
-      3.6666667, 3.5,       3.3529413, 3.2222223, 3.1052632, 3.0,
-      2.9047618, 2.8181818, 2.7391305, 2.6666667, 2.6,       2.5384614,
-      2.4814816, 2.4285715, 2.3793104, 2.3333333, 2.2903225, 2.25,
-      2.2121212, 2.1764705, 2.142857,  2.1111112, 2.0810812, 2.0526316,
-      2.025641,  2.0,       81.0,      41.0,      27.666666, 21.0,
-      17.0,      14.333333, 12.428572, 11.0,      9.888889,  9.0,
-      8.272727,  7.6666665, 7.1538463, 6.714286,  6.3333335, 6.0,
-      5.7058825, 5.4444447, 5.2105265, 5.0,       4.8095236, 4.6363635,
-      4.478261,  4.3333335, 4.2,       4.076923,  3.9629629, 3.857143,
-      3.7586207, 3.6666667, 3.580645,  3.5,       3.4242425, 3.3529413,
-      3.2857144, 3.2222223, 3.162162,  3.1052632, 3.0512822, 3.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(3, 1, 4, 5);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-      1.0,       1.0,       21.0,      11.0,      7.6666665, 6.0,
-      5.0,       4.3333335, 3.857143,  3.5,       3.2222223, 3.0,
-      2.8181818, 2.6666667, 2.5384614, 2.4285715, 2.3333333, 2.25,
-      2.1764705, 2.1111112, 2.0526316, 2.0,       1.9523809, 1.9090909,
-      1.8695652, 1.8333334, 1.8,       1.7692307, 1.7407408, 1.7142857,
-      1.6896552, 1.6666666, 1.6451613, 1.625,     1.6060606, 1.5882353,
-      1.5714285, 1.5555556, 1.5405406, 1.5263158, 1.5128205, 1.5,
-      2.9047618, 2.8181818, 2.7391305, 2.6666667, 2.6,       2.5384614,
-      2.4814816, 2.4285715, 2.3793104, 2.3333333, 2.2903225, 2.25,
-      2.2121212, 2.1764705, 2.142857,  2.1111112, 2.0810812, 2.0526316,
-      2.025641,  2.0,       1.9756098, 1.9523809, 1.9302325, 1.9090909,
-      1.8888888, 1.8695652, 1.8510638, 1.8333334, 1.8163265, 1.8,
-      1.7843137, 1.7692307, 1.754717,  1.7407408, 1.7272727, 1.7142857,
-      1.7017543, 1.6896552, 1.6779661, 1.6666666, 2.4634147, 2.4285715,
-      2.3953488, 2.3636363, 2.3333333, 2.3043478, 2.2765958, 2.25,
-      2.2244897, 2.2,       2.1764705, 2.1538463, 2.1320755, 2.1111112,
-      2.090909,  2.0714285, 2.0526316, 2.0344827, 2.0169492, 2.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(3, 2, 4, 1);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       2.0,       3.0,       4.0,       5.0,       3.0,
-      3.5,       4.0,       4.5,       5.0,       3.6666667, 4.0,
-      4.3333335, 4.6666665, 5.0,       4.0,       4.25,      4.5,
-      4.75,      5.0,       4.2,       4.4,       4.6,       4.8,
-      5.0,       4.3333335, 4.5,       4.6666665, 4.8333335, 5.0,
-      4.428571,  4.571429,  4.714286,  4.857143,  5.0,       4.5,
-      4.625,     4.75,      4.875,     5.0,       4.5555553, 4.6666665,
-      4.7777777, 4.888889,  5.0,       4.6,       4.7,       4.8,
-      4.9,       5.0,       4.6363635, 4.7272725, 4.818182,  4.909091,
-      5.0,       4.6666665, 4.75,      4.8333335, 4.9166665, 5.0,
-      4.6923075, 4.769231,  4.8461537, 4.923077,  5.0,       4.714286,
-      4.785714,  4.857143,  4.928571,  5.0,       4.733333,  4.8,
-      4.866667,  4.9333334, 5.0,       4.75,      4.8125,    4.875,
-      4.9375,    5.0,       4.7647057, 4.8235292, 4.882353,  4.9411764,
-      5.0,       4.7777777, 4.8333335, 4.888889,  4.9444447, 5.0,
-      4.7894735, 4.8421054, 4.894737,  4.9473686, 5.0,       4.8,
-      4.85,      4.9,       4.95,      5.0,       4.8095236, 4.857143,
-      4.904762,  4.952381,  5.0,       4.818182,  4.8636365, 4.909091,
-      4.9545455, 5.0,       4.826087,  4.869565,  4.9130435, 4.9565215,
-      5.0,       4.8333335, 4.875,     4.9166665, 4.9583335, 5.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(3, 1, 1, 5);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       1.0,       1.0,       1.0,       1.0,       6.0,
-      3.5,       2.6666667, 2.25,      2.0,       11.0,      6.0,
-      4.3333335, 3.5,       3.0,       16.0,      8.5,       6.0,
-      4.75,      4.0,       21.0,      11.0,      7.6666665, 6.0,
-      5.0,       26.0,      13.5,      9.333333,  7.25,      6.0,
-      31.0,      16.0,      11.0,      8.5,       7.0,       36.0,
-      18.5,      12.666667, 9.75,      8.0,       6.8333335, 6.0,
-      5.375,     4.888889,  4.5,       7.6666665, 6.714286,  6.0,
-      5.4444447, 5.0,       8.5,       7.428571,  6.625,     6.0,
-      5.5,       9.333333,  8.142858,  7.25,      6.5555553, 6.0,
-      10.166667, 8.857142,  7.875,     7.111111,  6.5,       11.0,
-      9.571428,  8.5,       7.6666665, 7.0,       11.833333, 10.285714,
-      9.125,     8.222222,  7.5,       12.666667, 11.0,      9.75,
-      8.777778,  8.0,       7.3636365, 6.8333335, 6.3846154, 6.0,
-      5.6666665, 7.818182,  7.25,      6.769231,  6.357143,  6.0,
-      8.272727,  7.6666665, 7.1538463, 6.714286,  6.3333335, 8.727273,
-      8.083333,  7.5384617, 7.071429,  6.6666665, 9.181818,  8.5,
-      7.923077,  7.428571,  7.0,       9.636364,  8.916667,  8.307693,
-      7.785714,  7.3333335, 10.090909, 9.333333,  8.692307,  8.142858,
-      7.6666665, 10.545455, 9.75,      9.076923,  8.5,       8.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(1, 2, 1, 5);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       1.0,       1.0,       1.0,       1.0,       6.0,
-      3.5,       2.6666667, 2.25,      2.0,       11.0,      6.0,
-      4.3333335, 3.5,       3.0,       16.0,      8.5,       6.0,
-      4.75,      4.0,       3.5,       3.142857,  2.875,     2.6666667,
-      2.5,       4.3333335, 3.857143,  3.5,       3.2222223, 3.0,
-      5.1666665, 4.571429,  4.125,     3.7777777, 3.5,       6.0,
-      5.285714,  4.75,      4.3333335, 4.0,       41.0,      21.0,
-      14.333333, 11.0,      9.0,       46.0,      23.5,      16.0,
-      12.25,     10.0,      51.0,      26.0,      17.666666, 13.5,
-      11.0,      56.0,      28.5,      19.333334, 14.75,     12.0,
-      10.166667, 8.857142,  7.875,     7.111111,  6.5,       11.0,
-      9.571428,  8.5,       7.6666665, 7.0,       11.833333, 10.285714,
-      9.125,     8.222222,  7.5,       12.666667, 11.0,      9.75,
-      8.777778,  8.0,       81.0,      41.0,      27.666666, 21.0,
-      17.0,      86.0,      43.5,      29.333334, 22.25,     18.0,
-      91.0,      46.0,      31.0,      23.5,      19.0,      96.0,
-      48.5,      32.666668, 24.75,     20.0,      16.833334, 14.571428,
-      12.875,    11.555555, 10.5,      17.666666, 15.285714, 13.5,
-      12.111111, 11.0,      18.5,      16.0,      14.125,    12.666667,
-      11.5,      19.333334, 16.714285, 14.75,     13.222222, 12.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(3, 1, 4, 1);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       2.0,       3.0,       4.0,       5.0,       3.0,
-      3.5,       4.0,       4.5,       5.0,       3.6666667, 4.0,
-      4.3333335, 4.6666665, 5.0,       4.0,       4.25,      4.5,
-      4.75,      5.0,       21.0,      22.0,      23.0,      24.0,
-      25.0,      13.0,      13.5,      14.0,      14.5,      15.0,
-      10.333333, 10.666667, 11.0,      11.333333, 11.666667, 9.0,
-      9.25,      9.5,       9.75,      10.0,      8.2,       8.4,
-      8.6,       8.8,       9.0,       7.6666665, 7.8333335, 8.0,
-      8.166667,  8.333333,  7.285714,  7.428571,  7.571429,  7.714286,
-      7.857143,  7.0,       7.125,     7.25,      7.375,     7.5,
-      12.2,      12.4,      12.6,      12.8,      13.0,      11.0,
-      11.166667, 11.333333, 11.5,      11.666667, 10.142858, 10.285714,
-      10.428572, 10.571428, 10.714286, 9.5,       9.625,     9.75,
-      9.875,     10.0,      9.0,       9.111111,  9.222222,  9.333333,
-      9.444445,  8.6,       8.7,       8.8,       8.9,       9.0,
-      8.272727,  8.363636,  8.454545,  8.545455,  8.636364,  8.0,
-      8.083333,  8.166667,  8.25,      8.333333,  11.222222, 11.333333,
-      11.444445, 11.555555, 11.666667, 10.6,      10.7,      10.8,
-      10.9,      11.0,      10.090909, 10.181818, 10.272727, 10.363636,
-      10.454545, 9.666667,  9.75,      9.833333,  9.916667,  10.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(1, 1, 1, 5);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,   1.0,  1.0,       1.0,  1.0,  6.0,   3.5,  2.6666667, 2.25,  2.0,
-      11.0,  6.0,  4.3333335, 3.5,  3.0,  16.0,  8.5,  6.0,       4.75,  4.0,
-      21.0,  11.0, 7.6666665, 6.0,  5.0,  26.0,  13.5, 9.333333,  7.25,  6.0,
-      31.0,  16.0, 11.0,      8.5,  7.0,  36.0,  18.5, 12.666667, 9.75,  8.0,
-      41.0,  21.0, 14.333333, 11.0, 9.0,  46.0,  23.5, 16.0,      12.25, 10.0,
-      51.0,  26.0, 17.666666, 13.5, 11.0, 56.0,  28.5, 19.333334, 14.75, 12.0,
-      61.0,  31.0, 21.0,      16.0, 13.0, 66.0,  33.5, 22.666666, 17.25, 14.0,
-      71.0,  36.0, 24.333334, 18.5, 15.0, 76.0,  38.5, 26.0,      19.75, 16.0,
-      81.0,  41.0, 27.666666, 21.0, 17.0, 86.0,  43.5, 29.333334, 22.25, 18.0,
-      91.0,  46.0, 31.0,      23.5, 19.0, 96.0,  48.5, 32.666668, 24.75, 20.0,
-      101.0, 51.0, 34.333332, 26.0, 21.0, 106.0, 53.5, 36.0,      27.25, 22.0,
-      111.0, 56.0, 37.666668, 28.5, 23.0, 116.0, 58.5, 39.333332, 29.75, 24.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(1, 2, 1, 1);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,  2.0,  3.0,  4.0,   5.0,  6.0,  7.0,  8.0,  9.0,  10.0, 11.0, 12.0,
-      13.0, 14.0, 15.0, 16.0,  17.0, 18.0, 19.0, 20.0, 10.5, 11.0, 11.5, 12.0,
-      12.5, 13.0, 13.5, 14.0,  14.5, 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0,
-      18.5, 19.0, 19.5, 20.0,  41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0,
-      49.0, 50.0, 51.0, 52.0,  53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0,
-      30.5, 31.0, 31.5, 32.0,  32.5, 33.0, 33.5, 34.0, 34.5, 35.0, 35.5, 36.0,
-      36.5, 37.0, 37.5, 38.0,  38.5, 39.0, 39.5, 40.0, 81.0, 82.0, 83.0, 84.0,
-      85.0, 86.0, 87.0, 88.0,  89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0,
-      97.0, 98.0, 99.0, 100.0, 50.5, 51.0, 51.5, 52.0, 52.5, 53.0, 53.5, 54.0,
-      54.5, 55.0, 55.5, 56.0,  56.5, 57.0, 57.5, 58.0, 58.5, 59.0, 59.5, 60.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(3, 1, 1, 1);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       2.0,       3.0,  4.0,       5.0,       6.0,
-      7.0,       8.0,       9.0,  10.0,      11.0,      12.0,
-      13.0,      14.0,      15.0, 16.0,      17.0,      18.0,
-      19.0,      20.0,      21.0, 22.0,      23.0,      24.0,
-      25.0,      26.0,      27.0, 28.0,      29.0,      30.0,
-      31.0,      32.0,      33.0, 34.0,      35.0,      36.0,
-      37.0,      38.0,      39.0, 40.0,      20.5,      21.0,
-      21.5,      22.0,      22.5, 23.0,      23.5,      24.0,
-      24.5,      25.0,      25.5, 26.0,      26.5,      27.0,
-      27.5,      28.0,      28.5, 29.0,      29.5,      30.0,
-      30.5,      31.0,      31.5, 32.0,      32.5,      33.0,
-      33.5,      34.0,      34.5, 35.0,      35.5,      36.0,
-      36.5,      37.0,      37.5, 38.0,      38.5,      39.0,
-      39.5,      40.0,      27.0, 27.333334, 27.666666, 28.0,
-      28.333334, 28.666666, 29.0, 29.333334, 29.666666, 30.0,
-      30.333334, 30.666666, 31.0, 31.333334, 31.666666, 32.0,
-      32.333332, 32.666668, 33.0, 33.333332, 33.666668, 34.0,
-      34.333332, 34.666668, 35.0, 35.333332, 35.666668, 36.0,
-      36.333332, 36.666668, 37.0, 37.333332, 37.666668, 38.0,
-      38.333332, 38.666668, 39.0, 39.333332, 39.666668, 40.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 5, 1, 4);
-    nntrainer::Tensor t = ranged(3, 5, 1, 4);
-    t.add_i(1);
-    nntrainer::Tensor m = ranged(3, 1, 1, 4);
-    m.add_i(1);
-    float answer_data[] = {
-      1.0,       1.0,       1.0,       1.0,       5.0,       3.0,
-      2.3333333, 2.0,       9.0,       5.0,       3.6666667, 3.0,
-      13.0,      7.0,       5.0,       4.0,       17.0,      9.0,
-      6.3333335, 5.0,       4.2,       3.6666667, 3.2857144, 3.0,
-      5.0,       4.3333335, 3.857143,  3.5,       5.8,       5.0,
-      4.428571,  4.0,       6.6,       5.6666665, 5.0,       4.5,
-      7.4,       6.3333335, 5.571429,  5.0,       4.5555553, 4.2,
-      3.909091,  3.6666667, 5.0,       4.6,       4.2727275, 4.0,
-      5.4444447, 5.0,       4.6363635, 4.3333335, 5.888889,  5.4,
-      5.0,       4.6666665, 6.3333335, 5.8,       5.3636365, 5.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.divide_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-}
-
-TEST(nntrainer_Tensor, divide_i_broadcast_not_supported_01_n) {
-  nntrainer::Tensor target(3, 1, 3, 1);
-  nntrainer::Tensor target2(3, 1, 3, 3);
-
-  EXPECT_EQ(target.divide_i(target2), ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, divide_i_broadcast_not_broadcastable_02_n) {
-  nntrainer::Tensor target(3, 2, 4, 5);
-  nntrainer::Tensor target2(3, 2, 3, 1);
-
-  EXPECT_EQ(target.divide_i(target2), ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, add_i_01_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  int channel = 1;
-
-  nntrainer::Tensor target(batch, channel, height, width);
-  GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-  nntrainer::Tensor original(batch, channel, height, width);
-  original.copy(target);
-
-  status = target.add_i(2.1);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  float *previous = original.getData();
-  ASSERT_NE(nullptr, previous);
-  float *data = target.getData();
-  ASSERT_NE(nullptr, data);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    EXPECT_FLOAT_EQ(data[i], previous[i] + (float)2.1);
-  }
-}
-
-TEST(nntrainer_Tensor, add_i_02_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  int channel = 1;
-
-  nntrainer::Tensor target(batch, channel, height, width);
-  GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor original(batch, height, width);
-  original.copy(target);
-
-  status = target.add_i(target, 3.0);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  float *previous = original.getData();
-  ASSERT_NE(nullptr, previous);
-  float *data = target.getData();
-  ASSERT_NE(nullptr, data);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    EXPECT_FLOAT_EQ(data[i], previous[i] * 4.0);
-  }
-}
-
-/**
- * @brief operand dimension is not right
- */
-TEST(nntrainer_Tensor, add_i_01_n) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  int channel = 1;
-
-  nntrainer::Tensor target(batch, channel, height, width);
-  GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor target2(batch, height - 2, width - 3);
-
-  status = target.add_i(target2);
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, add_i_broadcast_01_p) {
-  nntrainer::TensorDim ref_dim{3, 2, 4, 5};
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 2, 4, 5);
-    float answer_data[] = {
-      0,   2,   4,   6,   8,   10,  12,  14,  16,  18,  20,  22,  24,  26,
-      28,  30,  32,  34,  36,  38,  40,  42,  44,  46,  48,  50,  52,  54,
-      56,  58,  60,  62,  64,  66,  68,  70,  72,  74,  76,  78,  40,  42,
-      44,  46,  48,  50,  52,  54,  56,  58,  60,  62,  64,  66,  68,  70,
-      72,  74,  76,  78,  80,  82,  84,  86,  88,  90,  92,  94,  96,  98,
-      100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 80,  82,  84,  86,
-      88,  90,  92,  94,  96,  98,  100, 102, 104, 106, 108, 110, 112, 114,
-      116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142,
-      144, 146, 148, 150, 152, 154, 156, 158};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 4, 5);
-    float answer_data[] = {
-      0,   2,   4,   6,   8,   10,  12,  14,  16,  18,  20,  22,  24,  26,
-      28,  30,  32,  34,  36,  38,  20,  22,  24,  26,  28,  30,  32,  34,
-      36,  38,  40,  42,  44,  46,  48,  50,  52,  54,  56,  58,  60,  62,
-      64,  66,  68,  70,  72,  74,  76,  78,  80,  82,  84,  86,  88,  90,
-      92,  94,  96,  98,  80,  82,  84,  86,  88,  90,  92,  94,  96,  98,
-      100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
-      128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154,
-      156, 158, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162,
-      164, 166, 168, 170, 172, 174, 176, 178};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 2, 4, 1);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   6,   7,   8,   9,   10,  12,  13,  14,  15,
-      16,  18,  19,  20,  21,  22,  24,  25,  26,  27,  28,  30,  31,  32,
-      33,  34,  36,  37,  38,  39,  40,  42,  43,  44,  45,  46,  48,  49,
-      50,  51,  52,  54,  55,  56,  57,  58,  60,  61,  62,  63,  64,  66,
-      67,  68,  69,  70,  72,  73,  74,  75,  76,  78,  79,  80,  81,  82,
-      84,  85,  86,  87,  88,  90,  91,  92,  93,  94,  96,  97,  98,  99,
-      100, 102, 103, 104, 105, 106, 108, 109, 110, 111, 112, 114, 115, 116,
-      117, 118, 120, 121, 122, 123, 124, 126, 127, 128, 129, 130, 132, 133,
-      134, 135, 136, 138, 139, 140, 141, 142};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 1, 5);
-    float answer_data[] = {
-      0,   2,   4,   6,   8,   5,   7,   9,   11,  13,  10,  12,  14,  16,
-      18,  15,  17,  19,  21,  23,  20,  22,  24,  26,  28,  25,  27,  29,
-      31,  33,  30,  32,  34,  36,  38,  35,  37,  39,  41,  43,  45,  47,
-      49,  51,  53,  50,  52,  54,  56,  58,  55,  57,  59,  61,  63,  60,
-      62,  64,  66,  68,  65,  67,  69,  71,  73,  70,  72,  74,  76,  78,
-      75,  77,  79,  81,  83,  80,  82,  84,  86,  88,  90,  92,  94,  96,
-      98,  95,  97,  99,  101, 103, 100, 102, 104, 106, 108, 105, 107, 109,
-      111, 113, 110, 112, 114, 116, 118, 115, 117, 119, 121, 123, 120, 122,
-      124, 126, 128, 125, 127, 129, 131, 133};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 2, 1, 5);
-    float answer_data[] = {
-      0,   2,   4,   6,   8,   5,   7,   9,   11,  13,  10,  12,  14,  16,
-      18,  15,  17,  19,  21,  23,  25,  27,  29,  31,  33,  30,  32,  34,
-      36,  38,  35,  37,  39,  41,  43,  40,  42,  44,  46,  48,  40,  42,
-      44,  46,  48,  45,  47,  49,  51,  53,  50,  52,  54,  56,  58,  55,
-      57,  59,  61,  63,  65,  67,  69,  71,  73,  70,  72,  74,  76,  78,
-      75,  77,  79,  81,  83,  80,  82,  84,  86,  88,  80,  82,  84,  86,
-      88,  85,  87,  89,  91,  93,  90,  92,  94,  96,  98,  95,  97,  99,
-      101, 103, 105, 107, 109, 111, 113, 110, 112, 114, 116, 118, 115, 117,
-      119, 121, 123, 120, 122, 124, 126, 128};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 4, 1);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   6,   7,   8,   9,   10,  12,  13,  14,  15,
-      16,  18,  19,  20,  21,  22,  20,  21,  22,  23,  24,  26,  27,  28,
-      29,  30,  32,  33,  34,  35,  36,  38,  39,  40,  41,  42,  44,  45,
-      46,  47,  48,  50,  51,  52,  53,  54,  56,  57,  58,  59,  60,  62,
-      63,  64,  65,  66,  64,  65,  66,  67,  68,  70,  71,  72,  73,  74,
-      76,  77,  78,  79,  80,  82,  83,  84,  85,  86,  88,  89,  90,  91,
-      92,  94,  95,  96,  97,  98,  100, 101, 102, 103, 104, 106, 107, 108,
-      109, 110, 108, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121,
-      122, 123, 124, 126, 127, 128, 129, 130};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 1, 1, 5);
-    float answer_data[] = {
-      0,   2,   4,   6,   8,   5,   7,   9,   11,  13,  10,  12,  14,  16,
-      18,  15,  17,  19,  21,  23,  20,  22,  24,  26,  28,  25,  27,  29,
-      31,  33,  30,  32,  34,  36,  38,  35,  37,  39,  41,  43,  40,  42,
-      44,  46,  48,  45,  47,  49,  51,  53,  50,  52,  54,  56,  58,  55,
-      57,  59,  61,  63,  60,  62,  64,  66,  68,  65,  67,  69,  71,  73,
-      70,  72,  74,  76,  78,  75,  77,  79,  81,  83,  80,  82,  84,  86,
-      88,  85,  87,  89,  91,  93,  90,  92,  94,  96,  98,  95,  97,  99,
-      101, 103, 100, 102, 104, 106, 108, 105, 107, 109, 111, 113, 110, 112,
-      114, 116, 118, 115, 117, 119, 121, 123};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 2, 1, 1);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-      14,  15,  16,  17,  18,  19,  21,  22,  23,  24,  25,  26,  27,  28,
-      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  40,  41,
-      42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-      56,  57,  58,  59,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
-      71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  80,  81,  82,  83,
-      84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
-      98,  99,  101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
-      113, 114, 115, 116, 117, 118, 119, 120};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 1, 1, 1);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-      14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-      28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  41,  42,
-      43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
-      57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
-      71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  82,  83,  84,  85,
-      86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-      100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
-      114, 115, 116, 117, 118, 119, 120, 121};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(1, 1, 1, 1);
-    m.add_i(1.0);
-    float answer_data[] = {
-      1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
-      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
-      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
-      43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
-      57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
-      71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
-      85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
-      99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
-      113, 114, 115, 116, 117, 118, 119, 120};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 5, 1, 4);
-    nntrainer::Tensor t = ranged(3, 5, 1, 4);
-    nntrainer::Tensor m = ranged(3, 1, 1, 4);
-    float answer_data[] = {0,  2,  4,  6,  4,  6,  8,  10, 8,  10, 12, 14,
-                           12, 14, 16, 18, 16, 18, 20, 22, 24, 26, 28, 30,
-                           28, 30, 32, 34, 32, 34, 36, 38, 36, 38, 40, 42,
-                           40, 42, 44, 46, 48, 50, 52, 54, 52, 54, 56, 58,
-                           56, 58, 60, 62, 60, 62, 64, 66, 64, 66, 68, 70};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(1, 1, 2, 1);
-    nntrainer::Tensor t = ranged(1, 1, 2, 1);
-    nntrainer::Tensor m = ranged(1, 1, 2, 1);
-    float answer_data[] = {0.0, 2.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(16, 1, 1, 1);
-    nntrainer::Tensor t = ranged(16, 1, 1, 1);
-    nntrainer::Tensor m = ranged(1, 1, 1, 1);
-    float answer_data[] = {0.0, 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,
-                           8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0};
-    nntrainer::Tensor answer(ref_dim, answer_data);
-    int status = t.add_i(m);
-    EXPECT_EQ(status, ML_ERROR_NONE);
-    EXPECT_EQ(t, answer);
-  }
-}
-
-TEST(nntrainer_Tensor, add_i_broadcast_not_supported_01_n) {
-  nntrainer::Tensor target(3, 1, 3, 1);
-  nntrainer::Tensor target2(3, 1, 3, 3);
-
-  EXPECT_EQ(target.add_i(target2), ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, add_i_broadcast_not_broadcastable_02_n) {
-  nntrainer::Tensor target(3, 2, 4, 5);
-  nntrainer::Tensor target2(3, 2, 3, 1);
-
-  EXPECT_EQ(target.add_i(target2), ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, add_01_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor result = input.add(1.0);
-
-  float *data = result.getData();
-  ASSERT_NE(nullptr, data);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    if (data[i] != indata[i] + (float)1.0) {
-      status = ML_ERROR_RESULT_OUT_OF_RANGE;
-      break;
-    }
-  }
-
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, add_02_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor result = input.add(input);
-
-  float *data = result.getData();
-  ASSERT_NE(nullptr, data);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    if (data[i] != indata[i] + indata[i]) {
-      status = ML_ERROR_RESULT_OUT_OF_RANGE;
-      break;
-    }
-  }
-
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, add_03_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor test(batch - 1, channel, height - 1, width - 1);
-
-  EXPECT_THROW({ input.add(test); }, std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, add_04_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-  nntrainer::Tensor test(dim);
-
-  EXPECT_THROW(shared_input.add(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, add_05_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  nntrainer::Tensor test(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-  EXPECT_THROW(input.add(shared_test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, add_06_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim, false);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-  EXPECT_THROW(input.add(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, add_07_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim, false);
-
-  EXPECT_THROW(input.add(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, add_08_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-  nntrainer::Tensor output(dim, false);
-
-  EXPECT_THROW(input.add(test, output), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, pow_01_p) {
-
-  nntrainer::Tensor input = constant(4.0, 3, 2, 4, 5);
-
-  nntrainer::Tensor actual, expected;
-
-  actual = input.pow(0.5f);
-  expected = constant(2.0, 3, 2, 4, 5);
-  EXPECT_EQ(actual, expected);
-
-  actual = input.pow(2.0f);
-  expected = constant(16.0, 3, 2, 4, 5);
-  EXPECT_EQ(actual, expected);
-
-  actual = input.pow(-0.5f);
-  expected = constant(0.5, 3, 2, 4, 5);
-  EXPECT_EQ(actual, expected);
-}
-
-TEST(nntrainer_Tensor, erf_01_p) {
-  int batch = 1;
-  int channel = 1;
-  int height = 2;
-  int width = 2;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, k + l * 0.5 + 0.5);
-  nntrainer::Tensor actual = input.erf();
-  nntrainer::Tensor expected(
-    std::vector<std::vector<std::vector<std::vector<float>>>>(
-      {{{{0.5205, 0.8427}, {0.966105, 0.995322}}}}));
-
-  EXPECT_EQ(actual, expected);
-}
-
-TEST(nntrainer_Tensor, subtract_i_01_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  int channel = 1;
-
-  nntrainer::Tensor target(batch, channel, height, width);
-  GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-  nntrainer::Tensor original(batch, height, width);
-  original.copy(target);
-
-  status = target.subtract_i(2.1);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  float *previous = original.getData();
-  ASSERT_NE(nullptr, previous);
-  float *data = target.getData();
-  ASSERT_NE(nullptr, data);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    EXPECT_FLOAT_EQ(data[i], previous[i] - (float)2.1);
-  }
-}
-
-TEST(nntrainer_Tensor, subtract_i_02_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  int channel = 1;
-
-  nntrainer::Tensor target(batch, channel, height, width);
-  GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-  status = target.subtract_i(target);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  float *data = target.getData();
-  ASSERT_NE(nullptr, data);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    EXPECT_FLOAT_EQ(data[i], 0);
-  }
-}
-
-TEST(nntrainer_Tensor, subtract_i_03_n) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  int channel = 1;
-
-  nntrainer::Tensor target(batch, channel, height, width);
-  GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-  nntrainer::Tensor target2(batch, channel, height - 1, width - 3);
-
-  status = target.subtract_i(target2);
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-TEST(nntrainer_Tensor, subtract_01_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor result = input.subtract(1.0);
-
-  float *data = result.getData();
-  ASSERT_NE(nullptr, data);
-  float *indata = input.getData();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width; ++i) {
-    if (data[i] != indata[i] - 1.0) {
-      status = ML_ERROR_RESULT_OUT_OF_RANGE;
-      break;
-    }
-  }
-
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, subtract_02_p) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor result = input.subtract(input);
-
-  EXPECT_EQ(constant(0.0, batch, channel, height, width), result);
-}
-
-TEST(nntrainer_Tensor, subtract_03_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor test(batch - 1, channel, height - 1, width - 1);
-
-  EXPECT_THROW({ input.subtract(test); }, std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, subtract_04_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-  nntrainer::Tensor test(dim);
-
-  EXPECT_THROW(shared_input.subtract(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, subtract_05_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  nntrainer::Tensor test(batch, channel, height, 2 * width);
-  nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-  EXPECT_THROW(input.subtract(shared_test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, subtract_06_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim, false);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-  EXPECT_THROW(input.subtract(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, subtract_07_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim, false);
-
-  EXPECT_THROW(input.subtract(test), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, subtract_08_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::TensorDim dim(batch, channel, height, width);
-
-  nntrainer::Tensor input(dim);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-  nntrainer::Tensor test(dim);
-  GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-  nntrainer::Tensor output(dim, false);
-
-  EXPECT_THROW(input.subtract(test, output), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, subtract_float_01_p) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-  nntrainer::Tensor expected(batch, channel, height, width);
-  GEN_TEST_INPUT(expected, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor result = input.subtract(1.0);
-
-  EXPECT_EQ(result, expected);
-}
-
-TEST(nntrainer_Tensor, sum_01_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  EXPECT_THROW({ input.sum(4); }, std::out_of_range);
-}
-
-TEST(nntrainer_Tensor, sum_02_n) {
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  EXPECT_THROW({ input.sum(-1); }, std::out_of_range);
-}
-
-TEST(nntrainer_Tensor, sum_02_p) {
-  int batch = 3;
-  int channel = 2;
-  int height = 2;
-  int width = 10;
-
-  nntrainer::Tensor ans0(
-    std::vector<std::vector<std::vector<std::vector<float>>>>(
-      {{{{39, 42, 45, 48, 51, 54, 57, 60, 63, 66},
-         {69, 72, 75, 78, 81, 84, 87, 90, 93, 96}},
-        {{57, 60, 63, 66, 69, 72, 75, 78, 81, 84},
-         {87, 90, 93, 96, 99, 102, 105, 108, 111, 114}}}}));
-
-  nntrainer::Tensor ans1(
-    std::vector<std::vector<std::vector<std::vector<float>>>>(
-      {{{{8, 10, 12, 14, 16, 18, 20, 22, 24, 26},
-         {28, 30, 32, 34, 36, 38, 40, 42, 44, 46}}},
-       {{{32, 34, 36, 38, 40, 42, 44, 46, 48, 50},
-         {52, 54, 56, 58, 60, 62, 64, 66, 68, 70}}},
-       {{{56, 58, 60, 62, 64, 66, 68, 70, 72, 74},
-         {76, 78, 80, 82, 84, 86, 88, 90, 92, 94}}}}));
-
-  nntrainer::Tensor ans2(
-    std::vector<std::vector<std::vector<std::vector<float>>>>(
-      {{{{12, 14, 16, 18, 20, 22, 24, 26, 28, 30}},
-        {{24, 26, 28, 30, 32, 34, 36, 38, 40, 42}}},
-       {{{36, 38, 40, 42, 44, 46, 48, 50, 52, 54}},
-        {{48, 50, 52, 54, 56, 58, 60, 62, 64, 66}}},
-       {{{60, 62, 64, 66, 68, 70, 72, 74, 76, 78}},
-        {{72, 74, 76, 78, 80, 82, 84, 86, 88, 90}}}}));
-
-  nntrainer::Tensor ans3(
-    std::vector<std::vector<std::vector<std::vector<float>>>>(
-      {{{{55}, {155}}, {{115}, {215}}},
-       {{{175}, {275}}, {{235}, {335}}},
-       {{{295}, {395}}, {{355}, {455}}}}));
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height * channel) + j * (batch * height) +
-                          k * (width) + l + 1);
-
-  nntrainer::Tensor result0 = input.sum(0);
-  nntrainer::Tensor result1 = input.sum(1);
-  nntrainer::Tensor result2 = input.sum(2);
-  nntrainer::Tensor result3 = input.sum(3);
-
-  EXPECT_EQ(ans0, result0);
-  EXPECT_EQ(ans1, result1);
-  EXPECT_EQ(ans2, result2);
-  EXPECT_EQ(ans3, result3);
-}
-
-TEST(nntrainer_Tensor, sum_03_p) {
-  const int batch = 3;
-  const int channel = 2;
-  const int height = 1;
-  const int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (height * channel * width) + j * (height * width) +
-                          k * (width) + l + 1);
-  // Test for alpha == 1 and beta == 0 and dimension of reduced axis == 1
-  {
-    nntrainer::Tensor ans_0_1_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{63, 66, 69, 72, 75, 78, 81, 84, 87, 90}},
-          {{93, 96, 99, 102, 105, 108, 111, 114, 117, 120}}}}));
-
-    nntrainer::Tensor ans_1_1_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{12, 14, 16, 18, 20, 22, 24, 26, 28, 30}}},
-         {{{52, 54, 56, 58, 60, 62, 64, 66, 68, 70}}},
-         {{{92, 94, 96, 98, 100, 102, 104, 106, 108, 110}}}}));
-
-    nntrainer::Tensor ans_2_1_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
-          {{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}}},
-         {{{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}},
-          {{31, 32, 33, 34, 35, 36, 37, 38, 39, 40}}},
-         {{{41, 42, 43, 44, 45, 46, 47, 48, 49, 50}},
-          {{51, 52, 53, 54, 55, 56, 57, 58, 59, 60}}}}));
-
-    nntrainer::Tensor ans_3_1_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{55}}, {{155}}}, {{{255}}, {{355}}}, {{{455}}, {{555}}}}));
-
-    nntrainer::Tensor result_0_1_0 = input.sum(0, 1);
-    nntrainer::Tensor result_1_1_0 = input.sum(1, 1);
-    nntrainer::Tensor result_2_1_0 = input.sum(2, 1);
-    nntrainer::Tensor result_3_1_0 = input.sum(3, 1);
-
-    EXPECT_EQ(ans_0_1_0, result_0_1_0);
-    EXPECT_EQ(ans_1_1_0, result_1_1_0);
-    EXPECT_EQ(ans_2_1_0, result_2_1_0);
-    EXPECT_EQ(ans_3_1_0, result_3_1_0);
-  }
-
-  // Test for alpha == 1 and beta == 2 and dimension of reduced axis == 1
-  {
-    nntrainer::Tensor ans_0_1_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{65, 70, 75, 80, 85, 90, 95, 100, 105, 110}},
-          {{115, 120, 125, 130, 135, 140, 145, 150, 155, 160}}}}));
-
-    nntrainer::Tensor ans_1_1_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{14, 18, 22, 26, 30, 34, 38, 42, 46, 50}}},
-         {{{74, 78, 82, 86, 90, 94, 98, 102, 106, 110}}},
-         {{{134, 138, 142, 146, 150, 154, 158, 162, 166, 170}}}}));
-
-    nntrainer::Tensor ans_2_1_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{3, 6, 9, 12, 15, 18, 21, 24, 27, 30}},
-          {{33, 36, 39, 42, 45, 48, 51, 54, 57, 60}}},
-         {{{63, 66, 69, 72, 75, 78, 81, 84, 87, 90}},
-          {{93, 96, 99, 102, 105, 108, 111, 114, 117, 120}}},
-         {{{123, 126, 129, 132, 135, 138, 141, 144, 147, 150}},
-          {{153, 156, 159, 162, 165, 168, 171, 174, 177, 180}}}}));
-
-    nntrainer::Tensor ans_3_1_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{57}}, {{159}}}, {{{261}}, {{363}}}, {{{465}}, {{567}}}}));
-
-    nntrainer::Tensor output_0_1_2(1, channel, height, width);
-    {
-      const int batch = 1;
-      GEN_TEST_INPUT(output_0_1_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor output_1_1_2(batch, 1, height, width);
-    {
-      const int channel = 1;
-      GEN_TEST_INPUT(output_1_1_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor output_2_1_2(batch, channel, 1, width);
-    {
-      const int height = 1;
-      GEN_TEST_INPUT(output_2_1_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor output_3_1_2(batch, channel, height, 1);
-    {
-      const int width = 1;
-      GEN_TEST_INPUT(output_3_1_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor result_0_1_2 = input.sum(0, output_0_1_2, 1, 2);
-    nntrainer::Tensor result_1_1_2 = input.sum(1, output_1_1_2, 1, 2);
-    nntrainer::Tensor result_2_1_2 = input.sum(2, output_2_1_2, 1, 2);
-    nntrainer::Tensor result_3_1_2 = input.sum(3, output_3_1_2, 1, 2);
-
-    EXPECT_EQ(ans_0_1_2, result_0_1_2);
-    EXPECT_EQ(ans_1_1_2, result_1_1_2);
-    EXPECT_EQ(ans_2_1_2, result_2_1_2);
-    EXPECT_EQ(ans_3_1_2, result_3_1_2);
-  }
-
-  // Test for alpha == 2 and beta == 0
-  {
-    nntrainer::Tensor ans_0_2_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{126, 132, 138, 144, 150, 156, 162, 168, 174, 180}},
-          {{186, 192, 198, 204, 210, 216, 222, 228, 234, 240}}}}));
-
-    nntrainer::Tensor ans_1_2_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{24, 28, 32, 36, 40, 44, 48, 52, 56, 60}}},
-         {{{104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
-         {{{184, 188, 192, 196, 200, 204, 208, 212, 216, 220}}}}));
-
-    nntrainer::Tensor ans_2_2_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}},
-          {{22, 24, 26, 28, 30, 32, 34, 36, 38, 40}}},
-         {{{42, 44, 46, 48, 50, 52, 54, 56, 58, 60}},
-          {{62, 64, 66, 68, 70, 72, 74, 76, 78, 80}}},
-         {{{82, 84, 86, 88, 90, 92, 94, 96, 98, 100}},
-          {{102, 104, 106, 108, 110, 112, 114, 116, 118, 120}}}}));
-
-    nntrainer::Tensor ans_3_2_0(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{110}}, {{310}}}, {{{510}}, {{710}}}, {{{910}}, {{1110}}}}));
-
-    nntrainer::Tensor result_0_2_0 = input.sum(0, 2);
-    nntrainer::Tensor result_1_2_0 = input.sum(1, 2);
-    nntrainer::Tensor result_2_2_0 = input.sum(2, 2);
-    nntrainer::Tensor result_3_2_0 = input.sum(3, 2);
-
-    EXPECT_EQ(ans_0_2_0, result_0_2_0);
-    EXPECT_EQ(ans_1_2_0, result_1_2_0);
-    EXPECT_EQ(ans_2_2_0, result_2_2_0);
-    EXPECT_EQ(ans_3_2_0, result_3_2_0);
-  }
-
-  // Test for alpha == 2 and beta == 2
-  {
-    nntrainer::Tensor ans_0_2_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{128, 136, 144, 152, 160, 168, 176, 184, 192, 200}},
-          {{208, 216, 224, 232, 240, 248, 256, 264, 272, 280}}}}));
-
-    nntrainer::Tensor ans_1_2_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{26, 32, 38, 44, 50, 56, 62, 68, 74, 80}}},
-         {{{126, 132, 138, 144, 150, 156, 162, 168, 174, 180}}},
-         {{{226, 232, 238, 244, 250, 256, 262, 268, 274, 280}}}}));
-
-    nntrainer::Tensor ans_2_2_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{4, 8, 12, 16, 20, 24, 28, 32, 36, 40}},
-          {{44, 48, 52, 56, 60, 64, 68, 72, 76, 80}}},
-         {{{84, 88, 92, 96, 100, 104, 108, 112, 116, 120}},
-          {{124, 128, 132, 136, 140, 144, 148, 152, 156, 160}}},
-         {{{164, 168, 172, 176, 180, 184, 188, 192, 196, 200}},
-          {{204, 208, 212, 216, 220, 224, 228, 232, 236, 240}}}}));
-
-    nntrainer::Tensor ans_3_2_2(
-      std::vector<std::vector<std::vector<std::vector<float>>>>(
-        {{{{112}}, {{314}}}, {{{516}}, {{718}}}, {{{920}}, {{1122}}}}));
-
-    nntrainer::Tensor output_0_2_2(1, channel, height, width);
-    {
-      const int batch = 1;
-      GEN_TEST_INPUT(output_0_2_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor output_1_2_2(batch, 1, height, width);
-    {
-      const int channel = 1;
-      GEN_TEST_INPUT(output_1_2_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor output_2_2_2(batch, channel, 1, width);
-    {
-      const int height = 1;
-      GEN_TEST_INPUT(output_2_2_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor output_3_2_2(batch, channel, height, 1);
-    {
-      const int width = 1;
-      GEN_TEST_INPUT(output_3_2_2, i * (channel * height * width) +
-                                     j * (height * width) + k * (width) + l +
-                                     1);
-    }
-    nntrainer::Tensor result_0_2_2 = input.sum(0, output_0_2_2, 2, 2);
-    nntrainer::Tensor result_1_2_2 = input.sum(1, output_1_2_2, 2, 2);
-    nntrainer::Tensor result_2_2_2 = input.sum(2, output_2_2_2, 2, 2);
-    nntrainer::Tensor result_3_2_2 = input.sum(3, output_3_2_2, 2, 2);
-
-    EXPECT_EQ(ans_0_2_2, result_0_2_2);
-    EXPECT_EQ(ans_1_2_2, result_1_2_2);
-    EXPECT_EQ(ans_2_2_2, result_2_2_2);
-    EXPECT_EQ(ans_3_2_2, result_3_2_2);
-  }
-}
-
-TEST(nntrainer_Tensor, sum_04_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 2;
-  int height = 2;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (batch * height * channel) + j * (height * width) +
-                          k * width + l + 1);
-
-  nntrainer::Tensor result = input.sum_by_batch();
-  if (result.getValue(0, 0, 0, 0) != 820 ||
-      result.getValue(1, 0, 0, 0) != 1300 ||
-      result.getValue(2, 0, 0, 0) != 1780)
-    status = ML_ERROR_RESULT_OUT_OF_RANGE;
-
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, multiple_sum_invalid_args_01_n) {
-  nntrainer::Tensor t = constant(1.0, 1, 1, 1, 1);
-  EXPECT_THROW(t.sum(std::vector<unsigned int>()), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, multiple_sum_out_of_range_n) {
-  nntrainer::Tensor t = constant(1.0, 1, 1, 1, 1);
-  EXPECT_THROW(t.sum({7}), std::out_of_range);
-}
-
-TEST(nntrainer_Tensor, multiple_sum_p) {
-  nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-  nntrainer::Tensor actual, expected;
-
-  actual = t.sum({0, 1});
-  expected = constant(2 * 3, 1, 1, 5, 7);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.sum({1, 2, 3});
-  expected = constant(3 * 5 * 7, 2, 1, 1, 1);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.sum({3, 1});
-  expected = constant(7 * 3, 2, 1, 5, 1);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.sum({3, 1}, 0.5);
-  expected = constant(7 * 3 * 0.5, 2, 1, 5, 1);
-  EXPECT_EQ(actual, expected);
-}
-
-TEST(nntrainer_Tensor, average_p) {
-  nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-
-  nntrainer::Tensor actual, expected;
-
-  actual = t.average();
-  expected = constant(1.0, 1, 1, 1, 1);
-  EXPECT_EQ(actual, expected);
-
-  int idx = 0;
-  t = t.apply([&](float in) { return idx++ % 2; });
-
-  actual = t.average();
-  expected = constant(0.5, 1, 1, 1, 1);
-  EXPECT_EQ(actual, expected);
-}
-
-TEST(nntrainer_Tensor, average_axis_p) {
-  nntrainer::Tensor t = constant(1.0, 2, 2, 2, 2);
-  int idx = 0;
-  std::function<float(float)> f = [&](float in) { return idx++ % 2; };
-  t = t.apply(f);
-
-  nntrainer::Tensor actual, expected;
-
-  actual = t.average(0);
-  expected = constant(0, 1, 2, 2, 2).apply(f);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.average(1);
-  expected = constant(0, 2, 1, 2, 2).apply(f);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.average(2);
-  expected = constant(0, 2, 2, 1, 2).apply(f);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.average(3);
-  expected = constant(0.5, 2, 2, 2, 1);
-  EXPECT_EQ(actual, expected);
-}
-
-TEST(nntrainer_Tensor, average_axis_out_of_range_01_n) {
-  nntrainer::Tensor t = constant(1.0, 2, 2, 2, 2);
-  EXPECT_THROW(t.average(-1), std::out_of_range);
-}
-
-TEST(nntrainer_Tensor, average_axis_out_of_range_02_n) {
-  nntrainer::Tensor t = constant(1.0, 2, 2, 2, 2);
-  EXPECT_THROW(t.average(7), std::out_of_range);
-}
-
-TEST(nntrainer_Tensor, average_multiple_axes_p) {
-  nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-  nntrainer::Tensor actual, expected;
-
-  actual = t.average({0, 1, 2});
-  expected = constant(1.0, 1, 1, 1, 7);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.average({0, 1, 2, 3});
-  expected = constant(1.0, 1, 1, 1, 1);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.average({3, 1});
-  expected = constant(1.0, 2, 1, 5, 1);
-  EXPECT_EQ(actual, expected);
-
-  actual = t.average({3, 1, 1, 1, 3});
-  expected = constant(1.0, 2, 1, 5, 1);
-  EXPECT_EQ(actual, expected);
-}
-
-TEST(nntrainer_Tensor, average_multiple_axes_01_n) {
-  nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-  EXPECT_THROW(t.average({5, 7}), std::out_of_range);
-}
-
-TEST(nntrainer_Tensor, dot_01_n) {
-  nntrainer::Tensor input(2, 3, 4, 5);
-  nntrainer::Tensor m(1, 3, 4, 5);
-  EXPECT_THROW(nntrainer::Tensor result = input.dot(m), std::runtime_error);
-}
-
-TEST(nntrainer_Tensor, dot_02_n) {
-  nntrainer::Tensor input(2, 3, 4, 5);
-  nntrainer::Tensor m(1, 3, 4, 5);
-  EXPECT_THROW(nntrainer::Tensor result = input.dot(m, true),
-               std::runtime_error);
-}
-
-TEST(nntrainer_Tensor, dot_02_p) {
-  nntrainer::Tensor input(2, 3, 4, 5);
-  nntrainer::Tensor m(1, 3, 4, 5);
-  EXPECT_NO_THROW(nntrainer::Tensor result = input.dot(m, false, true));
-}
-
-TEST(nntrainer_Tensor, dot_03_p) {
-  nntrainer::Tensor input(1, 3, 4, 5);
-  nntrainer::Tensor m(1, 3, 4, 5);
-  EXPECT_NO_THROW(nntrainer::Tensor result = input.dot(m, true));
-}
-
-TEST(nntrainer_Tensor, dot_04_n) {
-  nntrainer::Tensor input(2, 3, 4, 5);
-  nntrainer::Tensor m(1, 1, 4, 5);
-  EXPECT_THROW(nntrainer::Tensor result = input.dot(m), std::runtime_error);
-  EXPECT_NO_THROW(nntrainer::Tensor result = input.dot(m, false, true));
-}
-
-TEST(nntrainer_Tensor, dot_05_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 2;
-  int channel = 3;
-  int height = 4;
-  int width = 5;
-  float ans[2][3][4][24] = {0};
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (channel * width * height) + j * (height * width) +
-                          k * (width) + l + 1);
-  nntrainer::Tensor weight(batch, channel, height, width);
-  GEN_TEST_INPUT(weight, i * (channel * width * height) + j * (height * width) +
-                           k * (width) + l + 1);
-  weight.reshape({1, 1, 24, 5});
-
-  nntrainer::Tensor result = input.dot(weight, false, true);
-
-  for (int b = 0; b < batch; b++) {
-    for (int c = 0; c < channel; c++) {
-      for (int h = 0; h < height; h++) {
-        for (int k = 0; k < batch * channel * height; k++) {
-          ans[b][c][h][k] = 0;
-          for (int w = 0; w < width; w++) {
-            float val1 = input.getValue(b, c, h, w);
-            float val2 = weight.getValue(0, 0, k, w);
-            ans[b][c][h][k] += val1 * val2;
-          }
-        }
-      }
-    }
-  }
-
-  for (unsigned int i = 0; i < result.batch(); ++i) {
-    for (unsigned int c = 0; c < result.channel(); ++c) {
-      for (unsigned int j = 0; j < result.height(); ++j) {
-        for (unsigned int k = 0; k < result.width(); ++k) {
-          float val1 = ans[i][c][j][k];
-          float val2 = result.getValue(i, c, j, k);
-          if (val1 != val2) {
-            status = ML_ERROR_RESULT_OUT_OF_RANGE;
-            goto end_dot_01_p;
-          }
-        }
-      }
-    }
-  }
-end_dot_01_p:
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, dot_06_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 1;
-  int width = 3;
-  float ans[3][1][1][3] = {
-    {{{30, 36, 42}}}, {{{66, 81, 96}}}, {{{102, 126, 150}}}};
-
-  nntrainer::Tensor input(batch, channel, height, width);
-  GEN_TEST_INPUT(input, i * (channel * width * height) + j * (height * width) +
-                          k * (width) + l + 1);
-
-  nntrainer::Tensor result = input.dot(input);
-
-  for (unsigned int i = 0; i < result.batch(); ++i) {
-    for (unsigned int j = 0; j < result.height(); ++j) {
-      for (unsigned int k = 0; k < result.width(); ++k) {
-        if (ans[i][0][j][k] != result.getValue(i, 0, j, k)) {
-          status = ML_ERROR_RESULT_OUT_OF_RANGE;
-          goto end_dot_01_p;
-        }
-      }
-    }
-  }
-end_dot_01_p:
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, dot_transpose_p) {
-  {
-    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-                           92, 113, 134, 155, 128, 158, 188, 218};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-                           92, 113, 134, 155, 128, 158, 188, 218};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-                           92, 113, 134, 155, 128, 158, 188, 218};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-                           92, 113, 134, 155, 128, 158, 188, 218};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 1, 4, 2, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 1, 4, 2, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-    float b_data[] = {0, 2, 4, 1, 3, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-    float b_data[] = {0, 2, 4, 1, 3, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 1, 4, 2, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-    float b_data[] = {0, 2, 4, 1, 3, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-    float answer_data[] = {10, 13, 28, 40};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 1, 4, 2, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-    float answer_data[] = {10, 13, 28, 40};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-    float b_data[] = {0, 2, 4, 1, 3, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-    float answer_data[] = {10, 13, 28, 40};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-    float answer_data[] = {10, 13, 28, 40};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-}
-
-TEST(nntrainer_Tensor, dot_shortcuts_p) {
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-    float answer_data[] = {5};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-    float answer_data[] = {5};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-    float answer_data[] = {5};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-    float answer_data[] = {5};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-    float answer_data[] = {5, 14};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 1, 4, 2, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-    float answer_data[] = {5, 14};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-    float answer_data[] = {5, 14};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 1, 4, 2, 5};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-    float answer_data[] = {5, 14};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-    float answer_data[] = {5, 14, 23, 32};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-    float answer_data[] = {5, 14, 23, 32};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-    float answer_data[] = {5, 14, 23, 32};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-    float b_data[] = {0, 1, 2};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-    float answer_data[] = {5, 14, 23, 32};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-    float answer_data[] = {20, 23, 26, 29};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-    float answer_data[] = {10, 13};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 1, 2, 3, 4, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-    float answer_data[] = {10, 13};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, false);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-    float b_data[] = {0, 2, 4, 1, 3, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-    float answer_data[] = {10, 13};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, false, true);
-    EXPECT_EQ(ret, answer);
-  }
-  {
-    float a_data[] = {0, 1, 2};
-    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-    float b_data[] = {0, 2, 4, 1, 3, 5};
-    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-    float answer_data[] = {10, 13};
-    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-    nntrainer::Tensor ret = a.dot(b, true, true);
-    EXPECT_EQ(ret, answer);
-  }
-}
-
-TEST(nntrainer_Tensor, transpose_p) {
-  nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-
-  /// plain transpose
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-      14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-      28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-      42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-      56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-      70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-      84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
-      98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-      112, 113, 114, 115, 116, 117, 118, 119};
-    nntrainer::Tensor answer({3, 2, 4, 5}, answer_data);
-    nntrainer::Tensor m = t.transpose("0:1:2");
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    float answer_data[] = {
-      0,   5,   10,  15,  1,   6,   11,  16,  2,   7,   12,  17,  3,   8,
-      13,  18,  4,   9,   14,  19,  20,  25,  30,  35,  21,  26,  31,  36,
-      22,  27,  32,  37,  23,  28,  33,  38,  24,  29,  34,  39,  40,  45,
-      50,  55,  41,  46,  51,  56,  42,  47,  52,  57,  43,  48,  53,  58,
-      44,  49,  54,  59,  60,  65,  70,  75,  61,  66,  71,  76,  62,  67,
-      72,  77,  63,  68,  73,  78,  64,  69,  74,  79,  80,  85,  90,  95,
-      81,  86,  91,  96,  82,  87,  92,  97,  83,  88,  93,  98,  84,  89,
-      94,  99,  100, 105, 110, 115, 101, 106, 111, 116, 102, 107, 112, 117,
-      103, 108, 113, 118, 104, 109, 114, 119};
-    nntrainer::Tensor answer({3, 2, 5, 4}, answer_data);
-    nntrainer::Tensor m = t.transpose("0:2:1");
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   20,  21,  22,  23,  24,  5,   6,   7,   8,
-      9,   25,  26,  27,  28,  29,  10,  11,  12,  13,  14,  30,  31,  32,
-      33,  34,  15,  16,  17,  18,  19,  35,  36,  37,  38,  39,  40,  41,
-      42,  43,  44,  60,  61,  62,  63,  64,  45,  46,  47,  48,  49,  65,
-      66,  67,  68,  69,  50,  51,  52,  53,  54,  70,  71,  72,  73,  74,
-      55,  56,  57,  58,  59,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-      84,  100, 101, 102, 103, 104, 85,  86,  87,  88,  89,  105, 106, 107,
-      108, 109, 90,  91,  92,  93,  94,  110, 111, 112, 113, 114, 95,  96,
-      97,  98,  99,  115, 116, 117, 118, 119};
-    nntrainer::Tensor answer({3, 4, 2, 5}, answer_data);
-    nntrainer::Tensor m = t.transpose("1:0:2");
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    float answer_data[] = {
-      0,  20,  1,  21,  2,  22,  3,  23,  4,  24,  5,  25,  6,  26,  7,  27,
-      8,  28,  9,  29,  10, 30,  11, 31,  12, 32,  13, 33,  14, 34,  15, 35,
-      16, 36,  17, 37,  18, 38,  19, 39,  40, 60,  41, 61,  42, 62,  43, 63,
-      44, 64,  45, 65,  46, 66,  47, 67,  48, 68,  49, 69,  50, 70,  51, 71,
-      52, 72,  53, 73,  54, 74,  55, 75,  56, 76,  57, 77,  58, 78,  59, 79,
-      80, 100, 81, 101, 82, 102, 83, 103, 84, 104, 85, 105, 86, 106, 87, 107,
-      88, 108, 89, 109, 90, 110, 91, 111, 92, 112, 93, 113, 94, 114, 95, 115,
-      96, 116, 97, 117, 98, 118, 99, 119};
-    nntrainer::Tensor answer({3, 4, 5, 2}, answer_data);
-    nntrainer::Tensor m = t.transpose("1:2:0");
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    float answer_data[] = {
-      0,  5,  10,  15,  20,  25,  30,  35, 1,  6,   11,  16,  21,  26,  31,
-      36, 2,  7,   12,  17,  22,  27,  32, 37, 3,   8,   13,  18,  23,  28,
-      33, 38, 4,   9,   14,  19,  24,  29, 34, 39,  40,  45,  50,  55,  60,
-      65, 70, 75,  41,  46,  51,  56,  61, 66, 71,  76,  42,  47,  52,  57,
-      62, 67, 72,  77,  43,  48,  53,  58, 63, 68,  73,  78,  44,  49,  54,
-      59, 64, 69,  74,  79,  80,  85,  90, 95, 100, 105, 110, 115, 81,  86,
-      91, 96, 101, 106, 111, 116, 82,  87, 92, 97,  102, 107, 112, 117, 83,
-      88, 93, 98,  103, 108, 113, 118, 84, 89, 94,  99,  104, 109, 114, 119};
-    nntrainer::Tensor answer({3, 5, 2, 4}, answer_data);
-    nntrainer::Tensor m = t.transpose("2:0:1");
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    float answer_data[] = {
-      0,  20,  5,  25,  10, 30,  15, 35,  1,  21,  6,  26,  11, 31,  16, 36,
-      2,  22,  7,  27,  12, 32,  17, 37,  3,  23,  8,  28,  13, 33,  18, 38,
-      4,  24,  9,  29,  14, 34,  19, 39,  40, 60,  45, 65,  50, 70,  55, 75,
-      41, 61,  46, 66,  51, 71,  56, 76,  42, 62,  47, 67,  52, 72,  57, 77,
-      43, 63,  48, 68,  53, 73,  58, 78,  44, 64,  49, 69,  54, 74,  59, 79,
-      80, 100, 85, 105, 90, 110, 95, 115, 81, 101, 86, 106, 91, 111, 96, 116,
-      82, 102, 87, 107, 92, 112, 97, 117, 83, 103, 88, 108, 93, 113, 98, 118,
-      84, 104, 89, 109, 94, 114, 99, 119};
-    nntrainer::Tensor answer({3, 5, 4, 2}, answer_data);
-    nntrainer::Tensor m = t.transpose("2:1:0");
-    EXPECT_EQ(answer, m);
-  }
-
-  /// outplace transpose
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 2, 4, 5);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-      14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-      28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-      42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-      56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-      70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-      84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
-      98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-      112, 113, 114, 115, 116, 117, 118, 119};
-    nntrainer::Tensor answer({3, 2, 4, 5}, answer_data);
-    t.transpose("0:1:2", m);
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 2, 5, 4);
-    float answer_data[] = {
-      0,   5,   10,  15,  1,   6,   11,  16,  2,   7,   12,  17,  3,   8,
-      13,  18,  4,   9,   14,  19,  20,  25,  30,  35,  21,  26,  31,  36,
-      22,  27,  32,  37,  23,  28,  33,  38,  24,  29,  34,  39,  40,  45,
-      50,  55,  41,  46,  51,  56,  42,  47,  52,  57,  43,  48,  53,  58,
-      44,  49,  54,  59,  60,  65,  70,  75,  61,  66,  71,  76,  62,  67,
-      72,  77,  63,  68,  73,  78,  64,  69,  74,  79,  80,  85,  90,  95,
-      81,  86,  91,  96,  82,  87,  92,  97,  83,  88,  93,  98,  84,  89,
-      94,  99,  100, 105, 110, 115, 101, 106, 111, 116, 102, 107, 112, 117,
-      103, 108, 113, 118, 104, 109, 114, 119};
-    nntrainer::Tensor answer({3, 2, 5, 4}, answer_data);
-    t.transpose("0:2:1", m);
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 4, 2, 5);
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   20,  21,  22,  23,  24,  5,   6,   7,   8,
-      9,   25,  26,  27,  28,  29,  10,  11,  12,  13,  14,  30,  31,  32,
-      33,  34,  15,  16,  17,  18,  19,  35,  36,  37,  38,  39,  40,  41,
-      42,  43,  44,  60,  61,  62,  63,  64,  45,  46,  47,  48,  49,  65,
-      66,  67,  68,  69,  50,  51,  52,  53,  54,  70,  71,  72,  73,  74,
-      55,  56,  57,  58,  59,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-      84,  100, 101, 102, 103, 104, 85,  86,  87,  88,  89,  105, 106, 107,
-      108, 109, 90,  91,  92,  93,  94,  110, 111, 112, 113, 114, 95,  96,
-      97,  98,  99,  115, 116, 117, 118, 119};
-    nntrainer::Tensor answer({3, 4, 2, 5}, answer_data);
-    t.transpose("1:0:2", m);
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 4, 5, 2);
-    float answer_data[] = {
-      0,  20,  1,  21,  2,  22,  3,  23,  4,  24,  5,  25,  6,  26,  7,  27,
-      8,  28,  9,  29,  10, 30,  11, 31,  12, 32,  13, 33,  14, 34,  15, 35,
-      16, 36,  17, 37,  18, 38,  19, 39,  40, 60,  41, 61,  42, 62,  43, 63,
-      44, 64,  45, 65,  46, 66,  47, 67,  48, 68,  49, 69,  50, 70,  51, 71,
-      52, 72,  53, 73,  54, 74,  55, 75,  56, 76,  57, 77,  58, 78,  59, 79,
-      80, 100, 81, 101, 82, 102, 83, 103, 84, 104, 85, 105, 86, 106, 87, 107,
-      88, 108, 89, 109, 90, 110, 91, 111, 92, 112, 93, 113, 94, 114, 95, 115,
-      96, 116, 97, 117, 98, 118, 99, 119};
-    nntrainer::Tensor answer({3, 4, 5, 2}, answer_data);
-    t.transpose("1:2:0", m);
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 5, 2, 4);
-    float answer_data[] = {
-      0,  5,  10,  15,  20,  25,  30,  35, 1,  6,   11,  16,  21,  26,  31,
-      36, 2,  7,   12,  17,  22,  27,  32, 37, 3,   8,   13,  18,  23,  28,
-      33, 38, 4,   9,   14,  19,  24,  29, 34, 39,  40,  45,  50,  55,  60,
-      65, 70, 75,  41,  46,  51,  56,  61, 66, 71,  76,  42,  47,  52,  57,
-      62, 67, 72,  77,  43,  48,  53,  58, 63, 68,  73,  78,  44,  49,  54,
-      59, 64, 69,  74,  79,  80,  85,  90, 95, 100, 105, 110, 115, 81,  86,
-      91, 96, 101, 106, 111, 116, 82,  87, 92, 97,  102, 107, 112, 117, 83,
-      88, 93, 98,  103, 108, 113, 118, 84, 89, 94,  99,  104, 109, 114, 119};
-    nntrainer::Tensor answer({3, 5, 2, 4}, answer_data);
-    t.transpose("2:0:1", m);
-    EXPECT_EQ(answer, m);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    nntrainer::Tensor m = ranged(3, 5, 4, 2);
-    float answer_data[] = {
-      0,  20,  5,  25,  10, 30,  15, 35,  1,  21,  6,  26,  11, 31,  16, 36,
-      2,  22,  7,  27,  12, 32,  17, 37,  3,  23,  8,  28,  13, 33,  18, 38,
-      4,  24,  9,  29,  14, 34,  19, 39,  40, 60,  45, 65,  50, 70,  55, 75,
-      41, 61,  46, 66,  51, 71,  56, 76,  42, 62,  47, 67,  52, 72,  57, 77,
-      43, 63,  48, 68,  53, 73,  58, 78,  44, 64,  49, 69,  54, 74,  59, 79,
-      80, 100, 85, 105, 90, 110, 95, 115, 81, 101, 86, 106, 91, 111, 96, 116,
-      82, 102, 87, 107, 92, 112, 97, 117, 83, 103, 88, 108, 93, 113, 98, 118,
-      84, 104, 89, 109, 94, 114, 99, 119};
-    nntrainer::Tensor answer({3, 5, 4, 2}, answer_data);
-    t.transpose("2:1:0", m);
-    EXPECT_EQ(answer, m);
-  }
-}
-
-TEST(nntrainer_Tensor, tranpose_dimension_not_match_n) {
-  nntrainer::Tensor a(3, 2, 4, 5);
-  nntrainer::Tensor b(3, 1, 2, 3);
-
-  EXPECT_THROW(a.transpose("0:1:2", b), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, set_01_p) {
-  nntrainer::Tensor tensor = nntrainer::Tensor(1, 1, 1, 1);
-
-  tensor.setZero();
-  EXPECT_EQ(tensor.getValue(0, 0, 0, 0), 0.0);
-
-  tensor.setRandUniform(-0.5, 0);
-  float val = tensor.getValue(0, 0, 0, 0);
-  EXPECT_TRUE(val >= -0.5 && val < 0);
-}
-
-TEST(nntrainer_Tensor, save_read_01_p) {
-  int batch = 3;
-  int channel = 4;
-  int height = 5;
-  int width = 6;
-  nntrainer::Tensor target(3, 4, 5, 6);
-  nntrainer::Tensor readed(3, 4, 5, 6);
-
-  GEN_TEST_INPUT(target, i * (channel * width * height) + j * (height * width) +
-                           k * (width) + l + 1);
-
-  std::ofstream save_file("save.bin", std::ios::out | std::ios::binary);
-  target.save(save_file);
-  save_file.close();
-
-  std::ifstream read_file("save.bin");
-  readed.read(read_file);
-  read_file.close();
-
-  EXPECT_EQ(target, readed);
-
-  int status = std::remove("save.bin");
-
-  ASSERT_EQ(status, 0);
-}
-
-TEST(nntrainer_Tensor, save_read_01_n) {
-  int batch = 3;
-  int channel = 4;
-  int height = 5;
-  int width = 6;
-  nntrainer::Tensor target(3, 4, 5, 6);
-  nntrainer::Tensor readed(3, 4, 1, 1);
-
-  GEN_TEST_INPUT(target, i * (channel * width * height) + j * (height * width) +
-                           k * (width) + l + 1);
-
-  std::ofstream save_file("save.bin", std::ios::out | std::ios::binary);
-  target.save(save_file);
-  save_file.close();
-
-  std::ifstream read_file("save.bin");
-  readed.read(read_file);
-  read_file.close();
-
-  EXPECT_NE(target, readed);
-
-  int status = std::remove("save.bin");
-
-  ASSERT_EQ(status, 0);
-}
-
-TEST(nntrainer_Tensor, copy_and_shares_variable_p) {
-  nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-  nntrainer::Tensor B = A.clone();
-  nntrainer::Tensor C = A;
-
-  C.setValue(1, 1, 1, 1, 2.0f);
-
-  EXPECT_EQ(A, C);
-  EXPECT_NE(B, C);
-
-  C.reshape(nntrainer::TensorDim(3, 4, 6, 5));
-  EXPECT_EQ(A.getDim(), B.getDim());
-  EXPECT_NE(A.getDim(), C.getDim());
-}
-
-TEST(nntrainer_Tensor, reshape_n_01) {
-  nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-
-  EXPECT_THROW(A.reshape(nntrainer::TensorDim(9, 9, 9, 9)),
-               std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, reshape_n_02) {
-  nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-  nntrainer::TensorDim A_dim = A.getDim();
-
-  /** Changing the dim of a tensor only affects local copy of the dim */
-  A_dim.setTensorDim(1, 100);
-  EXPECT_EQ(A_dim.getTensorDim(1), 100u);
-
-  nntrainer::TensorDim A_dim_2 = A.getDim();
-  EXPECT_EQ(A_dim_2.getTensorDim(1), 4u);
-}
-
-TEST(nntrainer_Tensor, copy_and_reshape_n) {
-  nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-  nntrainer::Tensor B = A;
-  nntrainer::Tensor C = A.clone();
-
-  EXPECT_THROW(B.reshape(nntrainer::TensorDim(9, 9, 9, 9)),
-               std::invalid_argument);
-}
-
-/// @note this test case demonstrates it is dangerous to use sharedConstTensor
-/// to const correct the inner data.
-TEST(nntrainer_Tensor, constructor_from_shared_const_ptr_shares_variable_n) {
-  nntrainer::sharedConstTensor A =
-    MAKE_SHARED_TENSOR(constant(1.0f, 3, 4, 5, 6));
-
-  nntrainer::Tensor B = *A;
-  nntrainer::Tensor C = A->clone();
-
-  B.setValue(2, 3, 4, 5, 2.0f);
-  EXPECT_EQ(*A, B);
-  EXPECT_NE(*A, C);
-
-  C.reshape(nntrainer::TensorDim(3, 4, 6, 5));
-  EXPECT_EQ(A->getDim(), B.getDim());
-  EXPECT_NE(A->getDim(), C.getDim());
-}
-
-TEST(nntrainer_Tensor, print_small_size) {
-  nntrainer::Tensor target = constant(1.0, 3, 1, 2, 3);
-
-  std::stringstream ss, expected;
-  ss << target;
-
-  expected << '<' << typeid(target).name() << " at " << &target << ">\n"
-           << "data addr: " << target.getData() << '\n'
-           << "Shape: 3:1:2:3\n"
-           << "         1          1          1 \n"
-           << "         1          1          1 \n"
-           << "\n"
-           << "-------\n"
-           << "         1          1          1 \n"
-           << "         1          1          1 \n"
-           << "\n"
-           << "-------\n"
-           << "         1          1          1 \n"
-           << "         1          1          1 \n"
-           << "\n"
-           << "-------\n";
-
-  EXPECT_EQ(ss.str(), expected.str());
-}
-
-// TEST(nntrainer_Tensor, print_large_size) {
-//   nntrainer::Tensor target = constant(1.2, 3, 10, 10, 10);
-
-//   std::stringstream ss, expected;
-
-//   expected << '<' << typeid(target).name() << " at " << &target << ">\n"
-//            << "data addr: " << target.getData() << '\n'
-//            << "Shape: 3:10:10:10\n"
-//            << "[1.2 1.2 1.2 ... 1.2 1.2 1.2]\n";
-//   ss << target;
-
-//   EXPECT_EQ(ss.str(), expected.str());
-// }
-
-TEST(nntrainer_Tensor, DISABLED_equation_test_01_p) {
-  nntrainer::Tensor a, b, c;
-  nntrainer::Tensor ret1, ret2;
-
-  a = randUniform(4, 6, 7, 3, -100, 100);
-  b = randUniform(4, 6, 7, 3, -100, 100);
-  c = randUniform(4, 6, 7, 3, -100, 100);
-
-  ret1 = a.subtract(b).multiply(c);
-  ret2 = a.multiply(c).subtract(b.multiply(c));
-
-  float *data1 = ret1.getData();
-  float *data2 = ret2.getData();
-  EXPECT_EQ(ret1, ret2);
-
-  for (unsigned int i = 0; i < ret1.size(); ++i) {
-    EXPECT_FLOAT_EQ(data1[i], data2[i]);
-  }
-}
-
-TEST(nntrainer_Tensor, fill_p) {
-  /// same dimension, buffer size
-  {
-    nntrainer::Tensor target(3, 2, 4, 5);
-    nntrainer::Tensor original = randUniform(3, 2, 4, 5, -1.0f, 1.0f);
-    target.fill(original, false);
-
-    EXPECT_EQ(target, original);
-  }
-
-  /// same dimension, buffer size is different (not tested)
-  {
-    /// there is no way to make non contiguous tensor publicily yet
-    EXPECT_TRUE(true);
-  }
-
-  /// uninitialized with initialized flag is true
-  {
-    nntrainer::Tensor target;
-    nntrainer::Tensor original = randUniform(3, 2, 4, 5, -1.0f, 1.0f);
-    target.fill(original, true);
-
-    EXPECT_EQ(target, original);
-  }
-}
-
-TEST(nntrainer_Tensor, fill_uninitialized_n) {
-  nntrainer::Tensor target;
-  nntrainer::Tensor original = randUniform(3, 1, 2, 3, -1.0f, 1.0f);
-  EXPECT_THROW(target.fill(original, false), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, fill_different_dimension_n) {
-  nntrainer::Tensor target(3, 1, 3, 2);
-  nntrainer::Tensor original = randUniform(3, 1, 2, 3, -1.0f, 1.0f);
-  EXPECT_THROW(target.fill(original, false), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, DISABLED_fill_non_contiguous_n) {
-  /// there is no way to make non contiguous tensor publicily yet
-  EXPECT_TRUE(false);
-}
-
-TEST(nntrainer_Tensor, DISABLED_fill_different_buffer_size_n) {
-  /// there is no way to make same dimension, diffrent buffersized tensor
-  /// publicily yet
-  EXPECT_TRUE(false);
-}
-
-TEST(nntrainer_Tensor, empty_01) {
-  nntrainer::Tensor t;
-
-  EXPECT_TRUE(t.empty());
-}
-
-TEST(nntrainer_Tensor, empty_02) {
-  nntrainer::Tensor t({1, 2, 3, 4}, false);
-
-  EXPECT_FALSE(t.empty());
-}
-
-TEST(nntrainer_Tensor, empty_03) {
-  nntrainer::Tensor t({1, 2, 3, 4}, true);
-
-  EXPECT_FALSE(t.empty());
-}
-
-TEST(nntrainer_Tensor, allocate_01_n) {
-  nntrainer::Tensor t;
-  EXPECT_FALSE(t.isAllocated());
-
-  t.allocate();
-  EXPECT_FALSE(t.isAllocated());
-}
-
-TEST(nntrainer_Tensor, allocate_02_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, false);
-  EXPECT_FALSE(t.isAllocated());
-
-  t.allocate();
-  EXPECT_TRUE(t.isAllocated());
-}
-
-TEST(nntrainer_Tensor, allocate_03_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, true);
-  EXPECT_TRUE(t.isAllocated());
-
-  t.allocate();
-  EXPECT_TRUE(t.isAllocated());
-}
-
-TEST(nntrainer_Tensor, initialize_01_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-
-  nntrainer::Tensor golden(1, 2, 3, 4);
-  golden.setValue(1);
-
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, initialize_02_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, true);
-
-  nntrainer::Tensor golden(1, 2, 3, 4);
-  golden.setValue(1);
-
-  EXPECT_NE(golden, t);
-
-  t.initialize(nntrainer::Tensor::Initializer::ONES);
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, initialize_03_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, false,
-                      nntrainer::Tensor::Initializer::ONES);
-  t.allocate();
-
-  nntrainer::Tensor golden(1, 2, 3, 4);
-  golden.setValue(1);
-
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, initialize_04_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, false);
-  t.initialize(nntrainer::Tensor::Initializer::ONES);
-  t.allocate();
-
-  nntrainer::Tensor golden(1, 2, 3, 4);
-  golden.setValue(1);
-
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, initialize_05_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, false);
-  t.allocate();
-
-  nntrainer::Tensor golden(1, 2, 3, 4);
-  golden.setValue(1.f);
-
-  /**
-   * Ideally, it should be NE, but it can be equal due to no initialization
-   * EXPECT_NE(golden, t);
-   */
-
-  t.initialize(nntrainer::Tensor::Initializer::ONES);
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, initialize_06_n) {
-  nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-  nntrainer::Tensor golden({1, 2, 3, 4}, true,
-                           nntrainer::Tensor::Initializer::ZEROS);
-
-  EXPECT_NE(golden, t);
-
-  golden.initialize(nntrainer::Tensor::Initializer::ONES);
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, initialize_07_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-
-  nntrainer::Tensor golden(1, 2, 3, 4);
-  golden.setValue(1);
-
-  EXPECT_EQ(golden, t);
-
-  t.setValue(0, 0, 0, 0, 0);
-  t.setValue(0, 0, 0, t.size() - 1, 0);
-  EXPECT_NE(golden, t);
-
-  t.initialize();
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, initialize_08_p) {
-  nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-
-  nntrainer::Tensor golden(1, 2, 3, 4, nntrainer::Tformat::NCHW, nntrainer::DataType::FP32);
-  golden.setValue(1);
-  EXPECT_EQ(golden, t);
-
-  t.initialize(nntrainer::Tensor::Initializer::HE_NORMAL);
-  EXPECT_NE(golden, t);
-
-
-  t.initialize();
-  EXPECT_NE(golden, t);
-
-  t.initialize(nntrainer::Tensor::Initializer::ONES);
-  EXPECT_EQ(golden, t);
-
-  t.initialize();
-  EXPECT_EQ(golden, t);
-}
-
-TEST(nntrainer_Tensor, split_01_p) {
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(3);
-    {
-      float answer_data[] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
-                             10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
-                             20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
-                             30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
-      answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-    }
-    {
-      float answer_data[] = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
-                             50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
-                             60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
-                             70, 71, 72, 73, 74, 75, 76, 77, 78, 79};
-      answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-    }
-    {
-      float answer_data[] = {80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-                             90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-                             100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-                             110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-      answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-    }
-    EXPECT_EQ(t.split(3, 0), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(2);
-    {
-      float answer_data[] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11,
-                             12, 13, 14, 15, 16, 17, 18, 19, 40, 41, 42, 43,
-                             44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
-                             56, 57, 58, 59, 80, 81, 82, 83, 84, 85, 86, 87,
-                             88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99};
-      answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-    }
-    {
-      float answer_data[] = {20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-                             30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
-                             60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-                             70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
-                             100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-                             110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-    }
-    EXPECT_EQ(t.split(2, 1), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(2);
-    {
-      float answer_data[] = {
-        0,  1,  2,  3,  4,  5,   6,   7,   8,   9,   20,  21,  22,  23,  24,
-        25, 26, 27, 28, 29, 40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
-        60, 61, 62, 63, 64, 65,  66,  67,  68,  69,  80,  81,  82,  83,  84,
-        85, 86, 87, 88, 89, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-    }
-    {
-      float answer_data[] = {
-        10, 11, 12, 13, 14, 15,  16,  17,  18,  19,  30,  31,  32,  33,  34,
-        35, 36, 37, 38, 39, 50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-        70, 71, 72, 73, 74, 75,  76,  77,  78,  79,  90,  91,  92,  93,  94,
-        95, 96, 97, 98, 99, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-    }
-    EXPECT_EQ(t.split(2, 2), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(5);
-    {
-      float answer_data[] = {0,  5,  10, 15, 20,  25,  30,  35,
-                             40, 45, 50, 55, 60,  65,  70,  75,
-                             80, 85, 90, 95, 100, 105, 110, 115};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    {
-      float answer_data[] = {1,  6,  11, 16, 21,  26,  31,  36,
-                             41, 46, 51, 56, 61,  66,  71,  76,
-                             81, 86, 91, 96, 101, 106, 111, 116};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    {
-      float answer_data[] = {2,  7,  12, 17, 22,  27,  32,  37,
-                             42, 47, 52, 57, 62,  67,  72,  77,
-                             82, 87, 92, 97, 102, 107, 112, 117};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    {
-      float answer_data[] = {3,  8,  13, 18, 23,  28,  33,  38,
-                             43, 48, 53, 58, 63,  68,  73,  78,
-                             83, 88, 93, 98, 103, 108, 113, 118};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    {
-      float answer_data[] = {4,  9,  14, 19, 24,  29,  34,  39,
-                             44, 49, 54, 59, 64,  69,  74,  79,
-                             84, 89, 94, 99, 104, 109, 114, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    EXPECT_EQ(t.split(5, 3), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(1, 1, 4, 6);
-    nntrainer::Tensor t = ranged(1, 1, 4, 6);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(2);
-    {
-      float answer_data[] = {0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20};
-      answer.emplace_back(ml::train::TensorDim{1, 1, 4, 3}, answer_data);
-    }
-    {
-      float answer_data[] = {3, 4, 5, 9, 10, 11, 15, 16, 17, 21, 22, 23};
-      answer.emplace_back(ml::train::TensorDim{1, 1, 4, 3}, answer_data);
-    }
-    EXPECT_EQ(t.split(2, 3), answer);
-  }
-}
-
-TEST(nntrainer_Tensor, split_02_n) {
-  nntrainer::Tensor t(1, 1, 1, 1);
-  EXPECT_THROW(t.split(0, 0), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, split_03_n) {
-  nntrainer::Tensor t(3, 1, 1, 1);
-  EXPECT_THROW(t.split(2, 0), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, split_04_p) {
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(2);
-    {
-      float answer_data[] = {
-        0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
-        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-        64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79};
-      answer.emplace_back(ml::train::TensorDim{2, 2, 4, 5}, answer_data);
-    }
-    {
-      float answer_data[] = {80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-                             90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-                             100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-                             110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-      answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-    }
-    EXPECT_EQ(t.split({2, 1}, 0), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(2);
-    {
-      float answer_data[] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11,
-                             12, 13, 14, 15, 16, 17, 18, 19, 40, 41, 42, 43,
-                             44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
-                             56, 57, 58, 59, 80, 81, 82, 83, 84, 85, 86, 87,
-                             88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99};
-      answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-    }
-    {
-      float answer_data[] = {20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-                             30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
-                             60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-                             70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
-                             100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-                             110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-    }
-    EXPECT_EQ(t.split({1, 1}, 1), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(2);
-    {
-      float answer_data[] = {
-        0,  1,  2,  3,  4,  5,   6,   7,   8,   9,   20,  21,  22,  23,  24,
-        25, 26, 27, 28, 29, 40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
-        60, 61, 62, 63, 64, 65,  66,  67,  68,  69,  80,  81,  82,  83,  84,
-        85, 86, 87, 88, 89, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-    }
-    {
-      float answer_data[] = {
-        10, 11, 12, 13, 14, 15,  16,  17,  18,  19,  30,  31,  32,  33,  34,
-        35, 36, 37, 38, 39, 50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-        70, 71, 72, 73, 74, 75,  76,  77,  78,  79,  90,  91,  92,  93,  94,
-        95, 96, 97, 98, 99, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-    }
-    EXPECT_EQ(t.split({2, 2}, 2), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(3);
-    {
-      float answer_data[] = {0,  5,  10, 15, 20,  25,  30,  35,
-                             40, 45, 50, 55, 60,  65,  70,  75,
-                             80, 85, 90, 95, 100, 105, 110, 115};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    {
-      float answer_data[] = {
-        1,   2,   3,   6,   7,   8,   11,  12,  13,  16,  17,  18, 21, 22, 23,
-        26,  27,  28,  31,  32,  33,  36,  37,  38,  41,  42,  43, 46, 47, 48,
-        51,  52,  53,  56,  57,  58,  61,  62,  63,  66,  67,  68, 71, 72, 73,
-        76,  77,  78,  81,  82,  83,  86,  87,  88,  91,  92,  93, 96, 97, 98,
-        101, 102, 103, 106, 107, 108, 111, 112, 113, 116, 117, 118};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 3}, answer_data);
-    }
-    {
-      float answer_data[] = {4,  9,  14, 19, 24,  29,  34,  39,
-                             44, 49, 54, 59, 64,  69,  74,  79,
-                             84, 89, 94, 99, 104, 109, 114, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    EXPECT_EQ(t.split({1, 3, 1}, 3), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(3);
-    {
-      float answer_data[] = {
-        0,  1,  5,  6,  10, 11, 15, 16, 20,  21,  25,  26,  30,  31,  35,  36,
-        40, 41, 45, 46, 50, 51, 55, 56, 60,  61,  65,  66,  70,  71,  75,  76,
-        80, 81, 85, 86, 90, 91, 95, 96, 100, 101, 105, 106, 110, 111, 115, 116};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 2}, answer_data);
-    }
-    {
-      float answer_data[] = {
-        2,  3,  7,  8,  12, 13, 17, 18, 22,  23,  27,  28,  32,  33,  37,  38,
-        42, 43, 47, 48, 52, 53, 57, 58, 62,  63,  67,  68,  72,  73,  77,  78,
-        82, 83, 87, 88, 92, 93, 97, 98, 102, 103, 107, 108, 112, 113, 117, 118};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 2}, answer_data);
-    }
-    {
-      float answer_data[] = {4,  9,  14, 19, 24,  29,  34,  39,
-                             44, 49, 54, 59, 64,  69,  74,  79,
-                             84, 89, 94, 99, 104, 109, 114, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-    }
-    EXPECT_EQ(t.split({2, 2, 1}, 3), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-    nntrainer::Tensor t = ranged(3, 2, 4, 5);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(2);
-    {
-      float answer_data[] = {
-        0,  1,  5,  6,  10, 11, 15, 16, 20,  21,  25,  26,  30,  31,  35,  36,
-        40, 41, 45, 46, 50, 51, 55, 56, 60,  61,  65,  66,  70,  71,  75,  76,
-        80, 81, 85, 86, 90, 91, 95, 96, 100, 101, 105, 106, 110, 111, 115, 116};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 2}, answer_data);
-    }
-    {
-      float answer_data[] = {
-        2,   3,   4,   7,   8,   9,   12,  13,  14,  17,  18,  19, 22, 23, 24,
-        27,  28,  29,  32,  33,  34,  37,  38,  39,  42,  43,  44, 47, 48, 49,
-        52,  53,  54,  57,  58,  59,  62,  63,  64,  67,  68,  69, 72, 73, 74,
-        77,  78,  79,  82,  83,  84,  87,  88,  89,  92,  93,  94, 97, 98, 99,
-        102, 103, 104, 107, 108, 109, 112, 113, 114, 117, 118, 119};
-      answer.emplace_back(ml::train::TensorDim{3, 2, 4, 3}, answer_data);
-    }
-    EXPECT_EQ(t.split({2, 3}, 3), answer);
-  }
-  {
-    nntrainer::TensorDim ref_dim(1, 1, 4, 6);
-    nntrainer::Tensor t = ranged(1, 1, 4, 6);
-    std::vector<nntrainer::Tensor> answer;
-    answer.reserve(3);
-    {
-      float answer_data[] = {0, 6, 12, 18};
-      answer.emplace_back(ml::train::TensorDim{1, 1, 4, 1}, answer_data);
-    }
-    {
-      float answer_data[] = {1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21};
-      answer.emplace_back(ml::train::TensorDim{1, 1, 4, 3}, answer_data);
-    }
-    {
-      float answer_data[] = {4, 5, 10, 11, 16, 17, 22, 23};
-      answer.emplace_back(ml::train::TensorDim{1, 1, 4, 2}, answer_data);
-    }
-    EXPECT_EQ(t.split({1, 3, 2}, 3), answer);
-  }
-}
-
-TEST(nntrainer_Tensor, split_05_n) {
-  nntrainer::Tensor t(3, 1, 1, 1);
-  EXPECT_THROW(t.split({1, 1}, 0), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, split_06_n) {
-  nntrainer::Tensor t(3, 1, 1, 1);
-  EXPECT_THROW(t.split({2, 0, 1}, 0), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, split_07_n) {
-  nntrainer::Tensor t(3, 1, 1, 1);
-  EXPECT_THROW(t.split({}, 0), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, cat_01_p) {
-  {
-    std::vector<nntrainer::Tensor> inputs;
-    inputs.reserve(2);
-    inputs.emplace_back(ranged(2, 1, 1, 2));
-    inputs.emplace_back(ranged(2, 2, 1, 2));
-    float answer_data[] = {0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 6, 7};
-    nntrainer::Tensor answer(ml::train::TensorDim{2, 3, 1, 2}, answer_data);
-    EXPECT_EQ(nntrainer::Tensor::cat(inputs, 1), answer);
-  }
-  {
-    std::vector<nntrainer::Tensor> inputs;
-    inputs.reserve(2);
-    inputs.emplace_back(ranged(3, 2, 4, 5));
-    inputs.emplace_back(ranged(2, 2, 4, 5));
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
-      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-      30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
-      45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-      60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
-      75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-      90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
-      105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
-      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
-      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-      30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
-      45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-      60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
-      75,  76,  77,  78,  79};
-    nntrainer::Tensor answer(ml::train::TensorDim{5, 2, 4, 5}, answer_data);
-    EXPECT_EQ(nntrainer::Tensor::cat(inputs, 0), answer);
-  }
-  {
-    std::vector<nntrainer::Tensor> inputs;
-    inputs.reserve(2);
-    inputs.emplace_back(ranged(3, 3, 4, 5));
-    inputs.emplace_back(ranged(3, 2, 4, 5));
-    float answer_data[] = {
-      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-      14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-      28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-      42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-      56,  57,  58,  59,  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
-      10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,
-      24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,
-      38,  39,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,
-      72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
-      86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-      100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
-      114, 115, 116, 117, 118, 119, 40,  41,  42,  43,  44,  45,  46,  47,
-      48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,
-      62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
-      76,  77,  78,  79,  120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
-      130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
-      144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
-      158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
-      172, 173, 174, 175, 176, 177, 178, 179, 80,  81,  82,  83,  84,  85,
-      86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-      100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
-      114, 115, 116, 117, 118, 119};
-    nntrainer::Tensor answer(ml::train::TensorDim{3, 5, 4, 5}, answer_data);
-    EXPECT_EQ(nntrainer::Tensor::cat(inputs, 1), answer);
-  }
-  {
-    std::vector<nntrainer::Tensor> inputs;
-    inputs.reserve(2);
-    inputs.emplace_back(ranged(3, 2, 1, 5));
-    inputs.emplace_back(ranged(3, 2, 2, 5));
-    float answer_data[] = {
-      0,  1,  2,  3,  4,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  5,  6,  7,
-      8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 11, 12, 13, 14, 20,
-      21, 22, 23, 24, 25, 26, 27, 28, 29, 15, 16, 17, 18, 19, 30, 31, 32, 33,
-      34, 35, 36, 37, 38, 39, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44, 45, 46,
-      47, 48, 49, 25, 26, 27, 28, 29, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
-    nntrainer::Tensor answer(ml::train::TensorDim{3, 2, 3, 5}, answer_data);
-    EXPECT_EQ(nntrainer::Tensor::cat(inputs, 2), answer);
-  }
-  {
-    std::vector<nntrainer::Tensor> inputs;
-    inputs.reserve(3);
-    inputs.emplace_back(ranged(3, 2, 4, 1));
-    inputs.emplace_back(ranged(3, 2, 4, 3));
-    inputs.emplace_back(ranged(3, 2, 4, 2));
-    float answer_data[] = {
-      0,  0,  1,  2,  0,  1,  1,  3,  4,  5,  2,  3,  2,  6,  7,  8,  4,  5,
-      3,  9,  10, 11, 6,  7,  4,  12, 13, 14, 8,  9,  5,  15, 16, 17, 10, 11,
-      6,  18, 19, 20, 12, 13, 7,  21, 22, 23, 14, 15, 8,  24, 25, 26, 16, 17,
-      9,  27, 28, 29, 18, 19, 10, 30, 31, 32, 20, 21, 11, 33, 34, 35, 22, 23,
-      12, 36, 37, 38, 24, 25, 13, 39, 40, 41, 26, 27, 14, 42, 43, 44, 28, 29,
-      15, 45, 46, 47, 30, 31, 16, 48, 49, 50, 32, 33, 17, 51, 52, 53, 34, 35,
-      18, 54, 55, 56, 36, 37, 19, 57, 58, 59, 38, 39, 20, 60, 61, 62, 40, 41,
-      21, 63, 64, 65, 42, 43, 22, 66, 67, 68, 44, 45, 23, 69, 70, 71, 46, 47};
-    nntrainer::Tensor answer(ml::train::TensorDim{3, 2, 4, 6}, answer_data);
-    EXPECT_EQ(nntrainer::Tensor::cat(inputs, 3), answer);
-  }
-}
-
-TEST(nntrainer_Tensor, cat_02_n) {
-  {
-    std::vector<nntrainer::Tensor> inputs;
-    inputs.reserve(2);
-    inputs.emplace_back(nntrainer::Tensor(2, 1, 1, 2));
-    inputs.emplace_back(nntrainer::Tensor(2, 2, 1, 2));
-    EXPECT_THROW(nntrainer::Tensor::cat(inputs, 2), std::invalid_argument);
-  }
-}
-
-TEST(nntrainer_Tensor, zoneout_mask_01_n) {
-  const float zoneout_rate = 0.3f;
-  nntrainer::Tensor t(10, 10, 10, 10);
-  nntrainer::Tensor opposite(20, 20, 20, 20);
-  EXPECT_THROW(t.zoneout_mask(opposite, zoneout_rate), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, zoneout_mask_02_p) {
-  const float zoneout_rate = 0.3f;
-  nntrainer::Tensor t(10, 10, 10, 10);
-  nntrainer::Tensor opposite = t.zoneout_mask(zoneout_rate);
-  constexpr float epsilon = 1e-3;
-
-  EXPECT_EQ(t.size(), opposite.size());
-
-  auto is_near = [epsilon](float val1, float val2) {
-    return val2 - epsilon < val1 && val1 < val2 + epsilon;
-  };
-
-  for (unsigned int i = 0; i < opposite.size(); ++i) {
-    if (is_near(opposite.getValue(i), 0.0f)) {
-      EXPECT_NEAR(t.getValue(i), 1.0f, epsilon);
-    } else if (is_near(opposite.getValue(i), 1.0f)) {
-      EXPECT_NEAR(t.getValue(i), 0.0f, epsilon);
-    } else {
-      FAIL() << "This should not be happen";
-    }
-  }
-}
-
-TEST(nntrainer_Tensor, zoneout_mask_03_p) {
-  const float zoneout_rate = 0.3f;
-  nntrainer::Tensor t(10, 10, 100, 100);
-  nntrainer::Tensor opposite = t.zoneout_mask(zoneout_rate);
-  constexpr float epsilon = 1e-3;
-
-  auto is_near = [epsilon](float val1, float val2) {
-    return val2 - epsilon < val1 && val1 < val2 + epsilon;
-  };
-  auto percentage = [](unsigned int dividend, unsigned int divisor) {
-    return (float)dividend / (float)divisor;
-  };
-
-  {
-    unsigned int zeros = 0;
-    unsigned int ones = 0;
-    for (unsigned int i = 0; i < opposite.size(); ++i) {
-      if (is_near(opposite.getValue(i), 0.0f)) {
-        ++zeros;
-      } else if (is_near(opposite.getValue(i), 1.0f)) {
-        ++ones;
-      } else {
-        FAIL() << "This should not be happen";
-      }
-    }
-    EXPECT_NEAR(percentage(zeros, opposite.size()), 1.0f - zoneout_rate,
-                epsilon);
-
-    // main test
-    EXPECT_NEAR(percentage(ones, opposite.size()), zoneout_rate, epsilon);
-  }
-
-  {
-    unsigned int zeros = 0;
-    unsigned int ones = 0;
-    for (unsigned int i = 0; i < t.size(); ++i) {
-      if (is_near(t.getValue(i), 0.0f)) {
-        ++zeros;
-      } else if (is_near(t.getValue(i), 1.0f)) {
-        ++ones;
-      } else {
-        FAIL() << "This should not be happen";
-      }
-    }
-    EXPECT_NEAR(percentage(zeros, t.size()), zoneout_rate, epsilon);
-
-    // main test
-    EXPECT_NEAR(percentage(ones, t.size()), 1.0f - zoneout_rate, epsilon);
-  }
-}
-
-TEST(nntrainer_Tensor, zoneout_mask_04_n) {
-  const float zoneout_rate = 0.3f;
-  nntrainer::Tensor t(10, 10, 100, 100);
-  nntrainer::Tensor opposite = t.zoneout_mask(zoneout_rate);
-  constexpr float epsilon = 1e-3;
-
-  auto is_near = [epsilon](float val1, float val2) {
-    return val2 - epsilon < val1 && val1 < val2 + epsilon;
-  };
-  auto percentage = [](unsigned int dividend, unsigned int divisor) {
-    return (float)dividend / (float)divisor;
-  };
-
-  {
-    unsigned int zeros = 0;
-    unsigned int ones = 0;
-    for (unsigned int i = 0; i < opposite.size(); ++i) {
-      if (is_near(opposite.getValue(i), 0.0f)) {
-        ++zeros;
-      } else if (is_near(opposite.getValue(i), 1.0f)) {
-        ++ones;
-      } else {
-        FAIL() << "This should not be happen";
-      }
-    }
-    EXPECT_FALSE(
-      is_near(percentage(ones, opposite.size()), 1.0f - zoneout_rate));
-  }
-
-  {
-    unsigned int zeros = 0;
-    unsigned int ones = 0;
-    for (unsigned int i = 0; i < t.size(); ++i) {
-      if (is_near(t.getValue(i), 0.0f)) {
-        ++zeros;
-      } else if (is_near(t.getValue(i), 1.0f)) {
-        ++ones;
-      } else {
-        FAIL() << "This should not be happen";
-      }
-    }
-    EXPECT_FALSE(is_near(percentage(ones, t.size()), zoneout_rate));
-  }
-}
-
-TEST(nntrainer_Tensor, TensorMap_p) {
-  float dat[] = {1, 2, 3};
-
-  {
-    nntrainer::Tensor a = nntrainer::Tensor::Map(dat, 3 * sizeof(float), {3});
-    /// check if a.getData() has same address with dat
-    EXPECT_EQ(dat, a.getData());
-    {
-      /// check if b.getData() has same address with data
-      nntrainer::Tensor b = a;
-      EXPECT_EQ(dat, b.getData());
-    }
-  }
-  /// check if dat is accessible after destruction of all the tensor
-  EXPECT_FLOAT_EQ(dat[2], 3);
-}
-
-TEST(nntrainer_Tensor, TensorWrap_01_n) {
-  float dat[] = {1, 2, 3};
-  EXPECT_THROW(nntrainer::Tensor::Map(dat, 3, nntrainer::TensorDim({})),
-               std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, TensorWrap_02_n) {
-  float dat[] = {1, 2, 3};
-  EXPECT_THROW(nntrainer::Tensor::Map(dat, 3, {4}), std::invalid_argument);
-}
-
-TEST(nntrainer_Tensor, TensorPaddedValue_p) {
-  nntrainer::Tensor a = ranged(1, 1, 3, 3);
-  float default_padded = -1;
-
-  for (int i = 0; i < 5; ++i) {
-    for (int j = 0; j < 5; ++j) {
-      float expected = default_padded;
-      if (1 <= i && i <= 3 && 1 <= j && j <= 3) {
-        expected = (i - 1) * 3 + (j - 1);
-      }
-      float actual = a.getValuePaddedVirtual<float>(0, 0, i, j, 1, 1, default_padded);
-      EXPECT_FLOAT_EQ(actual, expected);
-    }
-  }
-}
-
-GTEST_API_ int main(int argc, char **argv) {
-  int result = -1;
-
-  try {
-    testing::InitGoogleTest(&argc, argv);
-  } catch (...) {
-    std::cerr << "Error duing InitGoogleTest" << std::endl;
-    return 0;
-  }
-
-  try {
-    result = RUN_ALL_TESTS();
-  } catch (...) {
-    std::cerr << "Error duing RUN_ALL_TESTS()" << std::endl;
-  }
-
-  return result;
-}
diff --git a/test/unittest/jni/tests/unittest_nntrainer_tensor_fp16.cpp b/test/unittest/jni/tests/unittest_nntrainer_tensor_fp16.cpp
deleted file mode 100644 (file)
index 20e4723..0000000
+++ /dev/null
@@ -1,3893 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-/**
- * Copyright (C) 2020 Jijoong Moon <jijoong.moon@samsung.com>
- *
- * @file        unittest_nntrainer_tensor.cpp
- * @date        03 June 2020
- * @brief       Unit test utility for tensor.
- * @see         https://github.com/nnstreamer/nntrainer
- * @author      Jijoong Moon <jijoong.moon@samsung.com>
- * @bug         No known bugs
- */
-#include <gtest/gtest.h>
-
-#include "nntrainer_test_util.h"
-#include "util_func.h"
-#include <fstream>
-#include <nntrainer_error.h>
-#include <tensor.h>
-#include <tensor_dim.h>
-#include <iostream>
-
-TEST(nntrainer_Tensor, Tensor_01_fp16_p) {
-  int status = ML_ERROR_NONE;
-  nntrainer::Tensor tensor = nntrainer::Tensor(
-    1, 2, 3, nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-  tensor.setZero();
-  ASSERT_NE(nullptr, tensor.getData<__fp16>());
-  if (tensor.getValue(0, 0, 0, 0) != 0.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, Tensor_01_nhwc_fp16_p) {
-  int status = ML_ERROR_NONE;
-  nntrainer::Tensor tensor = nntrainer::Tensor(
-    1, 2, 3, nntrainer::Tformat::NHWC, nntrainer::DataType::FP16);
-  tensor.setZero();
-  ASSERT_NE(nullptr, tensor.getData<__fp16>());
-  if (tensor.getValue<__fp16>(0, 0, 0, 0) != 0.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, Tensor_02_fp16_p) {
-  int status = ML_ERROR_NONE;
-  int height = 3;
-  int width = 10;
-  std::vector<std::vector<__fp16>> in;
-  for (int i = 0; i < height; ++i) {
-    std::vector<__fp16> tv;
-    for (int j = 0; j < width; ++j) {
-      tv.push_back(i * 2.0 + j);
-    }
-    in.push_back(tv);
-  }
-
-  nntrainer::Tensor tensor = nntrainer::Tensor(in);
-  ASSERT_NE(nullptr, tensor.getData<__fp16>());
-
-  if (tensor.getValue<__fp16>(0, 0, 0, 1) != 1.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, Tensor_03_fp16_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int height = 3;
-  int width = 10;
-  std::vector<std::vector<std::vector<__fp16>>> in;
-  for (int k = 0; k < batch; ++k) {
-    std::vector<std::vector<__fp16>> ttv;
-    for (int i = 0; i < height; ++i) {
-      std::vector<__fp16> tv;
-      for (int j = 0; j < width; ++j) {
-        tv.push_back(k * height * width + i * width + j);
-      }
-      ttv.push_back(tv);
-    }
-    in.push_back(ttv);
-  }
-
-  nntrainer::Tensor tensor = nntrainer::Tensor(in);
-  ASSERT_NE(nullptr, tensor.getData<__fp16>());
-
-  if (tensor.getValue<__fp16>(0, 0, 0, 1) != 1.0)
-    status = ML_ERROR_INVALID_PARAMETER;
-  EXPECT_EQ(status, ML_ERROR_NONE);
-}
-
-TEST(nntrainer_Tensor, multiply_i_01_fp16_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width,
-                          nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor original;
-  original.copy(input);
-
-  status = input.multiply_i(2.0);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  __fp16 *data = original.getData<__fp16>();
-  ASSERT_NE(nullptr, data);
-  __fp16 *indata = input.getData<__fp16>();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width * channel; ++i) {
-    EXPECT_FLOAT_EQ(data[i] + data[i], indata[i]);
-  }
-}
-
-TEST(nntrainer_Tensor, multiply_i_02_fp16_p) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width,
-                          nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor original;
-  original.copy(input);
-
-  status = input.multiply_i(input);
-  EXPECT_EQ(status, ML_ERROR_NONE);
-
-  __fp16 *data = original.getData<__fp16>();
-  ASSERT_NE(nullptr, data);
-  __fp16 *indata = input.getData<__fp16>();
-  ASSERT_NE(nullptr, indata);
-
-  for (int i = 0; i < batch * height * width * channel; ++i) {
-    EXPECT_FLOAT_EQ(data[i] * data[i], indata[i]);
-  }
-}
-
-TEST(nntrainer_Tensor, multiply_i_03_fp16_n) {
-  int status = ML_ERROR_NONE;
-  int batch = 3;
-  int channel = 1;
-  int height = 3;
-  int width = 10;
-
-  nntrainer::Tensor input(batch, channel, height, width,
-                          nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-  GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-  nntrainer::Tensor target2(batch, channel, height - 2, width - 1,
-                            nntrainer::Tformat::NCHW,
-                            nntrainer::DataType::FP16);
-  status = input.multiply_i(target2);
-
-  EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-}
-
-// TEST(nntrainer_Tensor, multiply_i_broadcast_01_fp16_p) {
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t =
-//       ranged(3, 2, 4, 5, nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-//     nntrainer::Tensor m =
-//       ranged(1, 2, 4, 5, nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-//     __fp16 answer_data[] = {
-//       0,    1,    4,    9,    16,   25,   36,   49,   64,   81,   100,  121,
-//       144,  169,  196,  225,  256,  289,  324,  361,  400,  441,  484,  529,
-//       576,  625,  676,  729,  784,  841,  900,  961,  1024, 1089, 1156, 1225,
-//       1296, 1369, 1444, 1521, 0,    41,   84,   129,  176,  225,  276,  329,
-//       384,  441,  500,  561,  624,  689,  756,  825,  896,  969,  1044, 1121,
-//       1200, 1281, 1364, 1449, 1536, 1625, 1716, 1809, 1904, 2001, 2100, 2201,
-//       2304, 2409, 2516, 2625, 2736, 2849, 2964, 3081, 0,    81,   164,  249,
-//       336,  425,  516,  609,  704,  801,  900,  1001, 1104, 1209, 1316, 1425,
-//       1536, 1649, 1764, 1881, 2000, 2121, 2244, 2369, 2496, 2625, 2756, 2889,
-//       3024, 3161, 3300, 3441, 3584, 3729, 3876, 4025, 4176, 4329, 4484, 4641};
-//     nntrainer::Tensor answer(ref_dim, answer_data, nntrainer::DataType::FP16);
-//     int status = t.multiply_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5, nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-//     nntrainer::Tensor m = ranged(3, 1, 4, 5, nntrainer::Tformat::NCHW, nntrainer::DataType::FP16);
-//     __fp16 answer_data[] = {
-//       0,    1,    4,    9,    16,   25,   36,   49,   64,   81,   100,  121,
-//       144,  169,  196,  225,  256,  289,  324,  361,  0,    21,   44,   69,
-//       96,   125,  156,  189,  224,  261,  300,  341,  384,  429,  476,  525,
-//       576,  629,  684,  741,  800,  861,  924,  989,  1056, 1125, 1196, 1269,
-//       1344, 1421, 1500, 1581, 1664, 1749, 1836, 1925, 2016, 2109, 2204, 2301,
-//       1200, 1281, 1364, 1449, 1536, 1625, 1716, 1809, 1904, 2001, 2100, 2201,
-//       2304, 2409, 2516, 2625, 2736, 2849, 2964, 3081, 3200, 3321, 3444, 3569,
-//       3696, 3825, 3956, 4089, 4224, 4361, 4500, 4641, 4784, 4929, 5076, 5225,
-//       5376, 5529, 5684, 5841, 4000, 4141, 4284, 4429, 4576, 4725, 4876, 5029,
-//       5184, 5341, 5500, 5661, 5824, 5989, 6156, 6325, 6496, 6669, 6844, 7021};
-//     nntrainer::Tensor answer(ref_dim, answer_data, nntrainer::DataType::FP16);
-//     int status = t.multiply_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-  //   nntrainer::Tensor t = ranged(3, 2, 4, 5);
-  //   nntrainer::Tensor m = ranged(3, 2, 4, 1);
-  //   __fp16 answer_data[] = {
-  //     0,    0,    0,    0,    0,    5,    6,    7,    8,    9,    20,   22,
-  //     24,   26,   28,   45,   48,   51,   54,   57,   80,   84,   88,   92,
-  //     96,   125,  130,  135,  140,  145,  180,  186,  192,  198,  204,  245,
-  //     252,  259,  266,  273,  320,  328,  336,  344,  352,  405,  414,  423,
-  //     432,  441,  500,  510,  520,  530,  540,  605,  616,  627,  638,  649,
-  //     720,  732,  744,  756,  768,  845,  858,  871,  884,  897,  980,  994,
-  //     1008, 1022, 1036, 1125, 1140, 1155, 1170, 1185, 1280, 1296, 1312, 1328,
-  //     1344, 1445, 1462, 1479, 1496, 1513, 1620, 1638, 1656, 1674, 1692, 1805,
-  //     1824, 1843, 1862, 1881, 2000, 2020, 2040, 2060, 2080, 2205, 2226, 2247,
-  //     2268, 2289, 2420, 2442, 2464, 2486, 2508, 2645, 2668, 2691, 2714, 2737};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-  //   nntrainer::Tensor t = ranged(3, 2, 4, 5);
-  //   nntrainer::Tensor m = ranged(3, 1, 1, 5);
-  //   __fp16 answer_data[] = {
-  //     0,    1,    4,    9,    16,   0,    6,    14,   24,   36,   0,    11,
-  //     24,   39,   56,   0,    16,   34,   54,   76,   0,    21,   44,   69,
-  //     96,   0,    26,   54,   84,   116,  0,    31,   64,   99,   136,  0,
-  //     36,   74,   114,  156,  200,  246,  294,  344,  396,  225,  276,  329,
-  //     384,  441,  250,  306,  364,  424,  486,  275,  336,  399,  464,  531,
-  //     300,  366,  434,  504,  576,  325,  396,  469,  544,  621,  350,  426,
-  //     504,  584,  666,  375,  456,  539,  624,  711,  800,  891,  984,  1079,
-  //     1176, 850,  946,  1044, 1144, 1246, 900,  1001, 1104, 1209, 1316, 950,
-  //     1056, 1164, 1274, 1386, 1000, 1111, 1224, 1339, 1456, 1050, 1166, 1284,
-  //     1404, 1526, 1100, 1221, 1344, 1469, 1596, 1150, 1276, 1404, 1534, 1666};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-  //   nntrainer::Tensor t = ranged(3, 2, 4, 5);
-  //   nntrainer::Tensor m = ranged(1, 2, 1, 5);
-  //   __fp16 answer_data[] = {
-  //     0,   1,   4,    9,   16,  0,   6,   14,  24,  36,  0,   11,  24,  39,
-  //     56,  0,   16,   34,  54,  76,  100, 126, 154, 184, 216, 125, 156, 189,
-  //     224, 261, 150,  186, 224, 264, 306, 175, 216, 259, 304, 351, 0,   41,
-  //     84,  129, 176,  0,   46,  94,  144, 196, 0,   51,  104, 159, 216, 0,
-  //     56,  114, 174,  236, 300, 366, 434, 504, 576, 325, 396, 469, 544, 621,
-  //     350, 426, 504,  584, 666, 375, 456, 539, 624, 711, 0,   81,  164, 249,
-  //     336, 0,   86,   174, 264, 356, 0,   91,  184, 279, 376, 0,   96,  194,
-  //     294, 396, 500,  606, 714, 824, 936, 525, 636, 749, 864, 981, 550, 666,
-  //     784, 904, 1026, 575, 696, 819, 944, 1071};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-  //   nntrainer::Tensor t = ranged(3, 2, 4, 5);
-  //   nntrainer::Tensor m = ranged(3, 1, 4, 1);
-  //   __fp16 answer_data[] = {
-  //     0,    0,    0,    0,    0,    5,    6,    7,    8,    9,    20,   22,
-  //     24,   26,   28,   45,   48,   51,   54,   57,   0,    0,    0,    0,
-  //     0,    25,   26,   27,   28,   29,   60,   62,   64,   66,   68,   105,
-  //     108,  111,  114,  117,  160,  164,  168,  172,  176,  225,  230,  235,
-  //     240,  245,  300,  306,  312,  318,  324,  385,  392,  399,  406,  413,
-  //     240,  244,  248,  252,  256,  325,  330,  335,  340,  345,  420,  426,
-  //     432,  438,  444,  525,  532,  539,  546,  553,  640,  648,  656,  664,
-  //     672,  765,  774,  783,  792,  801,  900,  910,  920,  930,  940,  1045,
-  //     1056, 1067, 1078, 1089, 800,  808,  816,  824,  832,  945,  954,  963,
-  //     972,  981,  1100, 1110, 1120, 1130, 1140, 1265, 1276, 1287, 1298, 1309};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-  //   nntrainer::Tensor t = ranged(3, 2, 4, 5);
-  //   nntrainer::Tensor m = ranged(1, 1, 1, 5);
-  //   __fp16 answer_data[] = {
-  //     0, 1,   4,   9,   16,  0, 6,   14,  24,  36,  0, 11,  24,  39,  56,
-  //     0, 16,  34,  54,  76,  0, 21,  44,  69,  96,  0, 26,  54,  84,  116,
-  //     0, 31,  64,  99,  136, 0, 36,  74,  114, 156, 0, 41,  84,  129, 176,
-  //     0, 46,  94,  144, 196, 0, 51,  104, 159, 216, 0, 56,  114, 174, 236,
-  //     0, 61,  124, 189, 256, 0, 66,  134, 204, 276, 0, 71,  144, 219, 296,
-  //     0, 76,  154, 234, 316, 0, 81,  164, 249, 336, 0, 86,  174, 264, 356,
-  //     0, 91,  184, 279, 376, 0, 96,  194, 294, 396, 0, 101, 204, 309, 416,
-  //     0, 106, 214, 324, 436, 0, 111, 224, 339, 456, 0, 116, 234, 354, 476};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-  //   nntrainer::Tensor t = ranged(3, 2, 4, 5);
-  //   nntrainer::Tensor m = ranged(1, 2, 1, 1);
-  //   __fp16 answer_data[] = {
-  //     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  //     0,   0,   0,   0,   0,   0,   20,  21,  22,  23,  24,  25,  26,  27,
-  //     28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  0,   0,
-  //     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  //     0,   0,   0,   0,   60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-  //     70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  0,   0,   0,   0,
-  //     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  //     0,   0,   100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-  //     112, 113, 114, 115, 116, 117, 118, 119};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-  //   nntrainer::Tensor t = ranged(3, 2, 4, 5);
-  //   nntrainer::Tensor m = ranged(3, 1, 1, 1);
-  //   __fp16 answer_data[] = {
-  //     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  //     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-  //     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   40,  41,
-  //     42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-  //     56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-  //     70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  160, 162, 164, 166,
-  //     168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194,
-  //     196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222,
-  //     224, 226, 228, 230, 232, 234, 236, 238};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-  // {
-  //   nntrainer::TensorDim ref_dim(3, 5, 1, 4);
-  //   nntrainer::Tensor t = ranged(3, 5, 1, 4);
-  //   nntrainer::Tensor m = ranged(3, 1, 1, 4);
-  //   __fp16 answer_data[] = {0,   1,   4,   9,   0,   5,   12,  21,  0,   9,
-  //                          20,  33,  0,   13,  28,  45,  0,   17,  36,  57,
-  //                          80,  105, 132, 161, 96,  125, 156, 189, 112, 145,
-  //                          180, 217, 128, 165, 204, 245, 144, 185, 228, 273,
-  //                          320, 369, 420, 473, 352, 405, 460, 517, 384, 441,
-  //                          500, 561, 416, 477, 540, 605, 448, 513, 580, 649};
-  //   nntrainer::Tensor answer(ref_dim, answer_data);
-  //   int status = t.multiply_i(m);
-  //   EXPECT_EQ(status, ML_ERROR_NONE);
-  //   EXPECT_EQ(t, answer);
-  // }
-// }
-
-// TEST(nntrainer_Tensor, multiply_i_broadcast_not_supported_01_n) {
-//   nntrainer::Tensor target(3, 1, 3, 1);
-//   nntrainer::Tensor target2(3, 1, 3, 3);
-
-//   EXPECT_EQ(target.multiply_i(target2), ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, multiply_i_broadcast_not_broadcastable_02_n) {
-//   nntrainer::Tensor target(3, 2, 4, 5);
-//   nntrainer::Tensor target2(3, 2, 3, 1);
-
-//   EXPECT_EQ(target.multiply_i(target2), ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, multiply_01_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-//   nntrainer::Tensor result = input.multiply(0.0);
-//   if (result.getValue(0, 0, 1, 1) != 0.0)
-//     status = ML_ERROR_RESULT_OUT_OF_RANGE;
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, multiply_02_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor result = input.multiply(input);
-
-//   __fp16 *data = result.getData();
-//   ASSERT_NE(nullptr, data);
-//   __fp16 *indata = input.getData();
-//   ASSERT_NE(nullptr, indata);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     if (data[i] != indata[i] * indata[i]) {
-//       status = ML_ERROR_RESULT_OUT_OF_RANGE;
-//       break;
-//     }
-//   }
-
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, multiply_03_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor test(batch - 1, height - 1, width - 1);
-
-//   EXPECT_THROW({ input.multiply(test); }, std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, multiply_04_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-//   nntrainer::Tensor test(dim);
-
-//   EXPECT_THROW(shared_input.multiply(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, multiply_05_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   nntrainer::Tensor test(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-//   EXPECT_THROW(input.multiply(shared_test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, multiply_06_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim, false);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-//   EXPECT_THROW(input.multiply(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, multiply_07_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim, false);
-
-//   EXPECT_THROW(input.multiply(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, multiply_08_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-//   nntrainer::Tensor output(dim, false);
-
-//   EXPECT_THROW(input.multiply(test, output), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, multiply___fp16_01_p) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor expected(batch, channel, height, width);
-//   GEN_TEST_INPUT(expected, (i * (batch * height) + j * (width) + k + 1) * 2);
-
-//   nntrainer::Tensor result = input.multiply(2.0);
-
-//   EXPECT_EQ(result, expected);
-// }
-
-// TEST(nntrainer_Tensor, divide_i_01_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-//   nntrainer::Tensor original;
-//   original.copy(input);
-
-//   status = input.divide_i((__fp16)2.0);
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-
-//   __fp16 *data = original.getData();
-//   ASSERT_NE(nullptr, data);
-//   __fp16 *indata = input.getData();
-//   ASSERT_NE(nullptr, indata);
-
-//   for (int i = 0; i < batch * height * width * channel; ++i) {
-//     EXPECT_FLOAT_EQ(data[i], indata[i] + indata[i]);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, divide_i_02_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   status = input.divide_i(input);
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-//   __fp16 *indata = input.getData();
-//   ASSERT_NE(nullptr, indata);
-
-//   for (int i = 0; i < batch * height * width * channel; ++i) {
-//     EXPECT_FLOAT_EQ(indata[i], __fp16(1.0));
-//   }
-// }
-
-// TEST(nntrainer_Tensor, divide_i_01_n) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-//   status = input.divide_i((__fp16)0);
-//   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, divide_i_02_n) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-//   nntrainer::Tensor original(batch, channel, height - 2, width - 1);
-
-//   status = input.divide_i(original);
-//   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, divide_01_p) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor result = input.divide(1.0);
-
-//   __fp16 *previous = input.getData();
-//   ASSERT_NE(nullptr, previous);
-//   __fp16 *data = result.getData();
-//   ASSERT_NE(nullptr, data);
-
-//   for (int i = 0; i < batch * height * width * channel; ++i) {
-//     EXPECT_FLOAT_EQ(data[i], previous[i]);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, divide_02_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   EXPECT_THROW({ input.divide(0.0); }, std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, divide_03_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor test(batch - 1, channel, height - 1, width - 1);
-
-//   EXPECT_THROW({ input.divide(test); }, std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, divide_04_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-//   nntrainer::Tensor test(dim);
-
-//   EXPECT_THROW(shared_input.divide(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, divide_05_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   nntrainer::Tensor test(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-//   EXPECT_THROW(input.divide(shared_test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, divide_06_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim, false);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-//   EXPECT_THROW(input.divide(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, divide_07_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim, false);
-
-//   EXPECT_THROW(input.divide(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, divide_08_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-//   nntrainer::Tensor output(dim, false);
-
-//   EXPECT_THROW(input.divide(test, output), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, divide_i_broadcast_01_p) {
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(1, 2, 4, 5);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       41.0,      21.0,
-//       14.333333, 11.0,      9.0,       7.6666665, 6.714286,  6.0,
-//       5.4444447, 5.0,       4.6363635, 4.3333335, 4.076923,  3.857143,
-//       3.6666667, 3.5,       3.3529413, 3.2222223, 3.1052632, 3.0,
-//       2.9047618, 2.8181818, 2.7391305, 2.6666667, 2.6,       2.5384614,
-//       2.4814816, 2.4285715, 2.3793104, 2.3333333, 2.2903225, 2.25,
-//       2.2121212, 2.1764705, 2.142857,  2.1111112, 2.0810812, 2.0526316,
-//       2.025641,  2.0,       81.0,      41.0,      27.666666, 21.0,
-//       17.0,      14.333333, 12.428572, 11.0,      9.888889,  9.0,
-//       8.272727,  7.6666665, 7.1538463, 6.714286,  6.3333335, 6.0,
-//       5.7058825, 5.4444447, 5.2105265, 5.0,       4.8095236, 4.6363635,
-//       4.478261,  4.3333335, 4.2,       4.076923,  3.9629629, 3.857143,
-//       3.7586207, 3.6666667, 3.580645,  3.5,       3.4242425, 3.3529413,
-//       3.2857144, 3.2222223, 3.162162,  3.1052632, 3.0512822, 3.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(3, 1, 4, 5);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       1.0,       1.0,       1.0,       1.0,
-//       1.0,       1.0,       21.0,      11.0,      7.6666665, 6.0,
-//       5.0,       4.3333335, 3.857143,  3.5,       3.2222223, 3.0,
-//       2.8181818, 2.6666667, 2.5384614, 2.4285715, 2.3333333, 2.25,
-//       2.1764705, 2.1111112, 2.0526316, 2.0,       1.9523809, 1.9090909,
-//       1.8695652, 1.8333334, 1.8,       1.7692307, 1.7407408, 1.7142857,
-//       1.6896552, 1.6666666, 1.6451613, 1.625,     1.6060606, 1.5882353,
-//       1.5714285, 1.5555556, 1.5405406, 1.5263158, 1.5128205, 1.5,
-//       2.9047618, 2.8181818, 2.7391305, 2.6666667, 2.6,       2.5384614,
-//       2.4814816, 2.4285715, 2.3793104, 2.3333333, 2.2903225, 2.25,
-//       2.2121212, 2.1764705, 2.142857,  2.1111112, 2.0810812, 2.0526316,
-//       2.025641,  2.0,       1.9756098, 1.9523809, 1.9302325, 1.9090909,
-//       1.8888888, 1.8695652, 1.8510638, 1.8333334, 1.8163265, 1.8,
-//       1.7843137, 1.7692307, 1.754717,  1.7407408, 1.7272727, 1.7142857,
-//       1.7017543, 1.6896552, 1.6779661, 1.6666666, 2.4634147, 2.4285715,
-//       2.3953488, 2.3636363, 2.3333333, 2.3043478, 2.2765958, 2.25,
-//       2.2244897, 2.2,       2.1764705, 2.1538463, 2.1320755, 2.1111112,
-//       2.090909,  2.0714285, 2.0526316, 2.0344827, 2.0169492, 2.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(3, 2, 4, 1);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       2.0,       3.0,       4.0,       5.0,       3.0,
-//       3.5,       4.0,       4.5,       5.0,       3.6666667, 4.0,
-//       4.3333335, 4.6666665, 5.0,       4.0,       4.25,      4.5,
-//       4.75,      5.0,       4.2,       4.4,       4.6,       4.8,
-//       5.0,       4.3333335, 4.5,       4.6666665, 4.8333335, 5.0,
-//       4.428571,  4.571429,  4.714286,  4.857143,  5.0,       4.5,
-//       4.625,     4.75,      4.875,     5.0,       4.5555553, 4.6666665,
-//       4.7777777, 4.888889,  5.0,       4.6,       4.7,       4.8,
-//       4.9,       5.0,       4.6363635, 4.7272725, 4.818182,  4.909091,
-//       5.0,       4.6666665, 4.75,      4.8333335, 4.9166665, 5.0,
-//       4.6923075, 4.769231,  4.8461537, 4.923077,  5.0,       4.714286,
-//       4.785714,  4.857143,  4.928571,  5.0,       4.733333,  4.8,
-//       4.866667,  4.9333334, 5.0,       4.75,      4.8125,    4.875,
-//       4.9375,    5.0,       4.7647057, 4.8235292, 4.882353,  4.9411764,
-//       5.0,       4.7777777, 4.8333335, 4.888889,  4.9444447, 5.0,
-//       4.7894735, 4.8421054, 4.894737,  4.9473686, 5.0,       4.8,
-//       4.85,      4.9,       4.95,      5.0,       4.8095236, 4.857143,
-//       4.904762,  4.952381,  5.0,       4.818182,  4.8636365, 4.909091,
-//       4.9545455, 5.0,       4.826087,  4.869565,  4.9130435, 4.9565215,
-//       5.0,       4.8333335, 4.875,     4.9166665, 4.9583335, 5.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(3, 1, 1, 5);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       1.0,       1.0,       1.0,       1.0,       6.0,
-//       3.5,       2.6666667, 2.25,      2.0,       11.0,      6.0,
-//       4.3333335, 3.5,       3.0,       16.0,      8.5,       6.0,
-//       4.75,      4.0,       21.0,      11.0,      7.6666665, 6.0,
-//       5.0,       26.0,      13.5,      9.333333,  7.25,      6.0,
-//       31.0,      16.0,      11.0,      8.5,       7.0,       36.0,
-//       18.5,      12.666667, 9.75,      8.0,       6.8333335, 6.0,
-//       5.375,     4.888889,  4.5,       7.6666665, 6.714286,  6.0,
-//       5.4444447, 5.0,       8.5,       7.428571,  6.625,     6.0,
-//       5.5,       9.333333,  8.142858,  7.25,      6.5555553, 6.0,
-//       10.166667, 8.857142,  7.875,     7.111111,  6.5,       11.0,
-//       9.571428,  8.5,       7.6666665, 7.0,       11.833333, 10.285714,
-//       9.125,     8.222222,  7.5,       12.666667, 11.0,      9.75,
-//       8.777778,  8.0,       7.3636365, 6.8333335, 6.3846154, 6.0,
-//       5.6666665, 7.818182,  7.25,      6.769231,  6.357143,  6.0,
-//       8.272727,  7.6666665, 7.1538463, 6.714286,  6.3333335, 8.727273,
-//       8.083333,  7.5384617, 7.071429,  6.6666665, 9.181818,  8.5,
-//       7.923077,  7.428571,  7.0,       9.636364,  8.916667,  8.307693,
-//       7.785714,  7.3333335, 10.090909, 9.333333,  8.692307,  8.142858,
-//       7.6666665, 10.545455, 9.75,      9.076923,  8.5,       8.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(1, 2, 1, 5);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       1.0,       1.0,       1.0,       1.0,       6.0,
-//       3.5,       2.6666667, 2.25,      2.0,       11.0,      6.0,
-//       4.3333335, 3.5,       3.0,       16.0,      8.5,       6.0,
-//       4.75,      4.0,       3.5,       3.142857,  2.875,     2.6666667,
-//       2.5,       4.3333335, 3.857143,  3.5,       3.2222223, 3.0,
-//       5.1666665, 4.571429,  4.125,     3.7777777, 3.5,       6.0,
-//       5.285714,  4.75,      4.3333335, 4.0,       41.0,      21.0,
-//       14.333333, 11.0,      9.0,       46.0,      23.5,      16.0,
-//       12.25,     10.0,      51.0,      26.0,      17.666666, 13.5,
-//       11.0,      56.0,      28.5,      19.333334, 14.75,     12.0,
-//       10.166667, 8.857142,  7.875,     7.111111,  6.5,       11.0,
-//       9.571428,  8.5,       7.6666665, 7.0,       11.833333, 10.285714,
-//       9.125,     8.222222,  7.5,       12.666667, 11.0,      9.75,
-//       8.777778,  8.0,       81.0,      41.0,      27.666666, 21.0,
-//       17.0,      86.0,      43.5,      29.333334, 22.25,     18.0,
-//       91.0,      46.0,      31.0,      23.5,      19.0,      96.0,
-//       48.5,      32.666668, 24.75,     20.0,      16.833334, 14.571428,
-//       12.875,    11.555555, 10.5,      17.666666, 15.285714, 13.5,
-//       12.111111, 11.0,      18.5,      16.0,      14.125,    12.666667,
-//       11.5,      19.333334, 16.714285, 14.75,     13.222222, 12.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(3, 1, 4, 1);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       2.0,       3.0,       4.0,       5.0,       3.0,
-//       3.5,       4.0,       4.5,       5.0,       3.6666667, 4.0,
-//       4.3333335, 4.6666665, 5.0,       4.0,       4.25,      4.5,
-//       4.75,      5.0,       21.0,      22.0,      23.0,      24.0,
-//       25.0,      13.0,      13.5,      14.0,      14.5,      15.0,
-//       10.333333, 10.666667, 11.0,      11.333333, 11.666667, 9.0,
-//       9.25,      9.5,       9.75,      10.0,      8.2,       8.4,
-//       8.6,       8.8,       9.0,       7.6666665, 7.8333335, 8.0,
-//       8.166667,  8.333333,  7.285714,  7.428571,  7.571429,  7.714286,
-//       7.857143,  7.0,       7.125,     7.25,      7.375,     7.5,
-//       12.2,      12.4,      12.6,      12.8,      13.0,      11.0,
-//       11.166667, 11.333333, 11.5,      11.666667, 10.142858, 10.285714,
-//       10.428572, 10.571428, 10.714286, 9.5,       9.625,     9.75,
-//       9.875,     10.0,      9.0,       9.111111,  9.222222,  9.333333,
-//       9.444445,  8.6,       8.7,       8.8,       8.9,       9.0,
-//       8.272727,  8.363636,  8.454545,  8.545455,  8.636364,  8.0,
-//       8.083333,  8.166667,  8.25,      8.333333,  11.222222, 11.333333,
-//       11.444445, 11.555555, 11.666667, 10.6,      10.7,      10.8,
-//       10.9,      11.0,      10.090909, 10.181818, 10.272727, 10.363636,
-//       10.454545, 9.666667,  9.75,      9.833333,  9.916667,  10.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(1, 1, 1, 5);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,   1.0,  1.0,       1.0,  1.0,  6.0,   3.5,  2.6666667, 2.25,  2.0,
-//       11.0,  6.0,  4.3333335, 3.5,  3.0,  16.0,  8.5,  6.0,       4.75,  4.0,
-//       21.0,  11.0, 7.6666665, 6.0,  5.0,  26.0,  13.5, 9.333333,  7.25,  6.0,
-//       31.0,  16.0, 11.0,      8.5,  7.0,  36.0,  18.5, 12.666667, 9.75,  8.0,
-//       41.0,  21.0, 14.333333, 11.0, 9.0,  46.0,  23.5, 16.0,      12.25, 10.0,
-//       51.0,  26.0, 17.666666, 13.5, 11.0, 56.0,  28.5, 19.333334, 14.75, 12.0,
-//       61.0,  31.0, 21.0,      16.0, 13.0, 66.0,  33.5, 22.666666, 17.25, 14.0,
-//       71.0,  36.0, 24.333334, 18.5, 15.0, 76.0,  38.5, 26.0,      19.75, 16.0,
-//       81.0,  41.0, 27.666666, 21.0, 17.0, 86.0,  43.5, 29.333334, 22.25, 18.0,
-//       91.0,  46.0, 31.0,      23.5, 19.0, 96.0,  48.5, 32.666668, 24.75, 20.0,
-//       101.0, 51.0, 34.333332, 26.0, 21.0, 106.0, 53.5, 36.0,      27.25, 22.0,
-//       111.0, 56.0, 37.666668, 28.5, 23.0, 116.0, 58.5, 39.333332, 29.75, 24.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(1, 2, 1, 1);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,  2.0,  3.0,  4.0,   5.0,  6.0,  7.0,  8.0,  9.0,  10.0, 11.0, 12.0,
-//       13.0, 14.0, 15.0, 16.0,  17.0, 18.0, 19.0, 20.0, 10.5, 11.0, 11.5, 12.0,
-//       12.5, 13.0, 13.5, 14.0,  14.5, 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0,
-//       18.5, 19.0, 19.5, 20.0,  41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0,
-//       49.0, 50.0, 51.0, 52.0,  53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0,
-//       30.5, 31.0, 31.5, 32.0,  32.5, 33.0, 33.5, 34.0, 34.5, 35.0, 35.5, 36.0,
-//       36.5, 37.0, 37.5, 38.0,  38.5, 39.0, 39.5, 40.0, 81.0, 82.0, 83.0, 84.0,
-//       85.0, 86.0, 87.0, 88.0,  89.0, 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0,
-//       97.0, 98.0, 99.0, 100.0, 50.5, 51.0, 51.5, 52.0, 52.5, 53.0, 53.5, 54.0,
-//       54.5, 55.0, 55.5, 56.0,  56.5, 57.0, 57.5, 58.0, 58.5, 59.0, 59.5, 60.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(3, 1, 1, 1);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       2.0,       3.0,  4.0,       5.0,       6.0,
-//       7.0,       8.0,       9.0,  10.0,      11.0,      12.0,
-//       13.0,      14.0,      15.0, 16.0,      17.0,      18.0,
-//       19.0,      20.0,      21.0, 22.0,      23.0,      24.0,
-//       25.0,      26.0,      27.0, 28.0,      29.0,      30.0,
-//       31.0,      32.0,      33.0, 34.0,      35.0,      36.0,
-//       37.0,      38.0,      39.0, 40.0,      20.5,      21.0,
-//       21.5,      22.0,      22.5, 23.0,      23.5,      24.0,
-//       24.5,      25.0,      25.5, 26.0,      26.5,      27.0,
-//       27.5,      28.0,      28.5, 29.0,      29.5,      30.0,
-//       30.5,      31.0,      31.5, 32.0,      32.5,      33.0,
-//       33.5,      34.0,      34.5, 35.0,      35.5,      36.0,
-//       36.5,      37.0,      37.5, 38.0,      38.5,      39.0,
-//       39.5,      40.0,      27.0, 27.333334, 27.666666, 28.0,
-//       28.333334, 28.666666, 29.0, 29.333334, 29.666666, 30.0,
-//       30.333334, 30.666666, 31.0, 31.333334, 31.666666, 32.0,
-//       32.333332, 32.666668, 33.0, 33.333332, 33.666668, 34.0,
-//       34.333332, 34.666668, 35.0, 35.333332, 35.666668, 36.0,
-//       36.333332, 36.666668, 37.0, 37.333332, 37.666668, 38.0,
-//       38.333332, 38.666668, 39.0, 39.333332, 39.666668, 40.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 5, 1, 4);
-//     nntrainer::Tensor t = ranged(3, 5, 1, 4);
-//     t.add_i(1);
-//     nntrainer::Tensor m = ranged(3, 1, 1, 4);
-//     m.add_i(1);
-//     __fp16 answer_data[] = {
-//       1.0,       1.0,       1.0,       1.0,       5.0,       3.0,
-//       2.3333333, 2.0,       9.0,       5.0,       3.6666667, 3.0,
-//       13.0,      7.0,       5.0,       4.0,       17.0,      9.0,
-//       6.3333335, 5.0,       4.2,       3.6666667, 3.2857144, 3.0,
-//       5.0,       4.3333335, 3.857143,  3.5,       5.8,       5.0,
-//       4.428571,  4.0,       6.6,       5.6666665, 5.0,       4.5,
-//       7.4,       6.3333335, 5.571429,  5.0,       4.5555553, 4.2,
-//       3.909091,  3.6666667, 5.0,       4.6,       4.2727275, 4.0,
-//       5.4444447, 5.0,       4.6363635, 4.3333335, 5.888889,  5.4,
-//       5.0,       4.6666665, 6.3333335, 5.8,       5.3636365, 5.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.divide_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, divide_i_broadcast_not_supported_01_n) {
-//   nntrainer::Tensor target(3, 1, 3, 1);
-//   nntrainer::Tensor target2(3, 1, 3, 3);
-
-//   EXPECT_EQ(target.divide_i(target2), ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, divide_i_broadcast_not_broadcastable_02_n) {
-//   nntrainer::Tensor target(3, 2, 4, 5);
-//   nntrainer::Tensor target2(3, 2, 3, 1);
-
-//   EXPECT_EQ(target.divide_i(target2), ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, add_i_01_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int height = 3;
-//   int width = 10;
-//   int channel = 1;
-
-//   nntrainer::Tensor target(batch, channel, height, width);
-//   GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-//   nntrainer::Tensor original(batch, channel, height, width);
-//   original.copy(target);
-
-//   status = target.add_i(2.1);
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-
-//   __fp16 *previous = original.getData();
-//   ASSERT_NE(nullptr, previous);
-//   __fp16 *data = target.getData();
-//   ASSERT_NE(nullptr, data);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     EXPECT_FLOAT_EQ(data[i], previous[i] + (__fp16)2.1);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, add_i_02_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int height = 3;
-//   int width = 10;
-//   int channel = 1;
-
-//   nntrainer::Tensor target(batch, channel, height, width);
-//   GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor original(batch, height, width);
-//   original.copy(target);
-
-//   status = target.add_i(target, 3.0);
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-
-//   __fp16 *previous = original.getData();
-//   ASSERT_NE(nullptr, previous);
-//   __fp16 *data = target.getData();
-//   ASSERT_NE(nullptr, data);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     EXPECT_FLOAT_EQ(data[i], previous[i] * 4.0);
-//   }
-// }
-
-// /**
-//  * @brief operand dimension is not right
-//  */
-// TEST(nntrainer_Tensor, add_i_01_n) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int height = 3;
-//   int width = 10;
-//   int channel = 1;
-
-//   nntrainer::Tensor target(batch, channel, height, width);
-//   GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor target2(batch, height - 2, width - 3);
-
-//   status = target.add_i(target2);
-//   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, add_i_broadcast_01_p) {
-//   nntrainer::TensorDim ref_dim{3, 2, 4, 5};
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(1, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,   2,   4,   6,   8,   10,  12,  14,  16,  18,  20,  22,  24,  26,
-//       28,  30,  32,  34,  36,  38,  40,  42,  44,  46,  48,  50,  52,  54,
-//       56,  58,  60,  62,  64,  66,  68,  70,  72,  74,  76,  78,  40,  42,
-//       44,  46,  48,  50,  52,  54,  56,  58,  60,  62,  64,  66,  68,  70,
-//       72,  74,  76,  78,  80,  82,  84,  86,  88,  90,  92,  94,  96,  98,
-//       100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 80,  82,  84,  86,
-//       88,  90,  92,  94,  96,  98,  100, 102, 104, 106, 108, 110, 112, 114,
-//       116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142,
-//       144, 146, 148, 150, 152, 154, 156, 158};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 1, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,   2,   4,   6,   8,   10,  12,  14,  16,  18,  20,  22,  24,  26,
-//       28,  30,  32,  34,  36,  38,  20,  22,  24,  26,  28,  30,  32,  34,
-//       36,  38,  40,  42,  44,  46,  48,  50,  52,  54,  56,  58,  60,  62,
-//       64,  66,  68,  70,  72,  74,  76,  78,  80,  82,  84,  86,  88,  90,
-//       92,  94,  96,  98,  80,  82,  84,  86,  88,  90,  92,  94,  96,  98,
-//       100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
-//       128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154,
-//       156, 158, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162,
-//       164, 166, 168, 170, 172, 174, 176, 178};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 2, 4, 1);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   6,   7,   8,   9,   10,  12,  13,  14,  15,
-//       16,  18,  19,  20,  21,  22,  24,  25,  26,  27,  28,  30,  31,  32,
-//       33,  34,  36,  37,  38,  39,  40,  42,  43,  44,  45,  46,  48,  49,
-//       50,  51,  52,  54,  55,  56,  57,  58,  60,  61,  62,  63,  64,  66,
-//       67,  68,  69,  70,  72,  73,  74,  75,  76,  78,  79,  80,  81,  82,
-//       84,  85,  86,  87,  88,  90,  91,  92,  93,  94,  96,  97,  98,  99,
-//       100, 102, 103, 104, 105, 106, 108, 109, 110, 111, 112, 114, 115, 116,
-//       117, 118, 120, 121, 122, 123, 124, 126, 127, 128, 129, 130, 132, 133,
-//       134, 135, 136, 138, 139, 140, 141, 142};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 1, 1, 5);
-//     __fp16 answer_data[] = {
-//       0,   2,   4,   6,   8,   5,   7,   9,   11,  13,  10,  12,  14,  16,
-//       18,  15,  17,  19,  21,  23,  20,  22,  24,  26,  28,  25,  27,  29,
-//       31,  33,  30,  32,  34,  36,  38,  35,  37,  39,  41,  43,  45,  47,
-//       49,  51,  53,  50,  52,  54,  56,  58,  55,  57,  59,  61,  63,  60,
-//       62,  64,  66,  68,  65,  67,  69,  71,  73,  70,  72,  74,  76,  78,
-//       75,  77,  79,  81,  83,  80,  82,  84,  86,  88,  90,  92,  94,  96,
-//       98,  95,  97,  99,  101, 103, 100, 102, 104, 106, 108, 105, 107, 109,
-//       111, 113, 110, 112, 114, 116, 118, 115, 117, 119, 121, 123, 120, 122,
-//       124, 126, 128, 125, 127, 129, 131, 133};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(1, 2, 1, 5);
-//     __fp16 answer_data[] = {
-//       0,   2,   4,   6,   8,   5,   7,   9,   11,  13,  10,  12,  14,  16,
-//       18,  15,  17,  19,  21,  23,  25,  27,  29,  31,  33,  30,  32,  34,
-//       36,  38,  35,  37,  39,  41,  43,  40,  42,  44,  46,  48,  40,  42,
-//       44,  46,  48,  45,  47,  49,  51,  53,  50,  52,  54,  56,  58,  55,
-//       57,  59,  61,  63,  65,  67,  69,  71,  73,  70,  72,  74,  76,  78,
-//       75,  77,  79,  81,  83,  80,  82,  84,  86,  88,  80,  82,  84,  86,
-//       88,  85,  87,  89,  91,  93,  90,  92,  94,  96,  98,  95,  97,  99,
-//       101, 103, 105, 107, 109, 111, 113, 110, 112, 114, 116, 118, 115, 117,
-//       119, 121, 123, 120, 122, 124, 126, 128};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 1, 4, 1);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   6,   7,   8,   9,   10,  12,  13,  14,  15,
-//       16,  18,  19,  20,  21,  22,  20,  21,  22,  23,  24,  26,  27,  28,
-//       29,  30,  32,  33,  34,  35,  36,  38,  39,  40,  41,  42,  44,  45,
-//       46,  47,  48,  50,  51,  52,  53,  54,  56,  57,  58,  59,  60,  62,
-//       63,  64,  65,  66,  64,  65,  66,  67,  68,  70,  71,  72,  73,  74,
-//       76,  77,  78,  79,  80,  82,  83,  84,  85,  86,  88,  89,  90,  91,
-//       92,  94,  95,  96,  97,  98,  100, 101, 102, 103, 104, 106, 107, 108,
-//       109, 110, 108, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121,
-//       122, 123, 124, 126, 127, 128, 129, 130};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(1, 1, 1, 5);
-//     __fp16 answer_data[] = {
-//       0,   2,   4,   6,   8,   5,   7,   9,   11,  13,  10,  12,  14,  16,
-//       18,  15,  17,  19,  21,  23,  20,  22,  24,  26,  28,  25,  27,  29,
-//       31,  33,  30,  32,  34,  36,  38,  35,  37,  39,  41,  43,  40,  42,
-//       44,  46,  48,  45,  47,  49,  51,  53,  50,  52,  54,  56,  58,  55,
-//       57,  59,  61,  63,  60,  62,  64,  66,  68,  65,  67,  69,  71,  73,
-//       70,  72,  74,  76,  78,  75,  77,  79,  81,  83,  80,  82,  84,  86,
-//       88,  85,  87,  89,  91,  93,  90,  92,  94,  96,  98,  95,  97,  99,
-//       101, 103, 100, 102, 104, 106, 108, 105, 107, 109, 111, 113, 110, 112,
-//       114, 116, 118, 115, 117, 119, 121, 123};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(1, 2, 1, 1);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-//       14,  15,  16,  17,  18,  19,  21,  22,  23,  24,  25,  26,  27,  28,
-//       29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  40,  41,
-//       42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-//       56,  57,  58,  59,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
-//       71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  80,  81,  82,  83,
-//       84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
-//       98,  99,  101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
-//       113, 114, 115, 116, 117, 118, 119, 120};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 1, 1, 1);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-//       14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-//       28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  41,  42,
-//       43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
-//       57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
-//       71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  82,  83,  84,  85,
-//       86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-//       100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
-//       114, 115, 116, 117, 118, 119, 120, 121};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(1, 1, 1, 1);
-//     m.add_i(1.0);
-//     __fp16 answer_data[] = {
-//       1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
-//       15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
-//       29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
-//       43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
-//       57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
-//       71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
-//       85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
-//       99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
-//       113, 114, 115, 116, 117, 118, 119, 120};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 5, 1, 4);
-//     nntrainer::Tensor t = ranged(3, 5, 1, 4);
-//     nntrainer::Tensor m = ranged(3, 1, 1, 4);
-//     __fp16 answer_data[] = {0,  2,  4,  6,  4,  6,  8,  10, 8,  10, 12, 14,
-//                            12, 14, 16, 18, 16, 18, 20, 22, 24, 26, 28, 30,
-//                            28, 30, 32, 34, 32, 34, 36, 38, 36, 38, 40, 42,
-//                            40, 42, 44, 46, 48, 50, 52, 54, 52, 54, 56, 58,
-//                            56, 58, 60, 62, 60, 62, 64, 66, 64, 66, 68, 70};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(1, 1, 2, 1);
-//     nntrainer::Tensor t = ranged(1, 1, 2, 1);
-//     nntrainer::Tensor m = ranged(1, 1, 2, 1);
-//     __fp16 answer_data[] = {0.0, 2.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(16, 1, 1, 1);
-//     nntrainer::Tensor t = ranged(16, 1, 1, 1);
-//     nntrainer::Tensor m = ranged(1, 1, 1, 1);
-//     __fp16 answer_data[] = {0.0, 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,
-//                            8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0};
-//     nntrainer::Tensor answer(ref_dim, answer_data);
-//     int status = t.add_i(m);
-//     EXPECT_EQ(status, ML_ERROR_NONE);
-//     EXPECT_EQ(t, answer);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, add_i_broadcast_not_supported_01_n) {
-//   nntrainer::Tensor target(3, 1, 3, 1);
-//   nntrainer::Tensor target2(3, 1, 3, 3);
-
-//   EXPECT_EQ(target.add_i(target2), ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, add_i_broadcast_not_broadcastable_02_n) {
-//   nntrainer::Tensor target(3, 2, 4, 5);
-//   nntrainer::Tensor target2(3, 2, 3, 1);
-
-//   EXPECT_EQ(target.add_i(target2), ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, add_01_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor result = input.add(1.0);
-
-//   __fp16 *data = result.getData();
-//   ASSERT_NE(nullptr, data);
-//   __fp16 *indata = input.getData();
-//   ASSERT_NE(nullptr, indata);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     if (data[i] != indata[i] + (__fp16)1.0) {
-//       status = ML_ERROR_RESULT_OUT_OF_RANGE;
-//       break;
-//     }
-//   }
-
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, add_02_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor result = input.add(input);
-
-//   __fp16 *data = result.getData();
-//   ASSERT_NE(nullptr, data);
-//   __fp16 *indata = input.getData();
-//   ASSERT_NE(nullptr, indata);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     if (data[i] != indata[i] + indata[i]) {
-//       status = ML_ERROR_RESULT_OUT_OF_RANGE;
-//       break;
-//     }
-//   }
-
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, add_03_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor test(batch - 1, channel, height - 1, width - 1);
-
-//   EXPECT_THROW({ input.add(test); }, std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, add_04_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-//   nntrainer::Tensor test(dim);
-
-//   EXPECT_THROW(shared_input.add(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, add_05_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   nntrainer::Tensor test(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-//   EXPECT_THROW(input.add(shared_test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, add_06_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim, false);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-//   EXPECT_THROW(input.add(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, add_07_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim, false);
-
-//   EXPECT_THROW(input.add(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, add_08_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-//   nntrainer::Tensor output(dim, false);
-
-//   EXPECT_THROW(input.add(test, output), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, pow_01_p) {
-
-//   nntrainer::Tensor input = constant(4.0, 3, 2, 4, 5);
-
-//   nntrainer::Tensor actual, expected;
-
-//   actual = input.pow(0.5f);
-//   expected = constant(2.0, 3, 2, 4, 5);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = input.pow(2.0f);
-//   expected = constant(16.0, 3, 2, 4, 5);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = input.pow(-0.5f);
-//   expected = constant(0.5, 3, 2, 4, 5);
-//   EXPECT_EQ(actual, expected);
-// }
-
-// TEST(nntrainer_Tensor, erf_01_p) {
-//   int batch = 1;
-//   int channel = 1;
-//   int height = 2;
-//   int width = 2;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, k + l * 0.5 + 0.5);
-//   nntrainer::Tensor actual = input.erf();
-//   nntrainer::Tensor expected(
-//     std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//       {{{{0.5205, 0.8427}, {0.966105, 0.995322}}}}));
-
-//   EXPECT_EQ(actual, expected);
-// }
-
-// TEST(nntrainer_Tensor, subtract_i_01_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int height = 3;
-//   int width = 10;
-//   int channel = 1;
-
-//   nntrainer::Tensor target(batch, channel, height, width);
-//   GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-//   nntrainer::Tensor original(batch, height, width);
-//   original.copy(target);
-
-//   status = target.subtract_i(2.1);
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-
-//   __fp16 *previous = original.getData();
-//   ASSERT_NE(nullptr, previous);
-//   __fp16 *data = target.getData();
-//   ASSERT_NE(nullptr, data);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     EXPECT_FLOAT_EQ(data[i], previous[i] - (__fp16)2.1);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, subtract_i_02_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int height = 3;
-//   int width = 10;
-//   int channel = 1;
-
-//   nntrainer::Tensor target(batch, channel, height, width);
-//   GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-//   status = target.subtract_i(target);
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-
-//   __fp16 *data = target.getData();
-//   ASSERT_NE(nullptr, data);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     EXPECT_FLOAT_EQ(data[i], 0);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, subtract_i_03_n) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int height = 3;
-//   int width = 10;
-//   int channel = 1;
-
-//   nntrainer::Tensor target(batch, channel, height, width);
-//   GEN_TEST_INPUT(target, i * (batch * height) + j * (width) + k + 1 + channel);
-
-//   nntrainer::Tensor target2(batch, channel, height - 1, width - 3);
-
-//   status = target.subtract_i(target2);
-//   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
-// }
-
-// TEST(nntrainer_Tensor, subtract_01_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor result = input.subtract(1.0);
-
-//   __fp16 *data = result.getData();
-//   ASSERT_NE(nullptr, data);
-//   __fp16 *indata = input.getData();
-//   ASSERT_NE(nullptr, indata);
-
-//   for (int i = 0; i < batch * height * width; ++i) {
-//     if (data[i] != indata[i] - 1.0) {
-//       status = ML_ERROR_RESULT_OUT_OF_RANGE;
-//       break;
-//     }
-//   }
-
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, subtract_02_p) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor result = input.subtract(input);
-
-//   EXPECT_EQ(constant(0.0, batch, channel, height, width), result);
-// }
-
-// TEST(nntrainer_Tensor, subtract_03_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor test(batch - 1, channel, height - 1, width - 1);
-
-//   EXPECT_THROW({ input.subtract(test); }, std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, subtract_04_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_input = input.getSharedDataTensor(dim, 0, false);
-//   nntrainer::Tensor test(dim);
-
-//   EXPECT_THROW(shared_input.subtract(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, subtract_05_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   nntrainer::Tensor test(batch, channel, height, 2 * width);
-//   nntrainer::Tensor shared_test = test.getSharedDataTensor(dim, 0, false);
-
-//   EXPECT_THROW(input.subtract(shared_test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, subtract_06_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim, false);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 1);
-
-//   EXPECT_THROW(input.subtract(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, subtract_07_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim, false);
-
-//   EXPECT_THROW(input.subtract(test), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, subtract_08_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::TensorDim dim(batch, channel, height, width);
-
-//   nntrainer::Tensor input(dim);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-//   nntrainer::Tensor test(dim);
-//   GEN_TEST_INPUT(test, i * (batch * height) + j * (width) + k + 2);
-//   nntrainer::Tensor output(dim, false);
-
-//   EXPECT_THROW(input.subtract(test, output), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, subtract___fp16_01_p) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k + 1);
-
-//   nntrainer::Tensor expected(batch, channel, height, width);
-//   GEN_TEST_INPUT(expected, i * (batch * height) + j * (width) + k);
-
-//   nntrainer::Tensor result = input.subtract(1.0);
-
-//   EXPECT_EQ(result, expected);
-// }
-
-// TEST(nntrainer_Tensor, sum_01_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-//   EXPECT_THROW({ input.sum(4); }, std::out_of_range);
-// }
-
-// TEST(nntrainer_Tensor, sum_02_n) {
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 3;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height) + j * (width) + k);
-
-//   EXPECT_THROW({ input.sum(-1); }, std::out_of_range);
-// }
-
-// TEST(nntrainer_Tensor, sum_02_p) {
-//   int batch = 3;
-//   int channel = 2;
-//   int height = 2;
-//   int width = 10;
-
-//   nntrainer::Tensor ans0(
-//     std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//       {{{{39, 42, 45, 48, 51, 54, 57, 60, 63, 66},
-//          {69, 72, 75, 78, 81, 84, 87, 90, 93, 96}},
-//         {{57, 60, 63, 66, 69, 72, 75, 78, 81, 84},
-//          {87, 90, 93, 96, 99, 102, 105, 108, 111, 114}}}}));
-
-//   nntrainer::Tensor ans1(
-//     std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//       {{{{8, 10, 12, 14, 16, 18, 20, 22, 24, 26},
-//          {28, 30, 32, 34, 36, 38, 40, 42, 44, 46}}},
-//        {{{32, 34, 36, 38, 40, 42, 44, 46, 48, 50},
-//          {52, 54, 56, 58, 60, 62, 64, 66, 68, 70}}},
-//        {{{56, 58, 60, 62, 64, 66, 68, 70, 72, 74},
-//          {76, 78, 80, 82, 84, 86, 88, 90, 92, 94}}}}));
-
-//   nntrainer::Tensor ans2(
-//     std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//       {{{{12, 14, 16, 18, 20, 22, 24, 26, 28, 30}},
-//         {{24, 26, 28, 30, 32, 34, 36, 38, 40, 42}}},
-//        {{{36, 38, 40, 42, 44, 46, 48, 50, 52, 54}},
-//         {{48, 50, 52, 54, 56, 58, 60, 62, 64, 66}}},
-//        {{{60, 62, 64, 66, 68, 70, 72, 74, 76, 78}},
-//         {{72, 74, 76, 78, 80, 82, 84, 86, 88, 90}}}}));
-
-//   nntrainer::Tensor ans3(
-//     std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//       {{{{55}, {155}}, {{115}, {215}}},
-//        {{{175}, {275}}, {{235}, {335}}},
-//        {{{295}, {395}}, {{355}, {455}}}}));
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height * channel) + j * (batch * height) +
-//                           k * (width) + l + 1);
-
-//   nntrainer::Tensor result0 = input.sum(0);
-//   nntrainer::Tensor result1 = input.sum(1);
-//   nntrainer::Tensor result2 = input.sum(2);
-//   nntrainer::Tensor result3 = input.sum(3);
-
-//   EXPECT_EQ(ans0, result0);
-//   EXPECT_EQ(ans1, result1);
-//   EXPECT_EQ(ans2, result2);
-//   EXPECT_EQ(ans3, result3);
-// }
-
-// TEST(nntrainer_Tensor, sum_03_p) {
-//   const int batch = 3;
-//   const int channel = 2;
-//   const int height = 1;
-//   const int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (height * channel * width) + j * (height * width) +
-//                           k * (width) + l + 1);
-//   // Test for alpha == 1 and beta == 0 and dimension of reduced axis == 1
-//   {
-//     nntrainer::Tensor ans_0_1_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{63, 66, 69, 72, 75, 78, 81, 84, 87, 90}},
-//           {{93, 96, 99, 102, 105, 108, 111, 114, 117, 120}}}}));
-
-//     nntrainer::Tensor ans_1_1_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{12, 14, 16, 18, 20, 22, 24, 26, 28, 30}}},
-//          {{{52, 54, 56, 58, 60, 62, 64, 66, 68, 70}}},
-//          {{{92, 94, 96, 98, 100, 102, 104, 106, 108, 110}}}}));
-
-//     nntrainer::Tensor ans_2_1_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
-//           {{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}}},
-//          {{{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}},
-//           {{31, 32, 33, 34, 35, 36, 37, 38, 39, 40}}},
-//          {{{41, 42, 43, 44, 45, 46, 47, 48, 49, 50}},
-//           {{51, 52, 53, 54, 55, 56, 57, 58, 59, 60}}}}));
-
-//     nntrainer::Tensor ans_3_1_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{55}}, {{155}}}, {{{255}}, {{355}}}, {{{455}}, {{555}}}}));
-
-//     nntrainer::Tensor result_0_1_0 = input.sum(0, 1);
-//     nntrainer::Tensor result_1_1_0 = input.sum(1, 1);
-//     nntrainer::Tensor result_2_1_0 = input.sum(2, 1);
-//     nntrainer::Tensor result_3_1_0 = input.sum(3, 1);
-
-//     EXPECT_EQ(ans_0_1_0, result_0_1_0);
-//     EXPECT_EQ(ans_1_1_0, result_1_1_0);
-//     EXPECT_EQ(ans_2_1_0, result_2_1_0);
-//     EXPECT_EQ(ans_3_1_0, result_3_1_0);
-//   }
-
-//   // Test for alpha == 1 and beta == 2 and dimension of reduced axis == 1
-//   {
-//     nntrainer::Tensor ans_0_1_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{65, 70, 75, 80, 85, 90, 95, 100, 105, 110}},
-//           {{115, 120, 125, 130, 135, 140, 145, 150, 155, 160}}}}));
-
-//     nntrainer::Tensor ans_1_1_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{14, 18, 22, 26, 30, 34, 38, 42, 46, 50}}},
-//          {{{74, 78, 82, 86, 90, 94, 98, 102, 106, 110}}},
-//          {{{134, 138, 142, 146, 150, 154, 158, 162, 166, 170}}}}));
-
-//     nntrainer::Tensor ans_2_1_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{3, 6, 9, 12, 15, 18, 21, 24, 27, 30}},
-//           {{33, 36, 39, 42, 45, 48, 51, 54, 57, 60}}},
-//          {{{63, 66, 69, 72, 75, 78, 81, 84, 87, 90}},
-//           {{93, 96, 99, 102, 105, 108, 111, 114, 117, 120}}},
-//          {{{123, 126, 129, 132, 135, 138, 141, 144, 147, 150}},
-//           {{153, 156, 159, 162, 165, 168, 171, 174, 177, 180}}}}));
-
-//     nntrainer::Tensor ans_3_1_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{57}}, {{159}}}, {{{261}}, {{363}}}, {{{465}}, {{567}}}}));
-
-//     nntrainer::Tensor output_0_1_2(1, channel, height, width);
-//     {
-//       const int batch = 1;
-//       GEN_TEST_INPUT(output_0_1_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor output_1_1_2(batch, 1, height, width);
-//     {
-//       const int channel = 1;
-//       GEN_TEST_INPUT(output_1_1_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor output_2_1_2(batch, channel, 1, width);
-//     {
-//       const int height = 1;
-//       GEN_TEST_INPUT(output_2_1_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor output_3_1_2(batch, channel, height, 1);
-//     {
-//       const int width = 1;
-//       GEN_TEST_INPUT(output_3_1_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor result_0_1_2 = input.sum(0, output_0_1_2, 1, 2);
-//     nntrainer::Tensor result_1_1_2 = input.sum(1, output_1_1_2, 1, 2);
-//     nntrainer::Tensor result_2_1_2 = input.sum(2, output_2_1_2, 1, 2);
-//     nntrainer::Tensor result_3_1_2 = input.sum(3, output_3_1_2, 1, 2);
-
-//     EXPECT_EQ(ans_0_1_2, result_0_1_2);
-//     EXPECT_EQ(ans_1_1_2, result_1_1_2);
-//     EXPECT_EQ(ans_2_1_2, result_2_1_2);
-//     EXPECT_EQ(ans_3_1_2, result_3_1_2);
-//   }
-
-//   // Test for alpha == 2 and beta == 0
-//   {
-//     nntrainer::Tensor ans_0_2_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{126, 132, 138, 144, 150, 156, 162, 168, 174, 180}},
-//           {{186, 192, 198, 204, 210, 216, 222, 228, 234, 240}}}}));
-
-//     nntrainer::Tensor ans_1_2_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{24, 28, 32, 36, 40, 44, 48, 52, 56, 60}}},
-//          {{{104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
-//          {{{184, 188, 192, 196, 200, 204, 208, 212, 216, 220}}}}));
-
-//     nntrainer::Tensor ans_2_2_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}},
-//           {{22, 24, 26, 28, 30, 32, 34, 36, 38, 40}}},
-//          {{{42, 44, 46, 48, 50, 52, 54, 56, 58, 60}},
-//           {{62, 64, 66, 68, 70, 72, 74, 76, 78, 80}}},
-//          {{{82, 84, 86, 88, 90, 92, 94, 96, 98, 100}},
-//           {{102, 104, 106, 108, 110, 112, 114, 116, 118, 120}}}}));
-
-//     nntrainer::Tensor ans_3_2_0(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{110}}, {{310}}}, {{{510}}, {{710}}}, {{{910}}, {{1110}}}}));
-
-//     nntrainer::Tensor result_0_2_0 = input.sum(0, 2);
-//     nntrainer::Tensor result_1_2_0 = input.sum(1, 2);
-//     nntrainer::Tensor result_2_2_0 = input.sum(2, 2);
-//     nntrainer::Tensor result_3_2_0 = input.sum(3, 2);
-
-//     EXPECT_EQ(ans_0_2_0, result_0_2_0);
-//     EXPECT_EQ(ans_1_2_0, result_1_2_0);
-//     EXPECT_EQ(ans_2_2_0, result_2_2_0);
-//     EXPECT_EQ(ans_3_2_0, result_3_2_0);
-//   }
-
-//   // Test for alpha == 2 and beta == 2
-//   {
-//     nntrainer::Tensor ans_0_2_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{128, 136, 144, 152, 160, 168, 176, 184, 192, 200}},
-//           {{208, 216, 224, 232, 240, 248, 256, 264, 272, 280}}}}));
-
-//     nntrainer::Tensor ans_1_2_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{26, 32, 38, 44, 50, 56, 62, 68, 74, 80}}},
-//          {{{126, 132, 138, 144, 150, 156, 162, 168, 174, 180}}},
-//          {{{226, 232, 238, 244, 250, 256, 262, 268, 274, 280}}}}));
-
-//     nntrainer::Tensor ans_2_2_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{4, 8, 12, 16, 20, 24, 28, 32, 36, 40}},
-//           {{44, 48, 52, 56, 60, 64, 68, 72, 76, 80}}},
-//          {{{84, 88, 92, 96, 100, 104, 108, 112, 116, 120}},
-//           {{124, 128, 132, 136, 140, 144, 148, 152, 156, 160}}},
-//          {{{164, 168, 172, 176, 180, 184, 188, 192, 196, 200}},
-//           {{204, 208, 212, 216, 220, 224, 228, 232, 236, 240}}}}));
-
-//     nntrainer::Tensor ans_3_2_2(
-//       std::vector<std::vector<std::vector<std::vector<__fp16>>>>(
-//         {{{{112}}, {{314}}}, {{{516}}, {{718}}}, {{{920}}, {{1122}}}}));
-
-//     nntrainer::Tensor output_0_2_2(1, channel, height, width);
-//     {
-//       const int batch = 1;
-//       GEN_TEST_INPUT(output_0_2_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor output_1_2_2(batch, 1, height, width);
-//     {
-//       const int channel = 1;
-//       GEN_TEST_INPUT(output_1_2_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor output_2_2_2(batch, channel, 1, width);
-//     {
-//       const int height = 1;
-//       GEN_TEST_INPUT(output_2_2_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor output_3_2_2(batch, channel, height, 1);
-//     {
-//       const int width = 1;
-//       GEN_TEST_INPUT(output_3_2_2, i * (channel * height * width) +
-//                                      j * (height * width) + k * (width) + l +
-//                                      1);
-//     }
-//     nntrainer::Tensor result_0_2_2 = input.sum(0, output_0_2_2, 2, 2);
-//     nntrainer::Tensor result_1_2_2 = input.sum(1, output_1_2_2, 2, 2);
-//     nntrainer::Tensor result_2_2_2 = input.sum(2, output_2_2_2, 2, 2);
-//     nntrainer::Tensor result_3_2_2 = input.sum(3, output_3_2_2, 2, 2);
-
-//     EXPECT_EQ(ans_0_2_2, result_0_2_2);
-//     EXPECT_EQ(ans_1_2_2, result_1_2_2);
-//     EXPECT_EQ(ans_2_2_2, result_2_2_2);
-//     EXPECT_EQ(ans_3_2_2, result_3_2_2);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, sum_04_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 2;
-//   int height = 2;
-//   int width = 10;
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (batch * height * channel) + j * (height * width) +
-//                           k * width + l + 1);
-
-//   nntrainer::Tensor result = input.sum_by_batch();
-//   if (result.getValue(0, 0, 0, 0) != 820 ||
-//       result.getValue(1, 0, 0, 0) != 1300 ||
-//       result.getValue(2, 0, 0, 0) != 1780)
-//     status = ML_ERROR_RESULT_OUT_OF_RANGE;
-
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, multiple_sum_invalid_args_01_n) {
-//   nntrainer::Tensor t = constant(1.0, 1, 1, 1, 1);
-//   EXPECT_THROW(t.sum(std::vector<unsigned int>()), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, multiple_sum_out_of_range_n) {
-//   nntrainer::Tensor t = constant(1.0, 1, 1, 1, 1);
-//   EXPECT_THROW(t.sum({7}), std::out_of_range);
-// }
-
-// TEST(nntrainer_Tensor, multiple_sum_p) {
-//   nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-//   nntrainer::Tensor actual, expected;
-
-//   actual = t.sum({0, 1});
-//   expected = constant(2 * 3, 1, 1, 5, 7);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.sum({1, 2, 3});
-//   expected = constant(3 * 5 * 7, 2, 1, 1, 1);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.sum({3, 1});
-//   expected = constant(7 * 3, 2, 1, 5, 1);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.sum({3, 1}, 0.5);
-//   expected = constant(7 * 3 * 0.5, 2, 1, 5, 1);
-//   EXPECT_EQ(actual, expected);
-// }
-
-// TEST(nntrainer_Tensor, average_p) {
-//   nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-
-//   nntrainer::Tensor actual, expected;
-
-//   actual = t.average();
-//   expected = constant(1.0, 1, 1, 1, 1);
-//   EXPECT_EQ(actual, expected);
-
-//   int idx = 0;
-//   t = t.apply([&](__fp16 in) { return idx++ % 2; });
-
-//   actual = t.average();
-//   expected = constant(0.5, 1, 1, 1, 1);
-//   EXPECT_EQ(actual, expected);
-// }
-
-// TEST(nntrainer_Tensor, average_axis_p) {
-//   nntrainer::Tensor t = constant(1.0, 2, 2, 2, 2);
-//   int idx = 0;
-//   std::function<__fp16(__fp16)> f = [&](__fp16 in) { return idx++ % 2; };
-//   t = t.apply(f);
-
-//   nntrainer::Tensor actual, expected;
-
-//   actual = t.average(0);
-//   expected = constant(0, 1, 2, 2, 2).apply(f);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.average(1);
-//   expected = constant(0, 2, 1, 2, 2).apply(f);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.average(2);
-//   expected = constant(0, 2, 2, 1, 2).apply(f);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.average(3);
-//   expected = constant(0.5, 2, 2, 2, 1);
-//   EXPECT_EQ(actual, expected);
-// }
-
-// TEST(nntrainer_Tensor, average_axis_out_of_range_01_n) {
-//   nntrainer::Tensor t = constant(1.0, 2, 2, 2, 2);
-//   EXPECT_THROW(t.average(-1), std::out_of_range);
-// }
-
-// TEST(nntrainer_Tensor, average_axis_out_of_range_02_n) {
-//   nntrainer::Tensor t = constant(1.0, 2, 2, 2, 2);
-//   EXPECT_THROW(t.average(7), std::out_of_range);
-// }
-
-// TEST(nntrainer_Tensor, average_multiple_axes_p) {
-//   nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-//   nntrainer::Tensor actual, expected;
-
-//   actual = t.average({0, 1, 2});
-//   expected = constant(1.0, 1, 1, 1, 7);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.average({0, 1, 2, 3});
-//   expected = constant(1.0, 1, 1, 1, 1);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.average({3, 1});
-//   expected = constant(1.0, 2, 1, 5, 1);
-//   EXPECT_EQ(actual, expected);
-
-//   actual = t.average({3, 1, 1, 1, 3});
-//   expected = constant(1.0, 2, 1, 5, 1);
-//   EXPECT_EQ(actual, expected);
-// }
-
-// TEST(nntrainer_Tensor, average_multiple_axes_01_n) {
-//   nntrainer::Tensor t = constant(1.0, 2, 3, 5, 7);
-//   EXPECT_THROW(t.average({5, 7}), std::out_of_range);
-// }
-
-// TEST(nntrainer_Tensor, dot_01_n) {
-//   nntrainer::Tensor input(2, 3, 4, 5);
-//   nntrainer::Tensor m(1, 3, 4, 5);
-//   EXPECT_THROW(nntrainer::Tensor result = input.dot(m), std::runtime_error);
-// }
-
-// TEST(nntrainer_Tensor, dot_02_n) {
-//   nntrainer::Tensor input(2, 3, 4, 5);
-//   nntrainer::Tensor m(1, 3, 4, 5);
-//   EXPECT_THROW(nntrainer::Tensor result = input.dot(m, true),
-//                std::runtime_error);
-// }
-
-// TEST(nntrainer_Tensor, dot_02_p) {
-//   nntrainer::Tensor input(2, 3, 4, 5);
-//   nntrainer::Tensor m(1, 3, 4, 5);
-//   EXPECT_NO_THROW(nntrainer::Tensor result = input.dot(m, false, true));
-// }
-
-// TEST(nntrainer_Tensor, dot_03_p) {
-//   nntrainer::Tensor input(1, 3, 4, 5);
-//   nntrainer::Tensor m(1, 3, 4, 5);
-//   EXPECT_NO_THROW(nntrainer::Tensor result = input.dot(m, true));
-// }
-
-// TEST(nntrainer_Tensor, dot_04_n) {
-//   nntrainer::Tensor input(2, 3, 4, 5);
-//   nntrainer::Tensor m(1, 1, 4, 5);
-//   EXPECT_THROW(nntrainer::Tensor result = input.dot(m), std::runtime_error);
-//   EXPECT_NO_THROW(nntrainer::Tensor result = input.dot(m, false, true));
-// }
-
-// TEST(nntrainer_Tensor, dot_05_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 2;
-//   int channel = 3;
-//   int height = 4;
-//   int width = 5;
-//   __fp16 ans[2][3][4][24] = {0};
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (channel * width * height) + j * (height * width) +
-//                           k * (width) + l + 1);
-//   nntrainer::Tensor weight(batch, channel, height, width);
-//   GEN_TEST_INPUT(weight, i * (channel * width * height) + j * (height * width) +
-//                            k * (width) + l + 1);
-//   weight.reshape({1, 1, 24, 5});
-
-//   nntrainer::Tensor result = input.dot(weight, false, true);
-
-//   for (int b = 0; b < batch; b++) {
-//     for (int c = 0; c < channel; c++) {
-//       for (int h = 0; h < height; h++) {
-//         for (int k = 0; k < batch * channel * height; k++) {
-//           ans[b][c][h][k] = 0;
-//           for (int w = 0; w < width; w++) {
-//             __fp16 val1 = input.getValue(b, c, h, w);
-//             __fp16 val2 = weight.getValue(0, 0, k, w);
-//             ans[b][c][h][k] += val1 * val2;
-//           }
-//         }
-//       }
-//     }
-//   }
-
-//   for (unsigned int i = 0; i < result.batch(); ++i) {
-//     for (unsigned int c = 0; c < result.channel(); ++c) {
-//       for (unsigned int j = 0; j < result.height(); ++j) {
-//         for (unsigned int k = 0; k < result.width(); ++k) {
-//           __fp16 val1 = ans[i][c][j][k];
-//           __fp16 val2 = result.getValue(i, c, j, k);
-//           if (val1 != val2) {
-//             status = ML_ERROR_RESULT_OUT_OF_RANGE;
-//             goto end_dot_01_p;
-//           }
-//         }
-//       }
-//     }
-//   }
-// end_dot_01_p:
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, dot_06_p) {
-//   int status = ML_ERROR_NONE;
-//   int batch = 3;
-//   int channel = 1;
-//   int height = 1;
-//   int width = 3;
-//   __fp16 ans[3][1][1][3] = {
-//     {{{30, 36, 42}}}, {{{66, 81, 96}}}, {{{102, 126, 150}}}};
-
-//   nntrainer::Tensor input(batch, channel, height, width);
-//   GEN_TEST_INPUT(input, i * (channel * width * height) + j * (height * width) +
-//                           k * (width) + l + 1);
-
-//   nntrainer::Tensor result = input.dot(input);
-
-//   for (unsigned int i = 0; i < result.batch(); ++i) {
-//     for (unsigned int j = 0; j < result.height(); ++j) {
-//       for (unsigned int k = 0; k < result.width(); ++k) {
-//         if (ans[i][0][j][k] != result.getValue(i, 0, j, k)) {
-//           status = ML_ERROR_RESULT_OUT_OF_RANGE;
-//           goto end_dot_01_p;
-//         }
-//       }
-//     }
-//   }
-// end_dot_01_p:
-//   EXPECT_EQ(status, ML_ERROR_NONE);
-// }
-
-// TEST(nntrainer_Tensor, dot_transpose_p) {
-//   {
-//     __fp16 a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-//                            92, 113, 134, 155, 128, 158, 188, 218};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-//                            92, 113, 134, 155, 128, 158, 188, 218};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-//                            92, 113, 134, 155, 128, 158, 188, 218};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
-//                            92, 113, 134, 155, 128, 158, 188, 218};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 1, 4, 2, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 1, 4, 2, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-//     __fp16 b_data[] = {0, 2, 4, 1, 3, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-//     __fp16 b_data[] = {0, 2, 4, 1, 3, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 1, 4, 2, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-//     __fp16 b_data[] = {0, 2, 4, 1, 3, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 1, 4, 2, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-//     __fp16 b_data[] = {0, 2, 4, 1, 3, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-//     __fp16 answer_data[] = {10, 13, 28, 40};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, dot_shortcuts_p) {
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-//     __fp16 answer_data[] = {5};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-//     __fp16 answer_data[] = {5};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-//     __fp16 answer_data[] = {5};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-//     __fp16 answer_data[] = {5};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-//     __fp16 answer_data[] = {5, 14};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 1, 4, 2, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-//     __fp16 answer_data[] = {5, 14};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-//     __fp16 answer_data[] = {5, 14};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 1, 4, 2, 5};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-//     __fp16 answer_data[] = {5, 14};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-//     __fp16 answer_data[] = {5, 14, 23, 32};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 1), b_data);
-//     __fp16 answer_data[] = {5, 14, 23, 32};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-//     __fp16 answer_data[] = {5, 14, 23, 32};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
-//     __fp16 b_data[] = {0, 1, 2};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 1, 3), b_data);
-//     __fp16 answer_data[] = {5, 14, 23, 32};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 1), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
-//     __fp16 answer_data[] = {20, 23, 26, 29};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 4), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-//     __fp16 answer_data[] = {10, 13};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 1, 2, 3, 4, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
-//     __fp16 answer_data[] = {10, 13};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, false);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 1, 3), a_data);
-//     __fp16 b_data[] = {0, 2, 4, 1, 3, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-//     __fp16 answer_data[] = {10, 13};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, false, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-//   {
-//     __fp16 a_data[] = {0, 1, 2};
-//     nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 1), a_data);
-//     __fp16 b_data[] = {0, 2, 4, 1, 3, 5};
-//     nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
-//     __fp16 answer_data[] = {10, 13};
-//     nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 1, 2), answer_data);
-//     nntrainer::Tensor ret = a.dot(b, true, true);
-//     EXPECT_EQ(ret, answer);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, transpose_p) {
-//   nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-
-//   /// plain transpose
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-//       14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-//       28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-//       42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-//       56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-//       70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-//       84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
-//       98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-//       112, 113, 114, 115, 116, 117, 118, 119};
-//     nntrainer::Tensor answer({3, 2, 4, 5}, answer_data);
-//     nntrainer::Tensor m = t.transpose("0:1:2");
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,   5,   10,  15,  1,   6,   11,  16,  2,   7,   12,  17,  3,   8,
-//       13,  18,  4,   9,   14,  19,  20,  25,  30,  35,  21,  26,  31,  36,
-//       22,  27,  32,  37,  23,  28,  33,  38,  24,  29,  34,  39,  40,  45,
-//       50,  55,  41,  46,  51,  56,  42,  47,  52,  57,  43,  48,  53,  58,
-//       44,  49,  54,  59,  60,  65,  70,  75,  61,  66,  71,  76,  62,  67,
-//       72,  77,  63,  68,  73,  78,  64,  69,  74,  79,  80,  85,  90,  95,
-//       81,  86,  91,  96,  82,  87,  92,  97,  83,  88,  93,  98,  84,  89,
-//       94,  99,  100, 105, 110, 115, 101, 106, 111, 116, 102, 107, 112, 117,
-//       103, 108, 113, 118, 104, 109, 114, 119};
-//     nntrainer::Tensor answer({3, 2, 5, 4}, answer_data);
-//     nntrainer::Tensor m = t.transpose("0:2:1");
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   20,  21,  22,  23,  24,  5,   6,   7,   8,
-//       9,   25,  26,  27,  28,  29,  10,  11,  12,  13,  14,  30,  31,  32,
-//       33,  34,  15,  16,  17,  18,  19,  35,  36,  37,  38,  39,  40,  41,
-//       42,  43,  44,  60,  61,  62,  63,  64,  45,  46,  47,  48,  49,  65,
-//       66,  67,  68,  69,  50,  51,  52,  53,  54,  70,  71,  72,  73,  74,
-//       55,  56,  57,  58,  59,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-//       84,  100, 101, 102, 103, 104, 85,  86,  87,  88,  89,  105, 106, 107,
-//       108, 109, 90,  91,  92,  93,  94,  110, 111, 112, 113, 114, 95,  96,
-//       97,  98,  99,  115, 116, 117, 118, 119};
-//     nntrainer::Tensor answer({3, 4, 2, 5}, answer_data);
-//     nntrainer::Tensor m = t.transpose("1:0:2");
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,  20,  1,  21,  2,  22,  3,  23,  4,  24,  5,  25,  6,  26,  7,  27,
-//       8,  28,  9,  29,  10, 30,  11, 31,  12, 32,  13, 33,  14, 34,  15, 35,
-//       16, 36,  17, 37,  18, 38,  19, 39,  40, 60,  41, 61,  42, 62,  43, 63,
-//       44, 64,  45, 65,  46, 66,  47, 67,  48, 68,  49, 69,  50, 70,  51, 71,
-//       52, 72,  53, 73,  54, 74,  55, 75,  56, 76,  57, 77,  58, 78,  59, 79,
-//       80, 100, 81, 101, 82, 102, 83, 103, 84, 104, 85, 105, 86, 106, 87, 107,
-//       88, 108, 89, 109, 90, 110, 91, 111, 92, 112, 93, 113, 94, 114, 95, 115,
-//       96, 116, 97, 117, 98, 118, 99, 119};
-//     nntrainer::Tensor answer({3, 4, 5, 2}, answer_data);
-//     nntrainer::Tensor m = t.transpose("1:2:0");
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,  5,  10,  15,  20,  25,  30,  35, 1,  6,   11,  16,  21,  26,  31,
-//       36, 2,  7,   12,  17,  22,  27,  32, 37, 3,   8,   13,  18,  23,  28,
-//       33, 38, 4,   9,   14,  19,  24,  29, 34, 39,  40,  45,  50,  55,  60,
-//       65, 70, 75,  41,  46,  51,  56,  61, 66, 71,  76,  42,  47,  52,  57,
-//       62, 67, 72,  77,  43,  48,  53,  58, 63, 68,  73,  78,  44,  49,  54,
-//       59, 64, 69,  74,  79,  80,  85,  90, 95, 100, 105, 110, 115, 81,  86,
-//       91, 96, 101, 106, 111, 116, 82,  87, 92, 97,  102, 107, 112, 117, 83,
-//       88, 93, 98,  103, 108, 113, 118, 84, 89, 94,  99,  104, 109, 114, 119};
-//     nntrainer::Tensor answer({3, 5, 2, 4}, answer_data);
-//     nntrainer::Tensor m = t.transpose("2:0:1");
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,  20,  5,  25,  10, 30,  15, 35,  1,  21,  6,  26,  11, 31,  16, 36,
-//       2,  22,  7,  27,  12, 32,  17, 37,  3,  23,  8,  28,  13, 33,  18, 38,
-//       4,  24,  9,  29,  14, 34,  19, 39,  40, 60,  45, 65,  50, 70,  55, 75,
-//       41, 61,  46, 66,  51, 71,  56, 76,  42, 62,  47, 67,  52, 72,  57, 77,
-//       43, 63,  48, 68,  53, 73,  58, 78,  44, 64,  49, 69,  54, 74,  59, 79,
-//       80, 100, 85, 105, 90, 110, 95, 115, 81, 101, 86, 106, 91, 111, 96, 116,
-//       82, 102, 87, 107, 92, 112, 97, 117, 83, 103, 88, 108, 93, 113, 98, 118,
-//       84, 104, 89, 109, 94, 114, 99, 119};
-//     nntrainer::Tensor answer({3, 5, 4, 2}, answer_data);
-//     nntrainer::Tensor m = t.transpose("2:1:0");
-//     EXPECT_EQ(answer, m);
-//   }
-
-//   /// outplace transpose
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 2, 4, 5);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-//       14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-//       28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-//       42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-//       56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-//       70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-//       84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
-//       98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-//       112, 113, 114, 115, 116, 117, 118, 119};
-//     nntrainer::Tensor answer({3, 2, 4, 5}, answer_data);
-//     t.transpose("0:1:2", m);
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 2, 5, 4);
-//     __fp16 answer_data[] = {
-//       0,   5,   10,  15,  1,   6,   11,  16,  2,   7,   12,  17,  3,   8,
-//       13,  18,  4,   9,   14,  19,  20,  25,  30,  35,  21,  26,  31,  36,
-//       22,  27,  32,  37,  23,  28,  33,  38,  24,  29,  34,  39,  40,  45,
-//       50,  55,  41,  46,  51,  56,  42,  47,  52,  57,  43,  48,  53,  58,
-//       44,  49,  54,  59,  60,  65,  70,  75,  61,  66,  71,  76,  62,  67,
-//       72,  77,  63,  68,  73,  78,  64,  69,  74,  79,  80,  85,  90,  95,
-//       81,  86,  91,  96,  82,  87,  92,  97,  83,  88,  93,  98,  84,  89,
-//       94,  99,  100, 105, 110, 115, 101, 106, 111, 116, 102, 107, 112, 117,
-//       103, 108, 113, 118, 104, 109, 114, 119};
-//     nntrainer::Tensor answer({3, 2, 5, 4}, answer_data);
-//     t.transpose("0:2:1", m);
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 4, 2, 5);
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   20,  21,  22,  23,  24,  5,   6,   7,   8,
-//       9,   25,  26,  27,  28,  29,  10,  11,  12,  13,  14,  30,  31,  32,
-//       33,  34,  15,  16,  17,  18,  19,  35,  36,  37,  38,  39,  40,  41,
-//       42,  43,  44,  60,  61,  62,  63,  64,  45,  46,  47,  48,  49,  65,
-//       66,  67,  68,  69,  50,  51,  52,  53,  54,  70,  71,  72,  73,  74,
-//       55,  56,  57,  58,  59,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-//       84,  100, 101, 102, 103, 104, 85,  86,  87,  88,  89,  105, 106, 107,
-//       108, 109, 90,  91,  92,  93,  94,  110, 111, 112, 113, 114, 95,  96,
-//       97,  98,  99,  115, 116, 117, 118, 119};
-//     nntrainer::Tensor answer({3, 4, 2, 5}, answer_data);
-//     t.transpose("1:0:2", m);
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 4, 5, 2);
-//     __fp16 answer_data[] = {
-//       0,  20,  1,  21,  2,  22,  3,  23,  4,  24,  5,  25,  6,  26,  7,  27,
-//       8,  28,  9,  29,  10, 30,  11, 31,  12, 32,  13, 33,  14, 34,  15, 35,
-//       16, 36,  17, 37,  18, 38,  19, 39,  40, 60,  41, 61,  42, 62,  43, 63,
-//       44, 64,  45, 65,  46, 66,  47, 67,  48, 68,  49, 69,  50, 70,  51, 71,
-//       52, 72,  53, 73,  54, 74,  55, 75,  56, 76,  57, 77,  58, 78,  59, 79,
-//       80, 100, 81, 101, 82, 102, 83, 103, 84, 104, 85, 105, 86, 106, 87, 107,
-//       88, 108, 89, 109, 90, 110, 91, 111, 92, 112, 93, 113, 94, 114, 95, 115,
-//       96, 116, 97, 117, 98, 118, 99, 119};
-//     nntrainer::Tensor answer({3, 4, 5, 2}, answer_data);
-//     t.transpose("1:2:0", m);
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 5, 2, 4);
-//     __fp16 answer_data[] = {
-//       0,  5,  10,  15,  20,  25,  30,  35, 1,  6,   11,  16,  21,  26,  31,
-//       36, 2,  7,   12,  17,  22,  27,  32, 37, 3,   8,   13,  18,  23,  28,
-//       33, 38, 4,   9,   14,  19,  24,  29, 34, 39,  40,  45,  50,  55,  60,
-//       65, 70, 75,  41,  46,  51,  56,  61, 66, 71,  76,  42,  47,  52,  57,
-//       62, 67, 72,  77,  43,  48,  53,  58, 63, 68,  73,  78,  44,  49,  54,
-//       59, 64, 69,  74,  79,  80,  85,  90, 95, 100, 105, 110, 115, 81,  86,
-//       91, 96, 101, 106, 111, 116, 82,  87, 92, 97,  102, 107, 112, 117, 83,
-//       88, 93, 98,  103, 108, 113, 118, 84, 89, 94,  99,  104, 109, 114, 119};
-//     nntrainer::Tensor answer({3, 5, 2, 4}, answer_data);
-//     t.transpose("2:0:1", m);
-//     EXPECT_EQ(answer, m);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     nntrainer::Tensor m = ranged(3, 5, 4, 2);
-//     __fp16 answer_data[] = {
-//       0,  20,  5,  25,  10, 30,  15, 35,  1,  21,  6,  26,  11, 31,  16, 36,
-//       2,  22,  7,  27,  12, 32,  17, 37,  3,  23,  8,  28,  13, 33,  18, 38,
-//       4,  24,  9,  29,  14, 34,  19, 39,  40, 60,  45, 65,  50, 70,  55, 75,
-//       41, 61,  46, 66,  51, 71,  56, 76,  42, 62,  47, 67,  52, 72,  57, 77,
-//       43, 63,  48, 68,  53, 73,  58, 78,  44, 64,  49, 69,  54, 74,  59, 79,
-//       80, 100, 85, 105, 90, 110, 95, 115, 81, 101, 86, 106, 91, 111, 96, 116,
-//       82, 102, 87, 107, 92, 112, 97, 117, 83, 103, 88, 108, 93, 113, 98, 118,
-//       84, 104, 89, 109, 94, 114, 99, 119};
-//     nntrainer::Tensor answer({3, 5, 4, 2}, answer_data);
-//     t.transpose("2:1:0", m);
-//     EXPECT_EQ(answer, m);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, tranpose_dimension_not_match_n) {
-//   nntrainer::Tensor a(3, 2, 4, 5);
-//   nntrainer::Tensor b(3, 1, 2, 3);
-
-//   EXPECT_THROW(a.transpose("0:1:2", b), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, set_01_p) {
-//   nntrainer::Tensor tensor = nntrainer::Tensor(1, 1, 1, 1);
-
-//   tensor.setZero();
-//   EXPECT_EQ(tensor.getValue(0, 0, 0, 0), 0.0);
-
-//   tensor.setRandUniform(-0.5, 0);
-//   __fp16 val = tensor.getValue(0, 0, 0, 0);
-//   EXPECT_TRUE(val >= -0.5 && val < 0);
-// }
-
-// TEST(nntrainer_Tensor, save_read_01_p) {
-//   int batch = 3;
-//   int channel = 4;
-//   int height = 5;
-//   int width = 6;
-//   nntrainer::Tensor target(3, 4, 5, 6);
-//   nntrainer::Tensor readed(3, 4, 5, 6);
-
-//   GEN_TEST_INPUT(target, i * (channel * width * height) + j * (height * width) +
-//                            k * (width) + l + 1);
-
-//   std::ofstream save_file("save.bin", std::ios::out | std::ios::binary);
-//   target.save(save_file);
-//   save_file.close();
-
-//   std::ifstream read_file("save.bin");
-//   readed.read(read_file);
-//   read_file.close();
-
-//   EXPECT_EQ(target, readed);
-
-//   int status = std::remove("save.bin");
-
-//   ASSERT_EQ(status, 0);
-// }
-
-// TEST(nntrainer_Tensor, save_read_01_n) {
-//   int batch = 3;
-//   int channel = 4;
-//   int height = 5;
-//   int width = 6;
-//   nntrainer::Tensor target(3, 4, 5, 6);
-//   nntrainer::Tensor readed(3, 4, 1, 1);
-
-//   GEN_TEST_INPUT(target, i * (channel * width * height) + j * (height * width) +
-//                            k * (width) + l + 1);
-
-//   std::ofstream save_file("save.bin", std::ios::out | std::ios::binary);
-//   target.save(save_file);
-//   save_file.close();
-
-//   std::ifstream read_file("save.bin");
-//   readed.read(read_file);
-//   read_file.close();
-
-//   EXPECT_NE(target, readed);
-
-//   int status = std::remove("save.bin");
-
-//   ASSERT_EQ(status, 0);
-// }
-
-// TEST(nntrainer_Tensor, copy_and_shares_variable_p) {
-//   nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-//   nntrainer::Tensor B = A.clone();
-//   nntrainer::Tensor C = A;
-
-//   C.setValue(1, 1, 1, 1, 2.0f);
-
-//   EXPECT_EQ(A, C);
-//   EXPECT_NE(B, C);
-
-//   C.reshape(nntrainer::TensorDim(3, 4, 6, 5));
-//   EXPECT_EQ(A.getDim(), B.getDim());
-//   EXPECT_NE(A.getDim(), C.getDim());
-// }
-
-// TEST(nntrainer_Tensor, reshape_n_01) {
-//   nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-
-//   EXPECT_THROW(A.reshape(nntrainer::TensorDim(9, 9, 9, 9)),
-//                std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, reshape_n_02) {
-//   nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-//   nntrainer::TensorDim A_dim = A.getDim();
-
-//   /** Changing the dim of a tensor only affects local copy of the dim */
-//   A_dim.setTensorDim(1, 100);
-//   EXPECT_EQ(A_dim.getTensorDim(1), 100u);
-
-//   nntrainer::TensorDim A_dim_2 = A.getDim();
-//   EXPECT_EQ(A_dim_2.getTensorDim(1), 4u);
-// }
-
-// TEST(nntrainer_Tensor, copy_and_reshape_n) {
-//   nntrainer::Tensor A = constant(1.0f, 3, 4, 5, 6);
-//   nntrainer::Tensor B = A;
-//   nntrainer::Tensor C = A.clone();
-
-//   EXPECT_THROW(B.reshape(nntrainer::TensorDim(9, 9, 9, 9)),
-//                std::invalid_argument);
-// }
-
-// /// @note this test case demonstrates it is dangerous to use sharedConstTensor
-// /// to const correct the inner data.
-// TEST(nntrainer_Tensor, constructor_from_shared_const_ptr_shares_variable_n) {
-//   nntrainer::sharedConstTensor A =
-//     MAKE_SHARED_TENSOR(constant(1.0f, 3, 4, 5, 6));
-
-//   nntrainer::Tensor B = *A;
-//   nntrainer::Tensor C = A->clone();
-
-//   B.setValue(2, 3, 4, 5, 2.0f);
-//   EXPECT_EQ(*A, B);
-//   EXPECT_NE(*A, C);
-
-//   C.reshape(nntrainer::TensorDim(3, 4, 6, 5));
-//   EXPECT_EQ(A->getDim(), B.getDim());
-//   EXPECT_NE(A->getDim(), C.getDim());
-// }
-
-// TEST(nntrainer_Tensor, print_small_size) {
-//   nntrainer::Tensor target = constant(1.0, 3, 1, 2, 3);
-
-//   std::stringstream ss, expected;
-//   ss << target;
-
-//   expected << '<' << typeid(target).name() << " at " << &target << ">\n"
-//            << "data addr: " << target.getData() << '\n'
-//            << "Shape: 3:1:2:3\n"
-//            << "         1          1          1 \n"
-//            << "         1          1          1 \n"
-//            << "\n"
-//            << "-------\n"
-//            << "         1          1          1 \n"
-//            << "         1          1          1 \n"
-//            << "\n"
-//            << "-------\n"
-//            << "         1          1          1 \n"
-//            << "         1          1          1 \n"
-//            << "\n"
-//            << "-------\n";
-
-//   EXPECT_EQ(ss.str(), expected.str());
-// }
-
-// // TEST(nntrainer_Tensor, print_large_size) {
-// //   nntrainer::Tensor target = constant(1.2, 3, 10, 10, 10);
-
-// //   std::stringstream ss, expected;
-
-// //   expected << '<' << typeid(target).name() << " at " << &target << ">\n"
-// //            << "data addr: " << target.getData() << '\n'
-// //            << "Shape: 3:10:10:10\n"
-// //            << "[1.2 1.2 1.2 ... 1.2 1.2 1.2]\n";
-// //   ss << target;
-
-// //   EXPECT_EQ(ss.str(), expected.str());
-// // }
-
-// TEST(nntrainer_Tensor, DISABLED_equation_test_01_p) {
-//   nntrainer::Tensor a, b, c;
-//   nntrainer::Tensor ret1, ret2;
-
-//   a = randUniform(4, 6, 7, 3, -100, 100);
-//   b = randUniform(4, 6, 7, 3, -100, 100);
-//   c = randUniform(4, 6, 7, 3, -100, 100);
-
-//   ret1 = a.subtract(b).multiply(c);
-//   ret2 = a.multiply(c).subtract(b.multiply(c));
-
-//   __fp16 *data1 = ret1.getData();
-//   __fp16 *data2 = ret2.getData();
-//   EXPECT_EQ(ret1, ret2);
-
-//   for (unsigned int i = 0; i < ret1.size(); ++i) {
-//     EXPECT_FLOAT_EQ(data1[i], data2[i]);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, fill_p) {
-//   /// same dimension, buffer size
-//   {
-//     nntrainer::Tensor target(3, 2, 4, 5);
-//     nntrainer::Tensor original = randUniform(3, 2, 4, 5, -1.0f, 1.0f);
-//     target.fill(original, false);
-
-//     EXPECT_EQ(target, original);
-//   }
-
-//   /// same dimension, buffer size is different (not tested)
-//   {
-//     /// there is no way to make non contiguous tensor publicily yet
-//     EXPECT_TRUE(true);
-//   }
-
-//   /// uninitialized with initialized flag is true
-//   {
-//     nntrainer::Tensor target;
-//     nntrainer::Tensor original = randUniform(3, 2, 4, 5, -1.0f, 1.0f);
-//     target.fill(original, true);
-
-//     EXPECT_EQ(target, original);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, fill_uninitialized_n) {
-//   nntrainer::Tensor target;
-//   nntrainer::Tensor original = randUniform(3, 1, 2, 3, -1.0f, 1.0f);
-//   EXPECT_THROW(target.fill(original, false), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, fill_different_dimension_n) {
-//   nntrainer::Tensor target(3, 1, 3, 2);
-//   nntrainer::Tensor original = randUniform(3, 1, 2, 3, -1.0f, 1.0f);
-//   EXPECT_THROW(target.fill(original, false), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, DISABLED_fill_non_contiguous_n) {
-//   /// there is no way to make non contiguous tensor publicily yet
-//   EXPECT_TRUE(false);
-// }
-
-// TEST(nntrainer_Tensor, DISABLED_fill_different_buffer_size_n) {
-//   /// there is no way to make same dimension, diffrent buffersized tensor
-//   /// publicily yet
-//   EXPECT_TRUE(false);
-// }
-
-// TEST(nntrainer_Tensor, empty_01) {
-//   nntrainer::Tensor t;
-
-//   EXPECT_TRUE(t.empty());
-// }
-
-// TEST(nntrainer_Tensor, empty_02) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, false);
-
-//   EXPECT_FALSE(t.empty());
-// }
-
-// TEST(nntrainer_Tensor, empty_03) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, true);
-
-//   EXPECT_FALSE(t.empty());
-// }
-
-// TEST(nntrainer_Tensor, allocate_01_n) {
-//   nntrainer::Tensor t;
-//   EXPECT_FALSE(t.isAllocated());
-
-//   t.allocate();
-//   EXPECT_FALSE(t.isAllocated());
-// }
-
-// TEST(nntrainer_Tensor, allocate_02_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, false);
-//   EXPECT_FALSE(t.isAllocated());
-
-//   t.allocate();
-//   EXPECT_TRUE(t.isAllocated());
-// }
-
-// TEST(nntrainer_Tensor, allocate_03_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, true);
-//   EXPECT_TRUE(t.isAllocated());
-
-//   t.allocate();
-//   EXPECT_TRUE(t.isAllocated());
-// }
-
-// TEST(nntrainer_Tensor, initialize_01_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-
-//   nntrainer::Tensor golden(1, 2, 3, 4);
-//   golden.setValue(1);
-
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, initialize_02_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, true);
-
-//   nntrainer::Tensor golden(1, 2, 3, 4);
-//   golden.setValue(1);
-
-//   EXPECT_NE(golden, t);
-
-//   t.initialize(nntrainer::Tensor::Initializer::ONES);
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, initialize_03_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, false,
-//                       nntrainer::Tensor::Initializer::ONES);
-//   t.allocate();
-
-//   nntrainer::Tensor golden(1, 2, 3, 4);
-//   golden.setValue(1);
-
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, initialize_04_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, false);
-//   t.initialize(nntrainer::Tensor::Initializer::ONES);
-//   t.allocate();
-
-//   nntrainer::Tensor golden(1, 2, 3, 4);
-//   golden.setValue(1);
-
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, initialize_05_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, false);
-//   t.allocate();
-
-//   nntrainer::Tensor golden(1, 2, 3, 4);
-//   golden.setValue(1.f);
-
-//   /**
-//    * Ideally, it should be NE, but it can be equal due to no initialization
-//    * EXPECT_NE(golden, t);
-//    */
-
-//   t.initialize(nntrainer::Tensor::Initializer::ONES);
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, initialize_06_n) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-//   nntrainer::Tensor golden({1, 2, 3, 4}, true,
-//                            nntrainer::Tensor::Initializer::ZEROS);
-
-//   EXPECT_NE(golden, t);
-
-//   golden.initialize(nntrainer::Tensor::Initializer::ONES);
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, initialize_07_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-
-//   nntrainer::Tensor golden(1, 2, 3, 4);
-//   golden.setValue(1);
-
-//   EXPECT_EQ(golden, t);
-
-//   t.setValue(0, 0, 0, 0, 0);
-//   t.setValue(0, 0, 0, t.size() - 1, 0);
-//   EXPECT_NE(golden, t);
-
-//   t.initialize();
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, initialize_08_p) {
-//   nntrainer::Tensor t({1, 2, 3, 4}, true, nntrainer::Tensor::Initializer::ONES);
-
-//   nntrainer::Tensor golden(1, 2, 3, 4, nntrainer::Tformat::NCHW, nntrainer::DataType::FP32);
-//   golden.setValue(1);
-//   EXPECT_EQ(golden, t);
-
-//   t.initialize(nntrainer::Tensor::Initializer::HE_NORMAL);
-//   EXPECT_NE(golden, t);
-
-
-//   t.initialize();
-//   EXPECT_NE(golden, t);
-
-//   t.initialize(nntrainer::Tensor::Initializer::ONES);
-//   EXPECT_EQ(golden, t);
-
-//   t.initialize();
-//   EXPECT_EQ(golden, t);
-// }
-
-// TEST(nntrainer_Tensor, split_01_p) {
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(3);
-//     {
-//       __fp16 answer_data[] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
-//                              10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
-//                              20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
-//                              30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
-//       answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
-//                              50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
-//                              60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
-//                              70, 71, 72, 73, 74, 75, 76, 77, 78, 79};
-//       answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-//                              90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-//                              100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-//                              110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-//       answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-//     }
-//     EXPECT_EQ(t.split(3, 0), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(2);
-//     {
-//       __fp16 answer_data[] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11,
-//                              12, 13, 14, 15, 16, 17, 18, 19, 40, 41, 42, 43,
-//                              44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
-//                              56, 57, 58, 59, 80, 81, 82, 83, 84, 85, 86, 87,
-//                              88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99};
-//       answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-//                              30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
-//                              60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-//                              70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
-//                              100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-//                              110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-//     }
-//     EXPECT_EQ(t.split(2, 1), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(2);
-//     {
-//       __fp16 answer_data[] = {
-//         0,  1,  2,  3,  4,  5,   6,   7,   8,   9,   20,  21,  22,  23,  24,
-//         25, 26, 27, 28, 29, 40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
-//         60, 61, 62, 63, 64, 65,  66,  67,  68,  69,  80,  81,  82,  83,  84,
-//         85, 86, 87, 88, 89, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {
-//         10, 11, 12, 13, 14, 15,  16,  17,  18,  19,  30,  31,  32,  33,  34,
-//         35, 36, 37, 38, 39, 50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-//         70, 71, 72, 73, 74, 75,  76,  77,  78,  79,  90,  91,  92,  93,  94,
-//         95, 96, 97, 98, 99, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-//     }
-//     EXPECT_EQ(t.split(2, 2), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(5);
-//     {
-//       __fp16 answer_data[] = {0,  5,  10, 15, 20,  25,  30,  35,
-//                              40, 45, 50, 55, 60,  65,  70,  75,
-//                              80, 85, 90, 95, 100, 105, 110, 115};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {1,  6,  11, 16, 21,  26,  31,  36,
-//                              41, 46, 51, 56, 61,  66,  71,  76,
-//                              81, 86, 91, 96, 101, 106, 111, 116};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {2,  7,  12, 17, 22,  27,  32,  37,
-//                              42, 47, 52, 57, 62,  67,  72,  77,
-//                              82, 87, 92, 97, 102, 107, 112, 117};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {3,  8,  13, 18, 23,  28,  33,  38,
-//                              43, 48, 53, 58, 63,  68,  73,  78,
-//                              83, 88, 93, 98, 103, 108, 113, 118};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {4,  9,  14, 19, 24,  29,  34,  39,
-//                              44, 49, 54, 59, 64,  69,  74,  79,
-//                              84, 89, 94, 99, 104, 109, 114, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     EXPECT_EQ(t.split(5, 3), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(1, 1, 4, 6);
-//     nntrainer::Tensor t = ranged(1, 1, 4, 6);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(2);
-//     {
-//       __fp16 answer_data[] = {0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20};
-//       answer.emplace_back(ml::train::TensorDim{1, 1, 4, 3}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {3, 4, 5, 9, 10, 11, 15, 16, 17, 21, 22, 23};
-//       answer.emplace_back(ml::train::TensorDim{1, 1, 4, 3}, answer_data);
-//     }
-//     EXPECT_EQ(t.split(2, 3), answer);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, split_02_n) {
-//   nntrainer::Tensor t(1, 1, 1, 1);
-//   EXPECT_THROW(t.split(0, 0), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, split_03_n) {
-//   nntrainer::Tensor t(3, 1, 1, 1);
-//   EXPECT_THROW(t.split(2, 0), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, split_04_p) {
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(2);
-//     {
-//       __fp16 answer_data[] = {
-//         0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
-//         16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-//         32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-//         48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-//         64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79};
-//       answer.emplace_back(ml::train::TensorDim{2, 2, 4, 5}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-//                              90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-//                              100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-//                              110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-//       answer.emplace_back(ml::train::TensorDim{1, 2, 4, 5}, answer_data);
-//     }
-//     EXPECT_EQ(t.split({2, 1}, 0), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(2);
-//     {
-//       __fp16 answer_data[] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11,
-//                              12, 13, 14, 15, 16, 17, 18, 19, 40, 41, 42, 43,
-//                              44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
-//                              56, 57, 58, 59, 80, 81, 82, 83, 84, 85, 86, 87,
-//                              88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99};
-//       answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-//                              30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
-//                              60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
-//                              70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
-//                              100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-//                              110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 1, 4, 5}, answer_data);
-//     }
-//     EXPECT_EQ(t.split({1, 1}, 1), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(2);
-//     {
-//       __fp16 answer_data[] = {
-//         0,  1,  2,  3,  4,  5,   6,   7,   8,   9,   20,  21,  22,  23,  24,
-//         25, 26, 27, 28, 29, 40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
-//         60, 61, 62, 63, 64, 65,  66,  67,  68,  69,  80,  81,  82,  83,  84,
-//         85, 86, 87, 88, 89, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {
-//         10, 11, 12, 13, 14, 15,  16,  17,  18,  19,  30,  31,  32,  33,  34,
-//         35, 36, 37, 38, 39, 50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-//         70, 71, 72, 73, 74, 75,  76,  77,  78,  79,  90,  91,  92,  93,  94,
-//         95, 96, 97, 98, 99, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 2, 5}, answer_data);
-//     }
-//     EXPECT_EQ(t.split({2, 2}, 2), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(3);
-//     {
-//       __fp16 answer_data[] = {0,  5,  10, 15, 20,  25,  30,  35,
-//                              40, 45, 50, 55, 60,  65,  70,  75,
-//                              80, 85, 90, 95, 100, 105, 110, 115};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {
-//         1,   2,   3,   6,   7,   8,   11,  12,  13,  16,  17,  18, 21, 22, 23,
-//         26,  27,  28,  31,  32,  33,  36,  37,  38,  41,  42,  43, 46, 47, 48,
-//         51,  52,  53,  56,  57,  58,  61,  62,  63,  66,  67,  68, 71, 72, 73,
-//         76,  77,  78,  81,  82,  83,  86,  87,  88,  91,  92,  93, 96, 97, 98,
-//         101, 102, 103, 106, 107, 108, 111, 112, 113, 116, 117, 118};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 3}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {4,  9,  14, 19, 24,  29,  34,  39,
-//                              44, 49, 54, 59, 64,  69,  74,  79,
-//                              84, 89, 94, 99, 104, 109, 114, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     EXPECT_EQ(t.split({1, 3, 1}, 3), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(3);
-//     {
-//       __fp16 answer_data[] = {
-//         0,  1,  5,  6,  10, 11, 15, 16, 20,  21,  25,  26,  30,  31,  35,  36,
-//         40, 41, 45, 46, 50, 51, 55, 56, 60,  61,  65,  66,  70,  71,  75,  76,
-//         80, 81, 85, 86, 90, 91, 95, 96, 100, 101, 105, 106, 110, 111, 115, 116};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 2}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {
-//         2,  3,  7,  8,  12, 13, 17, 18, 22,  23,  27,  28,  32,  33,  37,  38,
-//         42, 43, 47, 48, 52, 53, 57, 58, 62,  63,  67,  68,  72,  73,  77,  78,
-//         82, 83, 87, 88, 92, 93, 97, 98, 102, 103, 107, 108, 112, 113, 117, 118};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 2}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {4,  9,  14, 19, 24,  29,  34,  39,
-//                              44, 49, 54, 59, 64,  69,  74,  79,
-//                              84, 89, 94, 99, 104, 109, 114, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 1}, answer_data);
-//     }
-//     EXPECT_EQ(t.split({2, 2, 1}, 3), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(3, 2, 4, 5);
-//     nntrainer::Tensor t = ranged(3, 2, 4, 5);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(2);
-//     {
-//       __fp16 answer_data[] = {
-//         0,  1,  5,  6,  10, 11, 15, 16, 20,  21,  25,  26,  30,  31,  35,  36,
-//         40, 41, 45, 46, 50, 51, 55, 56, 60,  61,  65,  66,  70,  71,  75,  76,
-//         80, 81, 85, 86, 90, 91, 95, 96, 100, 101, 105, 106, 110, 111, 115, 116};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 2}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {
-//         2,   3,   4,   7,   8,   9,   12,  13,  14,  17,  18,  19, 22, 23, 24,
-//         27,  28,  29,  32,  33,  34,  37,  38,  39,  42,  43,  44, 47, 48, 49,
-//         52,  53,  54,  57,  58,  59,  62,  63,  64,  67,  68,  69, 72, 73, 74,
-//         77,  78,  79,  82,  83,  84,  87,  88,  89,  92,  93,  94, 97, 98, 99,
-//         102, 103, 104, 107, 108, 109, 112, 113, 114, 117, 118, 119};
-//       answer.emplace_back(ml::train::TensorDim{3, 2, 4, 3}, answer_data);
-//     }
-//     EXPECT_EQ(t.split({2, 3}, 3), answer);
-//   }
-//   {
-//     nntrainer::TensorDim ref_dim(1, 1, 4, 6);
-//     nntrainer::Tensor t = ranged(1, 1, 4, 6);
-//     std::vector<nntrainer::Tensor> answer;
-//     answer.reserve(3);
-//     {
-//       __fp16 answer_data[] = {0, 6, 12, 18};
-//       answer.emplace_back(ml::train::TensorDim{1, 1, 4, 1}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21};
-//       answer.emplace_back(ml::train::TensorDim{1, 1, 4, 3}, answer_data);
-//     }
-//     {
-//       __fp16 answer_data[] = {4, 5, 10, 11, 16, 17, 22, 23};
-//       answer.emplace_back(ml::train::TensorDim{1, 1, 4, 2}, answer_data);
-//     }
-//     EXPECT_EQ(t.split({1, 3, 2}, 3), answer);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, split_05_n) {
-//   nntrainer::Tensor t(3, 1, 1, 1);
-//   EXPECT_THROW(t.split({1, 1}, 0), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, split_06_n) {
-//   nntrainer::Tensor t(3, 1, 1, 1);
-//   EXPECT_THROW(t.split({2, 0, 1}, 0), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, split_07_n) {
-//   nntrainer::Tensor t(3, 1, 1, 1);
-//   EXPECT_THROW(t.split({}, 0), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, cat_01_p) {
-//   {
-//     std::vector<nntrainer::Tensor> inputs;
-//     inputs.reserve(2);
-//     inputs.emplace_back(ranged(2, 1, 1, 2));
-//     inputs.emplace_back(ranged(2, 2, 1, 2));
-//     __fp16 answer_data[] = {0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 6, 7};
-//     nntrainer::Tensor answer(ml::train::TensorDim{2, 3, 1, 2}, answer_data);
-//     EXPECT_EQ(nntrainer::Tensor::cat(inputs, 1), answer);
-//   }
-//   {
-//     std::vector<nntrainer::Tensor> inputs;
-//     inputs.reserve(2);
-//     inputs.emplace_back(ranged(3, 2, 4, 5));
-//     inputs.emplace_back(ranged(2, 2, 4, 5));
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
-//       15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-//       30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
-//       45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-//       60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
-//       75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-//       90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
-//       105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
-//       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
-//       15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-//       30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
-//       45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
-//       60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
-//       75,  76,  77,  78,  79};
-//     nntrainer::Tensor answer(ml::train::TensorDim{5, 2, 4, 5}, answer_data);
-//     EXPECT_EQ(nntrainer::Tensor::cat(inputs, 0), answer);
-//   }
-//   {
-//     std::vector<nntrainer::Tensor> inputs;
-//     inputs.reserve(2);
-//     inputs.emplace_back(ranged(3, 3, 4, 5));
-//     inputs.emplace_back(ranged(3, 2, 4, 5));
-//     __fp16 answer_data[] = {
-//       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,
-//       14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,
-//       28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-//       42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-//       56,  57,  58,  59,  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
-//       10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,
-//       24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,
-//       38,  39,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,
-//       72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
-//       86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-//       100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
-//       114, 115, 116, 117, 118, 119, 40,  41,  42,  43,  44,  45,  46,  47,
-//       48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,
-//       62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
-//       76,  77,  78,  79,  120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
-//       130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
-//       144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
-//       158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
-//       172, 173, 174, 175, 176, 177, 178, 179, 80,  81,  82,  83,  84,  85,
-//       86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-//       100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
-//       114, 115, 116, 117, 118, 119};
-//     nntrainer::Tensor answer(ml::train::TensorDim{3, 5, 4, 5}, answer_data);
-//     EXPECT_EQ(nntrainer::Tensor::cat(inputs, 1), answer);
-//   }
-//   {
-//     std::vector<nntrainer::Tensor> inputs;
-//     inputs.reserve(2);
-//     inputs.emplace_back(ranged(3, 2, 1, 5));
-//     inputs.emplace_back(ranged(3, 2, 2, 5));
-//     __fp16 answer_data[] = {
-//       0,  1,  2,  3,  4,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  5,  6,  7,
-//       8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 11, 12, 13, 14, 20,
-//       21, 22, 23, 24, 25, 26, 27, 28, 29, 15, 16, 17, 18, 19, 30, 31, 32, 33,
-//       34, 35, 36, 37, 38, 39, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44, 45, 46,
-//       47, 48, 49, 25, 26, 27, 28, 29, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
-//     nntrainer::Tensor answer(ml::train::TensorDim{3, 2, 3, 5}, answer_data);
-//     EXPECT_EQ(nntrainer::Tensor::cat(inputs, 2), answer);
-//   }
-//   {
-//     std::vector<nntrainer::Tensor> inputs;
-//     inputs.reserve(3);
-//     inputs.emplace_back(ranged(3, 2, 4, 1));
-//     inputs.emplace_back(ranged(3, 2, 4, 3));
-//     inputs.emplace_back(ranged(3, 2, 4, 2));
-//     __fp16 answer_data[] = {
-//       0,  0,  1,  2,  0,  1,  1,  3,  4,  5,  2,  3,  2,  6,  7,  8,  4,  5,
-//       3,  9,  10, 11, 6,  7,  4,  12, 13, 14, 8,  9,  5,  15, 16, 17, 10, 11,
-//       6,  18, 19, 20, 12, 13, 7,  21, 22, 23, 14, 15, 8,  24, 25, 26, 16, 17,
-//       9,  27, 28, 29, 18, 19, 10, 30, 31, 32, 20, 21, 11, 33, 34, 35, 22, 23,
-//       12, 36, 37, 38, 24, 25, 13, 39, 40, 41, 26, 27, 14, 42, 43, 44, 28, 29,
-//       15, 45, 46, 47, 30, 31, 16, 48, 49, 50, 32, 33, 17, 51, 52, 53, 34, 35,
-//       18, 54, 55, 56, 36, 37, 19, 57, 58, 59, 38, 39, 20, 60, 61, 62, 40, 41,
-//       21, 63, 64, 65, 42, 43, 22, 66, 67, 68, 44, 45, 23, 69, 70, 71, 46, 47};
-//     nntrainer::Tensor answer(ml::train::TensorDim{3, 2, 4, 6}, answer_data);
-//     EXPECT_EQ(nntrainer::Tensor::cat(inputs, 3), answer);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, cat_02_n) {
-//   {
-//     std::vector<nntrainer::Tensor> inputs;
-//     inputs.reserve(2);
-//     inputs.emplace_back(nntrainer::Tensor(2, 1, 1, 2));
-//     inputs.emplace_back(nntrainer::Tensor(2, 2, 1, 2));
-//     EXPECT_THROW(nntrainer::Tensor::cat(inputs, 2), std::invalid_argument);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, zoneout_mask_01_n) {
-//   const __fp16 zoneout_rate = 0.3f;
-//   nntrainer::Tensor t(10, 10, 10, 10);
-//   nntrainer::Tensor opposite(20, 20, 20, 20);
-//   EXPECT_THROW(t.zoneout_mask(opposite, zoneout_rate), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, zoneout_mask_02_p) {
-//   const __fp16 zoneout_rate = 0.3f;
-//   nntrainer::Tensor t(10, 10, 10, 10);
-//   nntrainer::Tensor opposite = t.zoneout_mask(zoneout_rate);
-//   constexpr __fp16 epsilon = 1e-3;
-
-//   EXPECT_EQ(t.size(), opposite.size());
-
-//   auto is_near = [epsilon](__fp16 val1, __fp16 val2) {
-//     return val2 - epsilon < val1 && val1 < val2 + epsilon;
-//   };
-
-//   for (unsigned int i = 0; i < opposite.size(); ++i) {
-//     if (is_near(opposite.getValue(i), 0.0f)) {
-//       EXPECT_NEAR(t.getValue(i), 1.0f, epsilon);
-//     } else if (is_near(opposite.getValue(i), 1.0f)) {
-//       EXPECT_NEAR(t.getValue(i), 0.0f, epsilon);
-//     } else {
-//       FAIL() << "This should not be happen";
-//     }
-//   }
-// }
-
-// TEST(nntrainer_Tensor, zoneout_mask_03_p) {
-//   const __fp16 zoneout_rate = 0.3f;
-//   nntrainer::Tensor t(10, 10, 100, 100);
-//   nntrainer::Tensor opposite = t.zoneout_mask(zoneout_rate);
-//   constexpr __fp16 epsilon = 1e-3;
-
-//   auto is_near = [epsilon](__fp16 val1, __fp16 val2) {
-//     return val2 - epsilon < val1 && val1 < val2 + epsilon;
-//   };
-//   auto percentage = [](unsigned int dividend, unsigned int divisor) {
-//     return (__fp16)dividend / (__fp16)divisor;
-//   };
-
-//   {
-//     unsigned int zeros = 0;
-//     unsigned int ones = 0;
-//     for (unsigned int i = 0; i < opposite.size(); ++i) {
-//       if (is_near(opposite.getValue(i), 0.0f)) {
-//         ++zeros;
-//       } else if (is_near(opposite.getValue(i), 1.0f)) {
-//         ++ones;
-//       } else {
-//         FAIL() << "This should not be happen";
-//       }
-//     }
-//     EXPECT_NEAR(percentage(zeros, opposite.size()), 1.0f - zoneout_rate,
-//                 epsilon);
-
-//     // main test
-//     EXPECT_NEAR(percentage(ones, opposite.size()), zoneout_rate, epsilon);
-//   }
-
-//   {
-//     unsigned int zeros = 0;
-//     unsigned int ones = 0;
-//     for (unsigned int i = 0; i < t.size(); ++i) {
-//       if (is_near(t.getValue(i), 0.0f)) {
-//         ++zeros;
-//       } else if (is_near(t.getValue(i), 1.0f)) {
-//         ++ones;
-//       } else {
-//         FAIL() << "This should not be happen";
-//       }
-//     }
-//     EXPECT_NEAR(percentage(zeros, t.size()), zoneout_rate, epsilon);
-
-//     // main test
-//     EXPECT_NEAR(percentage(ones, t.size()), 1.0f - zoneout_rate, epsilon);
-//   }
-// }
-
-// TEST(nntrainer_Tensor, zoneout_mask_04_n) {
-//   const __fp16 zoneout_rate = 0.3f;
-//   nntrainer::Tensor t(10, 10, 100, 100);
-//   nntrainer::Tensor opposite = t.zoneout_mask(zoneout_rate);
-//   constexpr __fp16 epsilon = 1e-3;
-
-//   auto is_near = [epsilon](__fp16 val1, __fp16 val2) {
-//     return val2 - epsilon < val1 && val1 < val2 + epsilon;
-//   };
-//   auto percentage = [](unsigned int dividend, unsigned int divisor) {
-//     return (__fp16)dividend / (__fp16)divisor;
-//   };
-
-//   {
-//     unsigned int zeros = 0;
-//     unsigned int ones = 0;
-//     for (unsigned int i = 0; i < opposite.size(); ++i) {
-//       if (is_near(opposite.getValue(i), 0.0f)) {
-//         ++zeros;
-//       } else if (is_near(opposite.getValue(i), 1.0f)) {
-//         ++ones;
-//       } else {
-//         FAIL() << "This should not be happen";
-//       }
-//     }
-//     EXPECT_FALSE(
-//       is_near(percentage(ones, opposite.size()), 1.0f - zoneout_rate));
-//   }
-
-//   {
-//     unsigned int zeros = 0;
-//     unsigned int ones = 0;
-//     for (unsigned int i = 0; i < t.size(); ++i) {
-//       if (is_near(t.getValue(i), 0.0f)) {
-//         ++zeros;
-//       } else if (is_near(t.getValue(i), 1.0f)) {
-//         ++ones;
-//       } else {
-//         FAIL() << "This should not be happen";
-//       }
-//     }
-//     EXPECT_FALSE(is_near(percentage(ones, t.size()), zoneout_rate));
-//   }
-// }
-
-// TEST(nntrainer_Tensor, TensorMap_p) {
-//   __fp16 dat[] = {1, 2, 3};
-
-//   {
-//     nntrainer::Tensor a = nntrainer::Tensor::Map(dat, 3 * sizeof(__fp16), {3});
-//     /// check if a.getData() has same address with dat
-//     EXPECT_EQ(dat, a.getData());
-//     {
-//       /// check if b.getData() has same address with data
-//       nntrainer::Tensor b = a;
-//       EXPECT_EQ(dat, b.getData());
-//     }
-//   }
-//   /// check if dat is accessible after destruction of all the tensor
-//   EXPECT_FLOAT_EQ(dat[2], 3);
-// }
-
-// TEST(nntrainer_Tensor, TensorWrap_01_n) {
-//   __fp16 dat[] = {1, 2, 3};
-//   EXPECT_THROW(nntrainer::Tensor::Map(dat, 3, nntrainer::TensorDim({})),
-//                std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, TensorWrap_02_n) {
-//   __fp16 dat[] = {1, 2, 3};
-//   EXPECT_THROW(nntrainer::Tensor::Map(dat, 3, {4}), std::invalid_argument);
-// }
-
-// TEST(nntrainer_Tensor, TensorPaddedValue_p) {
-//   nntrainer::Tensor a = ranged(1, 1, 3, 3);
-//   __fp16 default_padded = -1;
-
-//   for (int i = 0; i < 5; ++i) {
-//     for (int j = 0; j < 5; ++j) {
-//       __fp16 expected = default_padded;
-//       if (1 <= i && i <= 3 && 1 <= j && j <= 3) {
-//         expected = (i - 1) * 3 + (j - 1);
-//       }
-//       __fp16 actual = a.getValuePaddedVirtual<__fp16>(0, 0, i, j, 1, 1, default_padded);
-//       EXPECT_FLOAT_EQ(actual, expected);
-//     }
-//   }
-// }
-
-// GTEST_API_ int main(int argc, char **argv) {
-//  int result = -1;
-
-//  try {
-  //   testing::InitGoogleTest(&argc, argv);
-  // } catch (...) {
-  //   std::cerr << "Error duing InitGoogleTest" << std::endl;
-  //   return 0;
-  // }
-
-  // try {
-  //   result = RUN_ALL_TESTS();
-//   } catch (...) {
-//     std::cerr << "Error duing RUN_ALL_TESTS()" << std::endl;
-//   }
-
-//   return result;
-// }
index 0846cc1..15d00d8 100644 (file)
@@ -37,7 +37,6 @@ test_target = [
   ['unittest_nntrainer_internal', []],
   ['unittest_nntrainer_lazy_tensor', []],
   ['unittest_nntrainer_tensor', []],
-  ['unittest_nntrainer_tensor_fp16', []],
   ['unittest_nntrainer_tensor_nhwc', []],
   ['unittest_util_func', []],
   ['unittest_nntrainer_modelfile', []],
@@ -53,6 +52,10 @@ test_target = [
   ['unittest_nntrainer_task', []],
 ]
 
+if get_option('enable-fp16')
+  test_target += [['unittest_nntrainer_tensor_fp16', []]]
+endif
+
 if get_option('enable-profile')
   if gmock_dep.version().version_compare('>=1.10.0')
     test_target += [['unittest_nntrainer_profiler', []]]
index f449ecc..20f8028 100644 (file)
@@ -395,8 +395,8 @@ TEST(TensorPool, allocate_deallocate_03_p) {
   EXPECT_TRUE(t2->isAllocated());
   EXPECT_TRUE(t3->isAllocated());
 
-  EXPECT_EQ(t1->getData(), t2->getData());
-  EXPECT_EQ(t1->getData(), t3->getData());
+  EXPECT_EQ(t1->getData<float>(), t2->getData<float>());
+  EXPECT_EQ(t1->getData<float>(), t3->getData<float>());
 
   EXPECT_NO_THROW(pool.deallocate());
   EXPECT_FALSE(t1->isAllocated());
@@ -441,11 +441,11 @@ TEST(TensorPool, validate_memory) {
  * @param t2 tensor2
  */
 static void testNoOverlap(nntrainer::Tensor *t1, nntrainer::Tensor *t2) {
-  char *t1_start = t1->getData<char>();
-  char *t1_end = t1_start + t1->bytes();
+  float *t1_start = t1->getData<float>();
+  float *t1_end = t1_start + t1->size();
 
-  char *t2_start = t2->getData<char>();
-  char *t2_end = t2_start + t2->bytes();
+  float *t2_start = t2->getData<float>();
+  float *t2_end = t2_start + t2->size();
 
   EXPECT_NE(t1_start, nullptr);
   EXPECT_NE(t2_start, nullptr);
@@ -460,11 +460,11 @@ static void testNoOverlap(nntrainer::Tensor *t1, nntrainer::Tensor *t2) {
  * @param t2 t2 tensor 2
  */
 static void testSubset(nntrainer::Tensor *t1, nntrainer::Tensor *t2) {
-  char *t1_start = t1->getData<char>();
-  char *t1_end = t1_start + t1->bytes();
+  float *t1_start = t1->getData<float>();
+  float *t1_end = t1_start + t1->size();
 
-  char *t2_start = t2->getData<char>();
-  char *t2_end = t2_start + t2->bytes();
+  float *t2_start = t2->getData<float>();
+  float *t2_end = t2_start + t2->size();
 
   EXPECT_NE(t1_start, nullptr);
   EXPECT_NE(t2_start, nullptr);
@@ -519,7 +519,7 @@ TEST(TensorPool, view_is_same_p) {
 
   EXPECT_NE(t1, t2);
   EXPECT_EQ(t1->getDim(), t2->getDim());
-  EXPECT_EQ(t1->getData(), t2->getData());
+  EXPECT_EQ(t1->getData<float>(), t2->getData<float>());
   pool.deallocate();
 }
 
@@ -593,8 +593,8 @@ TEST(TensorPool, view_of_placeholder_p) {
   pool.allocate();
 
   EXPECT_NE(t1, t2);
-  EXPECT_EQ(t1->getData(), nullptr);
-  EXPECT_EQ(t2->getData(), nullptr);
+  EXPECT_EQ(t1->getData<float>(), nullptr);
+  EXPECT_EQ(t2->getData<float>(), nullptr);
 
   /// t_original: 0 1 2 3 4 5 6 7 8 9
   /// t1        : 0 1 2 3 4 5 6 7 8 9
@@ -609,8 +609,8 @@ TEST(TensorPool, view_of_placeholder_p) {
   testSubset(t1, t3);
 
   EXPECT_EQ(*t1, t_original);
-  EXPECT_FLOAT_EQ(*t2->getData(), 1.0f);
-  EXPECT_FLOAT_EQ(*t3->getData(), 3.0f);
+  EXPECT_FLOAT_EQ(t2->getData<float>()[0], 1.0f);
+  EXPECT_FLOAT_EQ(t3->getData<float>()[0], 3.0f);
 
   pool.deallocate();
 }