From 2dbb53e36b1d46fe2fedc785a427cabcf6c63aff Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Wed, 12 Mar 2025 15:00:57 +0100
Subject: [PATCH 1/9] [New] Unit test for expected results at the end of the MR

---
 unit_tests/operator/Test_TransposeImpl.cpp | 30 ++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp
index 02b338dd2..be54b8c42 100644
--- a/unit_tests/operator/Test_TransposeImpl.cpp
+++ b/unit_tests/operator/Test_TransposeImpl.cpp
@@ -200,3 +200,33 @@ TEST_CASE("[cpu/operator] Transpose(forward)") {
         REQUIRE(*(op->getOutput(0)) == *output);
     }
 }
+
+TEST_CASE("[cpu/operator] Transpose DataFormat") {
+    SECTION("NCHW to NHWC"){
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
+        input->setDataFormat(Aidge::DataFormat::NCHW);
+
+        auto transposeNode = Transpose({0,2,3,1});
+
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator());
+        op->associateInput(0,input);
+        op->setBackend("cpu");
+        transposeNode->forward();
+
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC);
+    }
+    SECTION("NHWC to NCHW"){
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
+        input->setDataFormat(Aidge::DataFormat::NHWC);
+
+        auto transposeNode = Transpose({0,3,1,2});
+
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator());
+        op->associateInput(0,input);
+        op->setBackend("cpu");
+        transposeNode->forward();
+
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC);
+    }
+}
+
-- 
GitLab


From 05f7109d11190c048b48da55b45cc68579159315 Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Wed, 19 Mar 2025 10:19:34 +0100
Subject: [PATCH 2/9] Add transpose output data format computation and related
 tests

---
 include/aidge/data/DataFormat.hpp          | 19 +++++
 src/data/DataFormat.cpp                    | 46 +++++++++++
 src/operator/Transpose.cpp                 |  7 ++
 unit_tests/operator/Test_TransposeImpl.cpp | 90 +++++++++++++++++++++-
 4 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp
index 4df854a1e..9b929b14a 100644
--- a/include/aidge/data/DataFormat.hpp
+++ b/include/aidge/data/DataFormat.hpp
@@ -83,6 +83,25 @@ using DataFormatTranspose = std::array<std::size_t, 5>;
  */
 DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataFormat& dst);
 
+/**
+ * @brief Determine the output data format after applying a transpose operation.
+ *
+ * This function computes the new data format after transposing a tensor.
+ * It follows these steps:
+ *   1. Retrieves the permutation mapping from the default format (NCHW) to the input format.
+ *   2. Applies the given output dimensions order to compute the new permutation.
+ *   3. Determines the number of dimensions associated with the input data format.
+ *   4. Identifies the corresponding data format for the new permutation.
+ *
+ * @param inputDataFormat The data format of the input tensor.
+ * @param outputDimsOrder The permutation applied to the input tensor's dimensions.
+ * @return DataFormat The computed output data format after applying the permutation.
+ *
+ * @throws std::runtime_error if the provided permutation is invalid for the given format.
+ * @pre `outputDimsOrder` must be a valid permutation of the format's dimensions.
+ */
+DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder);
+
 } // namespace Aidge
 
 namespace {
diff --git a/src/data/DataFormat.cpp b/src/data/DataFormat.cpp
index 8b7460b3d..25621e1af 100644
--- a/src/data/DataFormat.cpp
+++ b/src/data/DataFormat.cpp
@@ -51,6 +51,25 @@ static std::size_t getNbDimensions(DataFormat dformat) {
     return nbDimensions[static_cast<std::size_t>(dformat)];
 }
 
+/**
+ * @brief Get the DataFormat corresponding to a given permutation vector.
+ *
+ * @param perm The permutation vector.
+ * @return DataFormat The matching DataFormat, or DataFormat::Default if not found.
+ */
+static DataFormat getDataFormatFromPermutation(const DataFormatTranspose& perm, const unsigned int nbDims) { 
+    for (size_t i = 0; i < NB_DFORMAT; ++i) {
+        DataFormat candidateFormat = static_cast<DataFormat>(i);
+        const DataFormatTranspose& candidatePerm = getPermutationFromNCHW(candidateFormat);
+
+        if (std::equal(candidatePerm.begin(), candidatePerm.begin() + nbDims, perm.begin())) {
+            return candidateFormat;
+        }
+    }
+    Log::warn("No matching DataFormat found for the given permutation : {}", perm);
+    return DataFormat::Default;  
+}
+
 DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataFormat& dst) {
     AIDGE_ASSERT((src != DataFormat::Any && dst != DataFormat::Any), "Permutation is not defined for DataFormat::Any");
     if (src == DataFormat::Default || dst == DataFormat::Default || src == dst) {
@@ -78,4 +97,31 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma
 
     return src_to_dst;
 }
+
+/**
+ * @brief Applies one permutation to another.
+ *
+ * Given an initial permutation `perm1` and another permutation `perm2`,
+ * this function returns a new permutation that results from applying `perm2` to `perm1`.
+ *
+ * @param perm1 The base permutation (original ordering → intermediate ordering).
+ * @param perm2 The permutation to apply (intermediate ordering → final ordering).
+    * @return DataFormatTranspose The resultng permutation (original ordering → final ordering).
+ */
+static DataFormatTranspose applyPermutation(const DataFormatTranspose& perm1, const DataFormatTranspose& perm2) {
+    DataFormatTranspose permuted{};
+    for (std::size_t i = 0; i < perm1.size(); ++i) {
+        permuted[i] = perm2[perm1[i]];
+    }
+    return permuted;
+}
+
+DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder){
+    const DataFormatTranspose permFromInput = getPermutationFromNCHW(inputDataFormat);
+    const DataFormatTranspose newPerm = applyPermutation(permFromInput, outputDimsOrder);
+    
+    const unsigned int nbDims = getNbDimensions(inputDataFormat);
+
+    return getDataFormatFromPermutation(newPerm, nbDims);
+}
 } // namespace Aidge
