From 5b5c64d334f33d0663603bcd4ee07747410f2cba Mon Sep 17 00:00:00 2001
From: Yifan Zhao <yifanz16@illinois.edu>
Date: Sat, 2 Nov 2019 23:02:47 -0500
Subject: [PATCH] Signature of runtime functions placed

---
 .../include/approxhpvm_img_runtime_utils.h    | 349 +++++++++---------
 .../include/img_tensor_runtime.h              |  39 +-
 .../tensor_runtime/src/img_tensor_runtime.cu  | 186 +++++-----
 3 files changed, 288 insertions(+), 286 deletions(-)

diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h
index dc5cddf8a2..b3bfb5a6d7 100644
--- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/approxhpvm_img_runtime_utils.h
@@ -6,233 +6,238 @@
 
 #include "img_tensor_runtime.h"
 
-
 // Utilities header for ApproxHPVM image runtime API (wrapper runtime API)
 
-void* handleTensorFftApproximationTuples(
-  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
-   void* input) {
+void *handleTensorFftApproximationTuples(
+    std::vector<std::pair<GPUNodeConfiguration::APPROX, int>> &approxTuples,
+    void *input) {
 
   if (approxTuples.size() == 1) {
     enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
     int param = approxTuples[0].second;
     switch (approx) {
-      case GPUNodeConfiguration::APPROX::FP32 :
-        {
-        void* t_out;
-        RC->resume_profiler();
-        t_out = tensorFft(input); //TODO: correct name here
-        RC->pause_profiler();
-        std::pair<double, double> pinfo = RC->get_time_energy();
-        RC->reset_profiler();
-        RC->addToCurrentIterationComputeTime("tensorFft", pinfo.first); // and here
-        RC->addToCurrentIterationComputeEnergy("tensorFft", pinfo.second); // and here
-        return t_out;
-        }
-      default :
-        CUSTOM_ASSERT(false && "Unknown approximation type");
-        ERROR("Unknown approximation type");
-        abort();
-      // TODO additional approx methods implemented here
-      }
-    } else if (approxTuples.size() == 2) {
-      ERROR("Currently unsupported case");
-      abort();
-    } else {
-      ERROR("Unsupported case");
+    case GPUNodeConfiguration::APPROX::FP32: {
+      void *t_out;
+      RC->resume_profiler();
+      t_out = tensorFft(input); // TODO: correct name here
+      RC->pause_profiler();
+      std::pair<double, double> pinfo = RC->get_time_energy();
+      RC->reset_profiler();
+      RC->addToCurrentIterationComputeTime(
+          "tensorFft", pinfo.first); // and here
+      RC->addToCurrentIterationComputeEnergy(
+          "tensorFft", pinfo.second); // and here
+      return t_out;
+    }
+    default:
+      CUSTOM_ASSERT(false && "Unknown approximation type");
+      ERROR("Unknown approximation type");
       abort();
+      // TODO additional approx methods implemented here
     }
+  } else if (approxTuples.size() == 2) {
+    ERROR("Currently unsupported case");
+    abort();
+  } else {
+    ERROR("Unsupported case");
+    abort();
+  }
   return NULL;
 }
 
