From ac47be4adf2753eda267608c426ef5ac6311b34e Mon Sep 17 00:00:00 2001
From: NAUD Maxence <maxence.naud@cea.fr>
Date: Thu, 14 Dec 2023 14:25:00 +0000
Subject: [PATCH] update slice and add some documentation to conv

---
 include/aidge/operator/Conv.hpp   | 12 ++++++++++++
 include/aidge/operator/Slice.hpp  | 26 +++++++++++++++++++-------
 src/operator/Slice.cpp            | 14 +++++++-------
 src/recipies/HorizontalTiling.cpp | 14 +++++++++-----
 4 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/include/aidge/operator/Conv.hpp b/include/aidge/operator/Conv.hpp
index 7fa99b084..08c642ab5 100644
--- a/include/aidge/operator/Conv.hpp
+++ b/include/aidge/operator/Conv.hpp
@@ -193,6 +193,18 @@ std::vector<std::pair<std::vector<Aidge::DimSize_t>, std::vector<DimSize_t>>> co
 template <DimIdx_t DIM>
 const std::string Conv_Op<DIM>::Type = "Conv";
 
+/**
+ * @brief Perform a convolution on the input Tensor.
+ *
+ * @tparam DIM Number of dimensions for the feature map.
+ * @param inChannels Number of input channels.
+ * @param outChannels Number of output channels.
+ * @param kernelDims Dimensions of the kernel. Must be the same number of dimensions as the feature map.
+ * @param name Name of the operator.
+ * @param strideDims Dimensions of the stride attribute. Must be the same number of dimensions as the feature map.
+ * @param dilationDims Dimensions of the dilation attribute. Must be the same number of dimensions as the feature map.
+ * @return std::shared_ptr<Node> A Node containing the operator.
+ */
 template <std::array<DimSize_t, 1>::size_type DIM>
 inline std::shared_ptr<Node> Conv(DimSize_t inChannels,
                                   DimSize_t outChannels,
diff --git a/include/aidge/operator/Slice.hpp b/include/aidge/operator/Slice.hpp
index 9b93b9448..a56e63508 100644
--- a/include/aidge/operator/Slice.hpp
+++ b/include/aidge/operator/Slice.hpp
@@ -29,17 +29,17 @@ enum class SliceAttr { Starts, Ends, Axes };
 class Slice_Op
     : public OperatorTensor,
       public Registrable<Slice_Op, std::string, std::unique_ptr<OperatorImpl>(const Slice_Op &)>,
-      public StaticAttributes<SliceAttr, std::vector<std::size_t>, std::vector<std::size_t>, std::vector<std::size_t>> {
+      public StaticAttributes<SliceAttr, std::vector<std::int32_t>, std::vector<std::int32_t>, std::vector<std::int32_t>> {
 public:
     static const std::string Type;
 
     Slice_Op() = delete;
 
-    using Attributes_ = StaticAttributes<SliceAttr, std::vector<std::size_t>, std::vector<std::size_t>, std::vector<std::size_t>>;
+    using Attributes_ = StaticAttributes<SliceAttr, std::vector<std::int32_t>, std::vector<std::int32_t>, std::vector<std::int32_t>>;
     template <SliceAttr e>
     using attr = typename Attributes_::template attr<e>;
 
-    Slice_Op(const std::vector<std::size_t>& starts, const std::vector<std::size_t>&  ends, const std::vector<std::size_t>& axes)
+    Slice_Op(const std::vector<std::int32_t>& starts, const std::vector<std::int32_t>&  ends, const std::vector<std::int32_t>& axes)
         : OperatorTensor(Type, 1, 0, 1),
           Attributes_(attr<SliceAttr::Starts>(starts),
                       attr<SliceAttr::Ends>(ends),
@@ -84,10 +84,22 @@ public:
     }
 };
 
-
-inline std::shared_ptr<Node> Slice(const std::vector<std::size_t> starts,
-                                   const std::vector<std::size_t> ends,
-                                   const std::vector<std::size_t> axes,
+/**
+ * @brief Exract a sub-Tensor from a bigger original Tensor.
+ * @param starts Indexes for each dimension of the first element.
+ * Can be a negative value. Negative values start their reference from the last index.
+ * ``-1`` referes to the last index of a dimension.
+ * @param ends Indexes for each dimension of the last element.
+ * Can be a negative value. Negative values start their reference from the last index.
+ * ``-1`` referes to the last index of a dimension.
+ * @param axes Dimensions for which start/end indexes apply. Not specifying a dimensions
+ * means the whole dimensions is extracted.
+ * @param name Name of the Operator.
+ * @return std::shared_ptr<Node> A Node containing the Operator.
+ */
+inline std::shared_ptr<Node> Slice(const std::vector<std::int32_t> starts,
+                                   const std::vector<std::int32_t> ends,
+                                   const std::vector<std::int32_t> axes,
                                    const std::string &name = "") {
     // FIXME: properly handle default w&b initialization in every cases
     return std::make_shared<Node>(std::make_shared<Slice_Op>(starts, ends, axes), name);
diff --git a/src/operator/Slice.cpp b/src/operator/Slice.cpp
index b9ba4fe36..bccb0b8b4 100644
--- a/src/operator/Slice.cpp
+++ b/src/operator/Slice.cpp
@@ -32,14 +32,14 @@ void Aidge::Slice_Op::computeOutputDims() {
     std::vector<DimSize_t> outDims = getInput(0)->dims();
     for (std::size_t i = 0; i < nbAxes; ++i) {
         // For each slice operation get the params and cast them to size_t
-        std::int64_t axis_ = this->template getAttr<SliceAttr::Axes>()[i];
-        std::int64_t start_ = this->template getAttr<SliceAttr::Starts>()[i];
-        std::int64_t end_ = this->template getAttr<SliceAttr::Ends>()[i];
-        std::size_t axis = axis_ >= 0 ? axis_ : axis_ + getInput(0)->nbDims();
-        std::size_t start = start_ >= 0 ? start_ : start_ + getInput(0)->dims()[axis];
-        std::size_t end = end_ >= 0 ? end_ : end_ + getInput(0)->dims()[axis];
+        const std::int64_t axis_ = this->template getAttr<SliceAttr::Axes>()[i];
+        const std::int64_t start_ = this->template getAttr<SliceAttr::Starts>()[i];
+        const std::int64_t end_ = this->template getAttr<SliceAttr::Ends>()[i];
+        const std::size_t axis = axis_ >= 0 ? static_cast<std::size_t>(axis_) : axis_ + getInput(0)->nbDims();
+        const std::size_t start = start_ >= 0 ? static_cast<std::size_t>(start_) : start_ + getInput(0)->dims()[axis];
+        const std::size_t end = end_ >= 0 ? static_cast<std::size_t>(end_) : end_ + getInput(0)->dims()[axis];
 
-        std::size_t sliceLength = end - start + 1;
+        const std::size_t sliceLength = end - start + 1;
         // Check if slice length is valid
         if (sliceLength > getInput(0)->dims()[axis])
             AIDGE_THROW_OR_ABORT(std::runtime_error, "ROI of Slice operator out of bounds");
diff --git a/src/recipies/HorizontalTiling.cpp b/src/recipies/HorizontalTiling.cpp
index 48d8cfc0b..6cc34eba0 100644
--- a/src/recipies/HorizontalTiling.cpp
+++ b/src/recipies/HorizontalTiling.cpp
@@ -82,13 +82,17 @@ std::set<std::shared_ptr<Aidge::Node>> Aidge::getConvHorizontalTiling(const std:
         clonedInputs[1] -> addChild(newNode, 0, 1);
         clonedInputs[2] -> addChild(newNode, 0, 2);
         // Slice for input and each parameter
-        auto inputDimsEnd = inputDims[0].first;
+        std::vector<std::int32_t> inputDimsEnd(inputDims[0].first.size());
         for (std::size_t dim = 0; dim < inputDimsEnd.size(); ++dim) {
-            inputDimsEnd[dim] += inputDims[0].second[dim];
+            inputDimsEnd[dim] = static_cast<std::int32_t>(inputDims[0].first[dim] + inputDims[0].second[dim]) - 1;
         }
-        std::vector<std::size_t> usedDims(inputDimsEnd.size());
-        std::iota(usedDims.begin(), usedDims.end(), static_cast<std::size_t>(0));
-        auto slice = Slice(inputDims[0].first, inputDimsEnd, usedDims, "Slice_" + std::to_string(currentFirstDims[axis]));
+        std::vector<std::int32_t> inputDimsStart(inputDims[0].first.size());
+        for (std::size_t dim = 0; dim < inputDimsStart.size(); ++dim) {
+            inputDimsStart[dim] = static_cast<std::int32_t>(inputDims[0].first[dim]);
+        }
+        std::vector<std::int32_t> usedDims(inputDimsEnd.size());
+        std::iota(usedDims.begin(), usedDims.end(), static_cast<std::int32_t>(0));
+        auto slice = Slice(inputDimsStart, inputDimsEnd, usedDims, "Slice_" + std::to_string(currentFirstDims[axis]));
         slice -> addChild(newNode, 0, 0);
         newNode -> addChild(concat, 0, i);
 
-- 
GitLab