\ No newline at end of file
diff --git a/src/operator/Transpose.cpp b/src/operator/Transpose.cpp
index f9d612353..51c2d5960 100644
--- a/src/operator/Transpose.cpp
+++ b/src/operator/Transpose.cpp
@@ -77,7 +77,14 @@ bool Aidge::Transpose_Op::forwardDims(bool /*allowDataDependency*/) {
             AIDGE_ASSERT(i == outputDimsOrder()[i],
                 "Permutation vector ({}) must be the identity above the input tensor rank ({}).", outputDimsOrder(), getInput(0)->dims());
         }
+        
         mOutputs[0]->resize(outputDims);
+
+        // Set the data format of the output tensor
+        std::array<std::size_t, 5> outputDimsArray;
+        std::copy_n(outputDimsOrder().begin(), 5, outputDimsArray.begin());
+
+        mOutputs[0]->setDataFormat(getTransposeOutputDataFormat(getInput(0)->dataFormat(), outputDimsArray));
         return true;
     }
     return false;
diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp
index be54b8c42..0e3037773 100644
--- a/unit_tests/operator/Test_TransposeImpl.cpp
+++ b/unit_tests/operator/Test_TransposeImpl.cpp
@@ -205,7 +205,7 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("NCHW to NHWC"){
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
         input->setDataFormat(Aidge::DataFormat::NCHW);
-
+        input->setBackend("cpu");
         auto transposeNode = Transpose({0,2,3,1});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator());
@@ -218,15 +218,99 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("NHWC to NCHW"){
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
         input->setDataFormat(Aidge::DataFormat::NHWC);
-
+        input->setBackend("cpu");
         auto transposeNode = Transpose({0,3,1,2});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator());
         op->associateInput(0,input);
         op->setBackend("cpu");
         transposeNode->forward();
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW);
+    }
+    SECTION("CHWN to NCHW") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,224,450,16}));
+        input->setDataFormat(Aidge::DataFormat::CHWN);
+        input->setBackend("cpu");
+        auto transposeNode = Transpose({3,0,1,2});
 