-void* handleTensorReduceApproximationTuples(
-  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
-   void* input) {
+void *handleTensorReduceApproximationTuples(
+    std::vector<std::pair<GPUNodeConfiguration::APPROX, int>> &approxTuples,
+    void *input, size_t axis, void *func) {
   if (approxTuples.size() == 1) {
     enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
     int param = approxTuples[0].second;
     switch (approx) {
-      case GPUNodeConfiguration::APPROX::FP32 :
-        {
-        void* t_out;
-        RC->resume_profiler();
-        t_out = tensorReduce(input); //TODO: correct name here
-        RC->pause_profiler();
-        std::pair<double, double> pinfo = RC->get_time_energy();
-        RC->reset_profiler();
-        RC->addToCurrentIterationComputeTime("tensorReduce", pinfo.first); // and here
-        RC->addToCurrentIterationComputeEnergy("tensorReduce", pinfo.second); // and here
-        return t_out;
-        }
-      case GPUNodeConfiguration::APPROX::REDUCTION_SAMPLING :
-        {
-        void* t_out;
-        RC->resume_profiler();
-        t_out = tensorReductionSamplingReduce(input); //TODO: correct name here
-        RC->pause_profiler();
-        std::pair<double, double> pinfo = RC->get_time_energy();
-        RC->reset_profiler();
-        RC->addToCurrentIterationComputeTime("tensorReductionSamplingReduce",
-                                              pinfo.first); // and here
-        RC->addToCurrentIterationComputeEnergy("tensorReductionSamplingReduce",
-                                                pinfo.second); // and here
-        return t_out;
-        }
-      default :
-        CUSTOM_ASSERT(false && "Unknown approximation type");
-        ERROR("Unknown approximation type");
-        abort();
-      // TODO additional approx methods implemented here
-      }
-    } else if (approxTuples.size() == 2) {
-      ERROR("Currently unsupported case");
-      abort();
-    } else {
-      ERROR("Unsupported case");
+    case GPUNodeConfiguration::APPROX::FP32: {
+      void *t_out;
+      RC->resume_profiler();
+      t_out = tensorReduce(input, axis, func); // TODO: correct name here
+      RC->pause_profiler();
+      std::pair<double, double> pinfo = RC->get_time_energy();
+      RC->reset_profiler();
+      RC->addToCurrentIterationComputeTime(
+          "tensorReduce", pinfo.first); // and here
+      RC->addToCurrentIterationComputeEnergy(
+          "tensorReduce", pinfo.second); // and here
+      return t_out;
+    }
+    case GPUNodeConfiguration::APPROX::REDUCTION_SAMPLING: {
+      void *t_out;
+      RC->resume_profiler();
+      t_out = tensorReductionSamplingReduce(input, axis, func, param); // TODO: correct name here
+      RC->pause_profiler();
+      std::pair<double, double> pinfo = RC->get_time_energy();
+      RC->reset_profiler();
+      RC->addToCurrentIterationComputeTime(
+          "tensorReductionSamplingReduce",
+          pinfo.first); // and here
+      RC->addToCurrentIterationComputeEnergy(
+          "tensorReductionSamplingReduce",
+          pinfo.second); // and here
+      return t_out;
+    }
+    default:
+      CUSTOM_ASSERT(false && "Unknown approximation type");
+      ERROR("Unknown approximation type");
       abort();
+      // TODO additional approx methods implemented here
     }
+  } else if (approxTuples.size() == 2) {
+    ERROR("Currently unsupported case");
+    abort();
+  } else {
+    ERROR("Unsupported case");
+    abort();
+  }
   return NULL;
 }
 