-        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC);
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
+        op->associateInput(0, input);
+        op->setBackend("cpu");
+        transposeNode->forward();
+
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW);
+    }
+
+    SECTION("NCDHW to NDHWC") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,8,224,450}));
+        input->setDataFormat(Aidge::DataFormat::NCDHW);
+        input->setBackend("cpu");
+        auto transposeNode = Transpose({0,2,3,4,1});
+
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
+        op->associateInput(0, input);
+        op->setBackend("cpu");
+        transposeNode->forward();
+
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NDHWC);
+    }
+
+    SECTION("NDHWC to NCDHW") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,8,224,450,3}));
+        input->setDataFormat(Aidge::DataFormat::NDHWC);
+        input->setBackend("cpu");
+        auto transposeNode = Transpose({0,4,1,2,3});
+
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
+        op->associateInput(0, input);
+        op->setBackend("cpu");
+        transposeNode->forward();
+
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW);
+    }
+
+    SECTION("CDHWN to NCDHW") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,8,224,450,16}));
+        input->setDataFormat(Aidge::DataFormat::CDHWN);
+        input->setBackend("cpu");
+        auto transposeNode = Transpose({4,0,1,2,3});
+
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
+        op->associateInput(0, input);
+        op->setBackend("cpu");
+        transposeNode->forward();
+
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW);
     }
+
+    SECTION("(Identity) NCHW to NCHW)") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
+        input->setDataFormat(Aidge::DataFormat::NCHW);
+        input->setBackend("cpu");
+        auto transposeNode = Transpose({0,1,2,3}); // Identity permutation
+
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
+        op->associateInput(0, input);
+        op->setBackend("cpu");
+        transposeNode->forward();
+
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW);
+    }
+
+    SECTION("Invalid Format Handling") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
+        input->setDataFormat(Aidge::DataFormat::Default);
+        input->setBackend("cpu");
+        auto transposeNode = Transpose({0,2,3,1});
+
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
+        op->associateInput(0, input);
+        op->setBackend("cpu");
+
+        transposeNode->forward();
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default);
+        //Should throw a Warning
+    }
+
 }
 
-- 
GitLab


From 0cd6c63c097e8091591c0c1f0e888269f151e06d Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Wed, 19 Mar 2025 10:20:55 +0100
Subject: [PATCH 3/9] Change doxygen

---
 include/aidge/data/DataFormat.hpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp
index 9b929b14a..238d48e82 100644
--- a/include/aidge/data/DataFormat.hpp
+++ b/include/aidge/data/DataFormat.hpp
@@ -97,7 +97,6 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma
  * @param outputDimsOrder The permutation applied to the input tensor's dimensions.
  * @return DataFormat The computed output data format after applying the permutation.
  *
- * @throws std::runtime_error if the provided permutation is invalid for the given format.
  * @pre `outputDimsOrder` must be a valid permutation of the format's dimensions.
  */
 DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder);
-- 
GitLab


From b45e341b13cb1b8f982ec7ae5c0d5f007525adc0 Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Wed, 19 Mar 2025 10:47:28 +0100
Subject: [PATCH 4/9] add pybind

---
 python_binding/data/pybind_DataFormat.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python_binding/data/pybind_DataFormat.cpp b/python_binding/data/pybind_DataFormat.cpp
index 5308fb302..d41251153 100644
--- a/python_binding/data/pybind_DataFormat.cpp
+++ b/python_binding/data/pybind_DataFormat.cpp
@@ -67,6 +67,7 @@ void init_DataFormat(py::module& m) {
     bindEnum<DataFormat>(m, "dformat");
     m.def("format_as", (const char* (*)(DataFormat)) &format_as, py::arg("df"));
     m.def("get_permutation_mapping", &getPermutationMapping, py::arg("src"), py::arg("dst"));
+    m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("inputDataFormat"), py::arg("outputDimsOrder"));
 }
 
 } // namespace Aidge
-- 
GitLab


From f69f024087e7544d9e56ede4529b22c66419ba63 Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Wed, 19 Mar 2025 16:09:37 +0100
Subject: [PATCH 5/9] Rename getTransposeOutputDataFormat to
 getTransposedDataFormat and update related bindings and usages

---
 include/aidge/data/DataFormat.hpp          |  7 +----
 python_binding/data/pybind_DataFormat.cpp  |  2 +-
 src/data/DataFormat.cpp                    |  2 +-
 src/operator/Transpose.cpp                 |  4 +--
 unit_tests/operator/Test_TransposeImpl.cpp | 34 ++++++----------------
 5 files changed, 14 insertions(+), 35 deletions(-)

diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp
index 238d48e82..64a996501 100644
--- a/include/aidge/data/DataFormat.hpp
+++ b/include/aidge/data/DataFormat.hpp
@@ -87,11 +87,6 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma
  * @brief Determine the output data format after applying a transpose operation.
  *
  * This function computes the new data format after transposing a tensor.
- * It follows these steps:
- *   1. Retrieves the permutation mapping from the default format (NCHW) to the input format.
- *   2. Applies the given output dimensions order to compute the new permutation.
- *   3. Determines the number of dimensions associated with the input data format.
- *   4. Identifies the corresponding data format for the new permutation.
  *
  * @param inputDataFormat The data format of the input tensor.
  * @param outputDimsOrder The permutation applied to the input tensor's dimensions.
@@ -99,7 +94,7 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma
  *
  * @pre `outputDimsOrder` must be a valid permutation of the format's dimensions.
  */
-DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder);
+DataFormat getTransposedDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder);
 
 } // namespace Aidge
 
diff --git a/python_binding/data/pybind_DataFormat.cpp b/python_binding/data/pybind_DataFormat.cpp
index d41251153..ae8b3636e 100644
--- a/python_binding/data/pybind_DataFormat.cpp
+++ b/python_binding/data/pybind_DataFormat.cpp
@@ -67,7 +67,7 @@ void init_DataFormat(py::module& m) {
     bindEnum<DataFormat>(m, "dformat");
     m.def("format_as", (const char* (*)(DataFormat)) &format_as, py::arg("df"));
     m.def("get_permutation_mapping", &getPermutationMapping, py::arg("src"), py::arg("dst"));
-    m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("inputDataFormat"), py::arg("outputDimsOrder"));
+    m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("input_data_format"), py::arg("output_dims_order"));
 }
 
 } // namespace Aidge
diff --git a/src/data/DataFormat.cpp b/src/data/DataFormat.cpp
index 25621e1af..e8dd605bb 100644
--- a/src/data/DataFormat.cpp
+++ b/src/data/DataFormat.cpp
@@ -116,7 +116,7 @@ static DataFormatTranspose applyPermutation(const DataFormatTranspose& perm1, co
     return permuted;
 }
 
-DataFormat getTransposeOutputDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder){
+DataFormat getTransposedDataFormat(const DataFormat inputDataFormat, const std::array<std::size_t, 5> outputDimsOrder){
     const DataFormatTranspose permFromInput = getPermutationFromNCHW(inputDataFormat);
     const DataFormatTranspose newPerm = applyPermutation(permFromInput, outputDimsOrder);
     
diff --git a/src/operator/Transpose.cpp b/src/operator/Transpose.cpp
index 51c2d5960..876d4e3fe 100644
--- a/src/operator/Transpose.cpp
+++ b/src/operator/Transpose.cpp
@@ -81,10 +81,10 @@ bool Aidge::Transpose_Op::forwardDims(bool /*allowDataDependency*/) {
         mOutputs[0]->resize(outputDims);
 
         // Set the data format of the output tensor
-        std::array<std::size_t, 5> outputDimsArray;
+        DataFormatTranspose outputDimsArray;
         std::copy_n(outputDimsOrder().begin(), 5, outputDimsArray.begin());
 
-        mOutputs[0]->setDataFormat(getTransposeOutputDataFormat(getInput(0)->dataFormat(), outputDimsArray));
+        mOutputs[0]->setDataFormat(getTransposedDataFormat(getInput(0)->dataFormat(), outputDimsArray));
         return true;
     }
     return false;
diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp
index 0e3037773..75adc9fd5 100644
--- a/unit_tests/operator/Test_TransposeImpl.cpp
+++ b/unit_tests/operator/Test_TransposeImpl.cpp
@@ -205,38 +205,32 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("NCHW to NHWC"){
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
         input->setDataFormat(Aidge::DataFormat::NCHW);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({0,2,3,1});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator());
         op->associateInput(0,input);
-        op->setBackend("cpu");
-        transposeNode->forward();
+        op->forwardDims();
 
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NHWC);
     }
     SECTION("NHWC to NCHW"){
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
         input->setDataFormat(Aidge::DataFormat::NHWC);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({0,3,1,2});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode -> getOperator());
         op->associateInput(0,input);