-void* handleTensorProjectiveTApproximationTuples(
-  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
-   void* input) {
+void *handleTensorProjectiveTApproximationTuples(
+    std::vector<std::pair<GPUNodeConfiguration::APPROX, int>> &approxTuples,
+    void *input, void *transformation) {
   if (approxTuples.size() == 1) {
     enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
     int param = approxTuples[0].second;
     switch (approx) {
-      case GPUNodeConfiguration::APPROX::FP32 :
-        {
-        void* t_out;
-        RC->resume_profiler();
-        t_out = tensorProjectiveT(input); //TODO: correct name here
-        RC->pause_profiler();
-        std::pair<double, double> pinfo = RC->get_time_energy();
-        RC->reset_profiler();
-        RC->addToCurrentIterationComputeTime("tensorProjectiveT", pinfo.first); // and here
-        RC->addToCurrentIterationComputeEnergy("tensorProjectiveT", pinfo.second); // and here
-        return t_out;
-        }
-      default :
-        CUSTOM_ASSERT(false && "Unknown approximation type");
-        ERROR("Unknown approximation type");
-        abort();
-      // TODO additional approx methods implemented here
-      }
-    } else if (approxTuples.size() == 2) {
-      ERROR("Currently unsupported case");
-      abort();
-    } else {
-      ERROR("Unsupported case");
+    case GPUNodeConfiguration::APPROX::FP32: {
+      void *t_out;
+      RC->resume_profiler();
+      t_out = tensorProjectiveT(input, transformation); // TODO: correct name here
+      RC->pause_profiler();
+      std::pair<double, double> pinfo = RC->get_time_energy();
+      RC->reset_profiler();
+      RC->addToCurrentIterationComputeTime(
+          "tensorProjectiveT", pinfo.first); // and here
+      RC->addToCurrentIterationComputeEnergy(
+          "tensorProjectiveT", pinfo.second); // and here
+      return t_out;
+    }
+    default:
+      CUSTOM_ASSERT(false && "Unknown approximation type");
+      ERROR("Unknown approximation type");
       abort();
+      // TODO additional approx methods implemented here
     }
+  } else if (approxTuples.size() == 2) {
+    ERROR("Currently unsupported case");
+    abort();
+  } else {
+    ERROR("Unsupported case");
+    abort();
+  }
   return NULL;
 }
 
-void* handleTensorMap1ApproximationTuples(
-  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
-   void* input) {
+void *handleTensorMap1ApproximationTuples(
+    std::vector<std::pair<GPUNodeConfiguration::APPROX, int>> &approxTuples,
+    void *func, void *input) {
   if (approxTuples.size() == 1) {
     enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
     int param = approxTuples[0].second;
     switch (approx) {
-      case GPUNodeConfiguration::APPROX::FP32 :
-        {
-        void* t_out;
-        RC->resume_profiler();
-        t_out = tensorMap1(input); //TODO: correct name here
-        RC->pause_profiler();
-        std::pair<double, double> pinfo = RC->get_time_energy();
-        RC->reset_profiler();
-        RC->addToCurrentIterationComputeTime("tensorMap1", pinfo.first); // and here
-        RC->addToCurrentIterationComputeEnergy("tensorMap1", pinfo.second); // and here
-        return t_out;
-        }
-      default :
-        CUSTOM_ASSERT(false && "Unknown approximation type");
-        ERROR("Unknown approximation type");
-        abort();
-      // TODO additional approx methods implemented here
-      }
-    } else if (approxTuples.size() == 2) {
-      ERROR("Currently unsupported case");
-      abort();
-    } else {
-      ERROR("Unsupported case");
+    case GPUNodeConfiguration::APPROX::FP32: {
+      void *t_out;
+      RC->resume_profiler();
+      t_out = tensorMap1(func, input); // TODO: correct name here
+      RC->pause_profiler();
+      std::pair<double, double> pinfo = RC->get_time_energy();
+      RC->reset_profiler();
+      RC->addToCurrentIterationComputeTime(
+          "tensorMap1", pinfo.first); // and here
+      RC->addToCurrentIterationComputeEnergy(
+          "tensorMap1", pinfo.second); // and here
+      return t_out;
+    }
+    default:
+      CUSTOM_ASSERT(false && "Unknown approximation type");
+      ERROR("Unknown approximation type");
       abort();
+      // TODO additional approx methods implemented here
     }
+  } else if (approxTuples.size() == 2) {
+    ERROR("Currently unsupported case");
+    abort();
+  } else {
+    ERROR("Unsupported case");
+    abort();
+  }
   return NULL;
 }
 