-        op->setBackend("cpu");
-        transposeNode->forward();
+        op->forwardDims();
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW);
     }
     SECTION("CHWN to NCHW") {
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,224,450,16}));
         input->setDataFormat(Aidge::DataFormat::CHWN);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({3,0,1,2});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
         op->associateInput(0, input);
-        op->setBackend("cpu");
-        transposeNode->forward();
+        op->forwardDims();
 
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW);
     }
@@ -244,13 +238,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("NCDHW to NDHWC") {
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,8,224,450}));
         input->setDataFormat(Aidge::DataFormat::NCDHW);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({0,2,3,4,1});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
         op->associateInput(0, input);
-        op->setBackend("cpu");
-        transposeNode->forward();
+        op->forwardDims();
 
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NDHWC);
     }
@@ -258,13 +250,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("NDHWC to NCDHW") {
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,8,224,450,3}));
         input->setDataFormat(Aidge::DataFormat::NDHWC);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({0,4,1,2,3});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
         op->associateInput(0, input);
-        op->setBackend("cpu");
-        transposeNode->forward();
+        op->forwardDims();
 
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW);
     }
@@ -272,13 +262,12 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("CDHWN to NCDHW") {
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({3,8,224,450,16}));
         input->setDataFormat(Aidge::DataFormat::CDHWN);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({4,0,1,2,3});
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
         op->associateInput(0, input);
-        op->setBackend("cpu");
-        transposeNode->forward();
+        op->forwardDims();
+
 
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCDHW);
     }
@@ -286,13 +275,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("(Identity) NCHW to NCHW)") {
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
         input->setDataFormat(Aidge::DataFormat::NCHW);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({0,1,2,3}); // Identity permutation
 
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
         op->associateInput(0, input);
-        op->setBackend("cpu");
-        transposeNode->forward();
+        op->forwardDims();
 
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW);
     }
@@ -300,14 +287,11 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
     SECTION("Invalid Format Handling") {
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
         input->setDataFormat(Aidge::DataFormat::Default);
-        input->setBackend("cpu");
         auto transposeNode = Transpose({0,2,3,1});
-
         auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
         op->associateInput(0, input);
-        op->setBackend("cpu");
 
-        transposeNode->forward();
+        op->forwardDims();
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default);
         //Should throw a Warning
     }
-- 
GitLab


From 665b736bb01b95788a80d5cf3b40b44b4fcd3b2b Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Thu, 20 Mar 2025 11:32:37 +0100
Subject: [PATCH 6/9] docstring : Back to the future

---
 include/aidge/data/DataFormat.hpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/aidge/data/DataFormat.hpp b/include/aidge/data/DataFormat.hpp
index 64a996501..d89eb24cd 100644
--- a/include/aidge/data/DataFormat.hpp
+++ b/include/aidge/data/DataFormat.hpp
@@ -88,6 +88,11 @@ DataFormatTranspose getPermutationMapping(const DataFormat& src, const DataForma
  *
  * This function computes the new data format after transposing a tensor.
  *
+ * It follows these steps:
+ *   1. Retrieves the permutation mapping from the input format.
+ *   2. Applies the given output dimensions order to compute the new permutation.
+ *   3. Identifies the corresponding data format after applying the new permutation.
+ * 
  * @param inputDataFormat The data format of the input tensor.
  * @param outputDimsOrder The permutation applied to the input tensor's dimensions.
  * @return DataFormat The computed output data format after applying the permutation.
-- 
GitLab


From 4849218e34905c35b8b03aa92e62a765c04d7a4f Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Thu, 20 Mar 2025 15:24:37 +0100
Subject: [PATCH 7/9] Update docstring for DataFormatTranspose and improve test
 case descriptions

---
 src/data/DataFormat.cpp                    |  2 +-
 unit_tests/operator/Test_TransposeImpl.cpp | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/src/data/DataFormat.cpp b/src/data/DataFormat.cpp
index e8dd605bb..095ef9368 100644
--- a/src/data/DataFormat.cpp
+++ b/src/data/DataFormat.cpp
@@ -52,7 +52,7 @@ static std::size_t getNbDimensions(DataFormat dformat) {
 }
 
 /**
- * @brief Get the DataFormat corresponding to a given permutation vector.
+ * @brief Get the DataFormat corresponding to a given ``DataFormatTranspose``.
  *
  * @param perm The permutation vector.
  * @return DataFormat The matching DataFormat, or DataFormat::Default if not found.
diff --git a/unit_tests/operator/Test_TransposeImpl.cpp b/unit_tests/operator/Test_TransposeImpl.cpp
index 75adc9fd5..f852c3fe0 100644
--- a/unit_tests/operator/Test_TransposeImpl.cpp
+++ b/unit_tests/operator/Test_TransposeImpl.cpp
@@ -284,7 +284,7 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::NCHW);
     }
 
-    SECTION("Invalid Format Handling") {
+    SECTION("Default to Default") {
         std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
         input->setDataFormat(Aidge::DataFormat::Default);
         auto transposeNode = Transpose({0,2,3,1});
@@ -293,7 +293,19 @@ TEST_CASE("[cpu/operator] Transpose DataFormat") {
 
         op->forwardDims();
         REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default);
-        //Should throw a Warning
+        //Should print a Log::Warning
+    }
+
+    SECTION("Invalid Format Handling") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(std::vector<std::size_t>({16,3,224,450}));
+        input->setDataFormat(Aidge::DataFormat::NCHW);
+        auto transposeNode = Transpose({0,2,1,3});
+        auto op = std::static_pointer_cast<OperatorTensor>(transposeNode->getOperator());
+        op->associateInput(0, input);
+
+        op->forwardDims();
+        REQUIRE(op->getOutput(0)->dataFormat() == DataFormat::Default);
+        //Should print a Log::Warning
     }
 
 }
-- 
GitLab


From 353048840e68a3c61b08e823901c2770b6bec2d9 Mon Sep 17 00:00:00 2001
From: Wissam Boussella <wissam.boussella@cea.fr>
Date: Thu, 20 Mar 2025 15:29:00 +0100
Subject: [PATCH 8/9] remove magic number

---
 src/operator/Transpose.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/operator/Transpose.cpp b/src/operator/Transpose.cpp
index 876d4e3fe..f9e469476 100644
--- a/src/operator/Transpose.cpp
+++ b/src/operator/Transpose.cpp
@@ -82,7 +82,7 @@ bool Aidge::Transpose_Op::forwardDims(bool /*allowDataDependency*/) {
 
         // Set the data format of the output tensor
         DataFormatTranspose outputDimsArray;
-        std::copy_n(outputDimsOrder().begin(), 5, outputDimsArray.begin());
+        std::copy_n(outputDimsOrder().begin(), outputDimsOrder().size(), outputDimsArray.begin());
 
         mOutputs[0]->setDataFormat(getTransposedDataFormat(getInput(0)->dataFormat(), outputDimsArray));
         return true;
-- 
GitLab


From 1c2e90e334d83444d1c1a94e46d3b0516649a7dc Mon Sep 17 00:00:00 2001
From: Cyril Moineau <cyril.moineau@cea.fr>
Date: Thu, 20 Mar 2025 15:43:53 +0000
Subject: [PATCH 9/9] Apply 1 suggestion(s) to 1 file(s)

---
 python_binding/data/pybind_DataFormat.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_binding/data/pybind_DataFormat.cpp b/python_binding/data/pybind_DataFormat.cpp
index ae8b3636e..354911c33 100644
--- a/python_binding/data/pybind_DataFormat.cpp
+++ b/python_binding/data/pybind_DataFormat.cpp
@@ -67,7 +67,7 @@ void init_DataFormat(py::module& m) {
     bindEnum<DataFormat>(m, "dformat");
     m.def("format_as", (const char* (*)(DataFormat)) &format_as, py::arg("df"));
     m.def("get_permutation_mapping", &getPermutationMapping, py::arg("src"), py::arg("dst"));
-    m.def("get_transpose_output_data_format", &getTransposeOutputDataFormat, py::arg("input_data_format"), py::arg("output_dims_order"));
+    m.def("get_transposed_data_format", &getTransposedDataFormat, py::arg("input_data_format"), py::arg("output_dims_order"));
 }
 
 } // namespace Aidge
-- 
GitLab