-void* handleTensorMap2ApproximationTuples(
-  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
-   void* input) {
+void *handleTensorMap2ApproximationTuples(
+    std::vector<std::pair<GPUNodeConfiguration::APPROX, int>> &approxTuples,
+    void *func, void *input1, void *input2) {
   if (approxTuples.size() == 1) {
     enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
     int param = approxTuples[0].second;
     switch (approx) {
-      case GPUNodeConfiguration::APPROX::FP32 :
-        {
-        void* t_out;
-        RC->resume_profiler();
-        t_out = tensorMap2(input); //TODO: correct name here
-        RC->pause_profiler();
-        std::pair<double, double> pinfo = RC->get_time_energy();
-        RC->reset_profiler();
-        RC->addToCurrentIterationComputeTime("tensorMap2", pinfo.first); // and here
-        RC->addToCurrentIterationComputeEnergy("tensorMap2", pinfo.second); // and here
-        return t_out;
-        }
-      default :
-        CUSTOM_ASSERT(false && "Unknown approximation type");
-        ERROR("Unknown approximation type");
-        abort();
-      // TODO additional approx methods implemented here
-      }
-    } else if (approxTuples.size() == 2) {
-      ERROR("Currently unsupported case");
-      abort();
-    } else {
-      ERROR("Unsupported case");
+    case GPUNodeConfiguration::APPROX::FP32: {
+      void *t_out;
+      RC->resume_profiler();
+      t_out = tensorMap2(func, input1, input2); // TODO: correct name here
+      RC->pause_profiler();
+      std::pair<double, double> pinfo = RC->get_time_energy();
+      RC->reset_profiler();
+      RC->addToCurrentIterationComputeTime(
+          "tensorMap2", pinfo.first); // and here
+      RC->addToCurrentIterationComputeEnergy(
+          "tensorMap2", pinfo.second); // and here
+      return t_out;
+    }
+    default:
+      CUSTOM_ASSERT(false && "Unknown approximation type");
+      ERROR("Unknown approximation type");
       abort();
+      // TODO additional approx methods implemented here
     }
+  } else if (approxTuples.size() == 2) {
+    ERROR("Currently unsupported case");
+    abort();
+  } else {
+    ERROR("Unsupported case");
+    abort();
+  }
   return NULL;
 }
 
-void* handleTensorMap3ApproximationTuples(
-  std::vector< std::pair<GPUNodeConfiguration::APPROX, int> > &approxTuples,
-   void* input) {
+void *handleTensorMap3ApproximationTuples(
+    std::vector<std::pair<GPUNodeConfiguration::APPROX, int>> &approxTuples,
+    void *func, void *input1, void *input2, void *input3) {
   if (approxTuples.size() == 1) {
     enum GPUNodeConfiguration::APPROX approx = approxTuples[0].first;
     int param = approxTuples[0].second;
     switch (approx) {
-      case GPUNodeConfiguration::APPROX::FP32 :
-        {
-        void* t_out;
-        RC->resume_profiler();
-        t_out = tensorMap3(input); //TODO: correct name here
-        RC->pause_profiler();
-        std::pair<double, double> pinfo = RC->get_time_energy();
-        RC->reset_profiler();
-        RC->addToCurrentIterationComputeTime("tensorMap3", pinfo.first); // and here
-        RC->addToCurrentIterationComputeEnergy("tensorMap3", pinfo.second); // and here
-        return t_out;
-        }
-      default :
-        CUSTOM_ASSERT(false && "Unknown approximation type");
-        ERROR("Unknown approximation type");
-        abort();
-      // TODO additional approx methods implemented here
-      }
-    } else if (approxTuples.size() == 2) {
-      ERROR("Currently unsupported case");
-      abort();
-    } else {
-      ERROR("Unsupported case");
+    case GPUNodeConfiguration::APPROX::FP32: {
+      void *t_out;
+      RC->resume_profiler();
+      t_out = tensorMap3(func, input1, input2, input3); // TODO: correct name here
+      RC->pause_profiler();
+      std::pair<double, double> pinfo = RC->get_time_energy();
+      RC->reset_profiler();
+      RC->addToCurrentIterationComputeTime(
+          "tensorMap3", pinfo.first); // and here
+      RC->addToCurrentIterationComputeEnergy(
+          "tensorMap3", pinfo.second); // and here
+      return t_out;
+    }
+    default:
+      CUSTOM_ASSERT(false && "Unknown approximation type");
+      ERROR("Unknown approximation type");
       abort();
+      // TODO additional approx methods implemented here
     }
+  } else if (approxTuples.size() == 2) {
+    ERROR("Currently unsupported case");
+    abort();
+  } else {
+    ERROR("Unsupported case");
+    abort();
+  }
   return NULL;
 }
 
-
 #endif
diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h
index 9c098719e5..eae57400bd 100644
--- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/img_tensor_runtime.h
@@ -1,26 +1,33 @@
 #ifndef IMG_TENSOR_RUNTIME_H
 #define IMG_TENSOR_RUNTIME_H
 
+#include <cstddef>
+
 // ***                        Runtime declaration                        *** //
-void* tensorFft(void* input);
-void* tensorReduce(void* input);
-void* tensorReductionSamplingReduce(void* input);
-void* tensorProjectiveT(void* input);
-void* tensorMap1(void* input);
-void* tensorMap2(void* input);
-void* tensorMap3(void* input);
+void *tensorFft(void *input);
+void *tensorReduce(void *input, size_t axis, void *func);
+void *tensorReductionSamplingReduce(
+    void *input, size_t axis, void *func, int skip_level);
+void *tensorProjectiveT(void *input, void *transformation);
+void *tensorMap1(void *f, void *i);
+void *tensorMap2(void *f2, void *i1, void *i2);
+void *tensorMap3(void *f3, void *i1, void *i2, void *i3);
 
 // ***                      Wrapper API declaration                      *** //
-void* wrapper_tensorFft(const char* hpvm_node_id, void* input);
-void* wrapper_tensorReduce(const char* hpvm_node_id, void* input);
-void* wrapper_tensorProjectiveT(const char* hpvm_node_id, void* input);
-void* wrapper_tensorMap1(const char* hpvm_node_id, void* input);
-void* wrapper_tensorMap2(const char* hpvm_node_id, void* input);
-void* wrapper_tensorMap3(const char* hpvm_node_id, void* input);
+void *wrapper_tensorFft(const char *hpvm_node_id, void *input);
+void *wrapper_tensorReduce(
+    const char *hpvm_node_id, void *input, size_t axis, void *func);
+void *wrapper_tensorProjectiveT(
+    const char *hpvm_node_id, void *input, void *transformation);
+void *wrapper_tensorMap1(const char *hpvm_node_id, void *func, void *input);
+void *wrapper_tensorMap2(
+    const char *hpvm_node_id, void *func, void *input1, void *input2);
+void *wrapper_tensorMap3(
+    const char *hpvm_node_id, void *func, void *input1, void *input2,
+    void *input3);
 
 // Tentative
-void* wrapper_tensorStencil(const char* hpvm_node_id, void* input);
-void* wrapper_tensorCosineT(const char* hpvm_node_id, void* input);
-
+void *wrapper_tensorStencil(const char *hpvm_node_id, void *input);
+void *wrapper_tensorCosineT(const char *hpvm_node_id, void *input);
 
 #endif
diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu
index 0460e490fd..5776e5c385 100644
--- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/img_tensor_runtime.cu
@@ -1,137 +1,127 @@
+#include "../include/approxhpvm_img_runtime_utils.h"
 #include "../include/debug.h"
 #include "../include/img_tensor_runtime.h"
-#include "../include/approxhpvm_img_runtime_utils.h" 
 
 // ***                       Runtime implementation                      *** //
-void* tensorFft(void* input) {
-
-}
-
-void* tensorReduce(void* input) {
-
-}
-
-void* tensorReductionSamplingReduce(void* input) {
-
-}
-
-void* tensorProjectiveT(void* input) {
-
-}
-
-void* tensorMap1(void* input) {
-
-}
-
-void* tensorMap2(void* input) {
-
-}
-
-void* tensorMap3(void* input) {
-
-}
-
+void *tensorFft(void *input) {}
+void *tensorReduce(void *input, size_t axis, void *func) {}
+void *tensorReductionSamplingReduce(
+    void *input, size_t axis, void *func, int skip_level) {}
+void *tensorProjectiveT(void *input, void *transformation) {}
+void *tensorMap1(void *f, void *i) {}
+void *tensorMap2(void *f2, void *i1, void *i2) {}
+void *tensorMap3(void *f3, void *i1, void *i2, void *i3) {}
 
 // ***                     Wrapper API implementation                    *** //
 
-void* wrapper_tensorFft(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorFft(const char *hpvm_node_id, void *input) {
   GPUNodeConfiguration *GPUConf =
-    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
-  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
-                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
-                                                 int> > > > &ApproxChoices =
-    GPUConf->getApproxChoices();
+      (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector<std::pair<
+      GPUNodeConfiguration::TENSOR_OP,
+      std::vector<std::pair<GPUNodeConfiguration::APPROX, int>>>>
+      &ApproxChoices = GPUConf->getApproxChoices();
   // Approximation choices must be for a fft operation
-  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
-         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::FFT &&
-         "Invalid configuration generated for tensor fft wrapper operation");
-  return handleTensorFftApproximationTuples(ApproxChoices[0].second,
-                                            input);
+  CUSTOM_ASSERT(
+      ApproxChoices.size() == 1 &&
+      ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::FFT &&
+      "Invalid configuration generated for tensor fft wrapper operation");
+  return handleTensorFftApproximationTuples(ApproxChoices[0].second, input);
 }
 
-void* wrapper_tensorReduce(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorReduce(
+    const char *hpvm_node_id, void *input, size_t axis, void *func) {
   GPUNodeConfiguration *GPUConf =
-    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
-  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
-                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
-                                                 int> > > > &ApproxChoices =
-    GPUConf->getApproxChoices();
+      (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector<std::pair<
+      GPUNodeConfiguration::TENSOR_OP,
+      std::vector<std::pair<GPUNodeConfiguration::APPROX, int>>>>
+      &ApproxChoices = GPUConf->getApproxChoices();
   // Approximation choices must be for a reduce operation
-  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
-         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::REDUCE &&
-         "Invalid configuration generated for tensor reduce wrapper operation");
-  return handleTensorReduceApproximationTuples(ApproxChoices[0].second,
-                                            input);
+  CUSTOM_ASSERT(
+      ApproxChoices.size() == 1 &&
+      ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::REDUCE &&
+      "Invalid configuration generated for tensor reduce wrapper operation");
+  return handleTensorReduceApproximationTuples(
+      ApproxChoices[0].second, input, axis, func);
 }
 
-void* wrapper_tensorProjectiveT(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorProjectiveT(
+    const char *hpvm_node_id, void *input, void *transformation) {
   GPUNodeConfiguration *GPUConf =
-    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
-  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
-                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
-                                                 int> > > > &ApproxChoices =
-    GPUConf->getApproxChoices();
+      (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector<std::pair<
+      GPUNodeConfiguration::TENSOR_OP,
+      std::vector<std::pair<GPUNodeConfiguration::APPROX, int>>>>
+      &ApproxChoices = GPUConf->getApproxChoices();
   // Approximation choices must be for a projectiveT operation
-  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
-         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::PROJECTIVE_T &&
-         "Invalid configuration generated for tensor projectiveT wrapper operation");
-  return handleTensorProjectiveTApproximationTuples(ApproxChoices[0].second,
-                                            input);
+  CUSTOM_ASSERT(
+      ApproxChoices.size() == 1 &&
+      ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::PROJECTIVE_T &&
+      "Invalid configuration generated for tensor projectiveT "
+      "wrapper operation");
+  return handleTensorProjectiveTApproximationTuples(
+      ApproxChoices[0].second, input, transformation);
 }
 
-void* wrapper_tensorMap1(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorMap1(const char *hpvm_node_id, void *func, void *input) {
   GPUNodeConfiguration *GPUConf =
-    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
-  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
-                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
-                                                 int> > > > &ApproxChoices =
-    GPUConf->getApproxChoices();
+      (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector<std::pair<
+      GPUNodeConfiguration::TENSOR_OP,
+      std::vector<std::pair<GPUNodeConfiguration::APPROX, int>>>>
+      &ApproxChoices = GPUConf->getApproxChoices();
   // Approximation choices must be for a map1 operation
-  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
-         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP1 &&
-         "Invalid configuration generated for tensor map1 wrapper operation");
-  return handleTensorMap1ApproximationTuples(ApproxChoices[0].second,
-                                            input);
+  CUSTOM_ASSERT(
+      ApproxChoices.size() == 1 &&
+      ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP1 &&
+      "Invalid configuration generated for tensor map1 wrapper operation");
+  return handleTensorMap1ApproximationTuples(
+      ApproxChoices[0].second, func, input);
 }
 
-void* wrapper_tensorMap2(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorMap2(
+    const char *hpvm_node_id, void *func, void *input1, void *input2) {
   GPUNodeConfiguration *GPUConf =
-    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
-  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
-                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
-                                                 int> > > > &ApproxChoices =
-    GPUConf->getApproxChoices();
+      (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector<std::pair<
+      GPUNodeConfiguration::TENSOR_OP,
+      std::vector<std::pair<GPUNodeConfiguration::APPROX, int>>>>
+      &ApproxChoices = GPUConf->getApproxChoices();
   // Approximation choices must be for a map2 operation
-  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
-         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP2 &&
-         "Invalid configuration generated for tensor map2 wrapper operation");
-  return handleTensorMap2ApproximationTuples(ApproxChoices[0].second,
-                                            input);
+  CUSTOM_ASSERT(
+      ApproxChoices.size() == 1 &&
+      ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP2 &&
+      "Invalid configuration generated for tensor map2 wrapper operation");
+  return handleTensorMap2ApproximationTuples(
+      ApproxChoices[0].second, func, input1, input2);
 }
 
-void* wrapper_tensorMap3(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorMap3(
+    const char *hpvm_node_id, void *func, void *input1, void *input2,
+    void *input3) {
   GPUNodeConfiguration *GPUConf =
-    (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
-  std::vector< std::pair< GPUNodeConfiguration::TENSOR_OP,
-                          std::vector< std::pair<GPUNodeConfiguration::APPROX,
-                                                 int> > > > &ApproxChoices =
-    GPUConf->getApproxChoices();
+      (GPUNodeConfiguration *)RC->getNodeConfiguration(hpvm_node_id);
+  std::vector<std::pair<
+      GPUNodeConfiguration::TENSOR_OP,
+      std::vector<std::pair<GPUNodeConfiguration::APPROX, int>>>>
+      &ApproxChoices = GPUConf->getApproxChoices();
   // Approximation choices must be for a map3 operation
-  CUSTOM_ASSERT(ApproxChoices.size() == 1 &&
-         ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP3 &&
-         "Invalid configuration generated for tensor map3 wrapper operation");
-  return handleTensorMap3ApproximationTuples(ApproxChoices[0].second,
-                                            input);
+  CUSTOM_ASSERT(
+      ApproxChoices.size() == 1 &&
+      ApproxChoices[0].first == GPUNodeConfiguration::TENSOR_OP::MAP3 &&
+      "Invalid configuration generated for tensor map3 wrapper operation");
+  return handleTensorMap3ApproximationTuples(
+      ApproxChoices[0].second, func, input1, input2, input3);
 }
 
 // Tentative
-void* wrapper_tensorStencil(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorStencil(const char *hpvm_node_id, void *input) {
   ERROR("Stencil operation currently unsupported.\n");
   abort();
 }
 
-void* wrapper_tensorCosineT(const char* hpvm_node_id, void* input) {
+void *wrapper_tensorCosineT(const char *hpvm_node_id, void *input) {
   ERROR("CosineT operation currently unsupported.\n");
   abort();
 }
-
-- 
GitLab