Skip to content
Snippets Groups Projects
Commit a8a9d369 authored by Grégoire Kubler's avatar Grégoire Kubler Committed by Maxence Naud
Browse files

feat : created Tensor::getIdx(), Tensor::getCoords() & Tensor::isInBounds()

parent d67dadc8
No related branches found
No related tags found
2 merge requests!279v0.4.0,!242Extends the functionalities of Resize Operator
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#ifndef AIDGE_CORE_DATA_TENSOR_H_ #ifndef AIDGE_CORE_DATA_TENSOR_H_
#define AIDGE_CORE_DATA_TENSOR_H_ #define AIDGE_CORE_DATA_TENSOR_H_
#include <algorithm>
#include <cstddef> // std::size_t #include <cstddef> // std::size_t
#include <cstring> #include <cstring>
#include <functional> // std::multiplies #include <functional> // std::multiplies
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
#include "aidge/backend/TensorImpl.hpp" #include "aidge/backend/TensorImpl.hpp"
#include "aidge/data/Data.hpp" #include "aidge/data/Data.hpp"
#include "aidge/utils/ErrorHandling.hpp"
#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Registrar.hpp"
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/utils/ArrayHelpers.hpp" #include "aidge/utils/ArrayHelpers.hpp"
...@@ -625,16 +627,19 @@ public: ...@@ -625,16 +627,19 @@ public:
* @return std::vector<DimSize_t> * @return std::vector<DimSize_t>
*/ */
std::vector<std::size_t> getCoord(std::size_t flatIdx) const { std::vector<std::size_t> getCoord(std::size_t flatIdx) const {
std::vector<std::size_t> coordIdx(mDims.size()); return Tensor::getCoord(mDims, flatIdx);
std::size_t i = mDims.size();
while (i-- > 0) {
coordIdx[i] = (flatIdx % mDims[i]);
flatIdx/=mDims[i];
}
return coordIdx;
} }
/**
* @brief From the the 1D contiguous index, return the coordinate of an element in the tensor.
* Beware: do not use this function with the storage index!
*
* @param flatIdx 1D contiguous index of the value considering a flatten, contiguous, tensor.
* @return std::vector<DimSize_t>
*/
static std::vector<std::size_t>
getCoord(const std::vector<Aidge::DimSize_t> &dimensions, std::size_t flattenedIdx);
/** /**
* @brief From the coordinate returns the 1D contiguous index of an element in the tensor. * @brief From the coordinate returns the 1D contiguous index of an element in the tensor.
* If the number of coordinates is inferior to the number of dimensions, * If the number of coordinates is inferior to the number of dimensions,
...@@ -647,17 +652,33 @@ public: ...@@ -647,17 +652,33 @@ public:
* @return DimSize_t Contiguous index * @return DimSize_t Contiguous index
*/ */
std::size_t getIdx(const std::vector<std::size_t>& coordIdx) const { std::size_t getIdx(const std::vector<std::size_t>& coordIdx) const {
AIDGE_ASSERT(coordIdx.size() <= mDims.size(), "Coordinates does not match number of dimensions"); return Tensor::getIdx(mDims,coordIdx);
std::size_t flatIdx = 0;
for(std::size_t i = 0; i < mDims.size(); ++i) {
auto coord = i < coordIdx.size() ? coordIdx[i]: 0;
AIDGE_ASSERT(coord < mDims[i], "Coordinates dimensions does not fit the dimensions of the tensor");
auto nextDimSize = i + 1 < mDims.size() ? mDims[i + 1]: 1;
flatIdx = (flatIdx + coord) * nextDimSize;
}
return flatIdx;
} }
/**
* @brief From the coordinate returns the 1D contiguous index of an element in the tensor.
* If the number of coordinates is inferior to the number of dimensions,
* the remaining coordinates are assumed to be 0.
* Beware: the contiguous index will only correspond to the storage index
* if the tensor is contiguous!
* Note that the coordIdx may be an empty vector.
*
* @param coordIdx Coordinate to an element in the tensor
* @return DimSize_t Contiguous index
*/
static std::size_t getIdx(const std::vector<DimSize_t>& tensorDims, const std::vector<std::size_t>& coords);
/**
* @brief check if index is in bound of given tensor dimensions
* @warning this function is templated in order to welcome cases like interpolation where indexes are not integers.
* However, the only types accepted are floating, integer & size_t
* @param tensorDims : tensor dimensions
* @param coords : coords of the tensor you want to flattened index of
* @return true if all coords are in bound. False otherwise
*/
template<typename T>
static bool isInBounds(const std::vector<DimSize_t>& tensorDims, const std::vector<T>& coords);
/** /**
* @brief From the coordinate returns the 1D storage index of an element in the tensor. * @brief From the coordinate returns the 1D storage index of an element in the tensor.
* If the number of coordinates is inferior to the number of dimensions, * If the number of coordinates is inferior to the number of dimensions,
......
...@@ -329,9 +329,8 @@ void init_Tensor(py::module& m){ ...@@ -329,9 +329,8 @@ void init_Tensor(py::module& m){
.def("capacity", &Tensor::capacity) .def("capacity", &Tensor::capacity)
.def("resize", (void (Tensor::*)(const std::vector<DimSize_t>&, std::vector<DimSize_t>)) &Tensor::resize, py::arg("dims"), py::arg("strides") = std::vector<DimSize_t>()) .def("resize", (void (Tensor::*)(const std::vector<DimSize_t>&, std::vector<DimSize_t>)) &Tensor::resize, py::arg("dims"), py::arg("strides") = std::vector<DimSize_t>())
.def("has_impl", &Tensor::hasImpl) .def("has_impl", &Tensor::hasImpl)
.def("get_coord", &Tensor::getCoord) .def("get_coord", (std::vector<std::size_t> (Tensor::*)(const std::size_t) &Tensor::getCoord, py::arg("flatIdx"))
.def("get_idx", &Tensor::getIdx) .def("get_idx",(std::size_t (Tensor::*)(const std::vector<std::size_t> &) &Tensor::getIdx, py::arg("coords"))
.def_static("get_available_backends", &Tensor::getAvailableBackends)
.def("undefined", &Tensor::undefined) .def("undefined", &Tensor::undefined)
.def("cpy_transpose", (void (Tensor::*)(const Tensor& src, const std::vector<DimSize_t>& transpose)) &Tensor::copyTranspose, py::arg("src"), py::arg("transpose")) .def("cpy_transpose", (void (Tensor::*)(const Tensor& src, const std::vector<DimSize_t>& transpose)) &Tensor::copyTranspose, py::arg("src"), py::arg("transpose"))
......
...@@ -11,9 +11,11 @@ ...@@ -11,9 +11,11 @@
#include "aidge/data/Tensor.hpp" #include "aidge/data/Tensor.hpp"
#include <algorithm>
#include <cstddef> #include <cstddef>
#include <vector> #include <vector>
#include "aidge/data/half.hpp"
#include "aidge/utils/ErrorHandling.hpp" #include "aidge/utils/ErrorHandling.hpp"
#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Registrar.hpp"
#include "aidge/operator/Abs.hpp" #include "aidge/operator/Abs.hpp"
...@@ -675,7 +677,58 @@ const Aidge::Tensor& Aidge::Tensor::ref(std::shared_ptr<Tensor>& fallback, ...@@ -675,7 +677,58 @@ const Aidge::Tensor& Aidge::Tensor::ref(std::shared_ptr<Tensor>& fallback,
std::set<std::string> Aidge::Tensor::getAvailableBackends() { std::set<std::string> Aidge::Tensor::getAvailableBackends() {
std::set<std::string> backendsList; std::set<std::string> backendsList;
for (const auto& tupleKey : Registrar<Tensor>::getKeys()) for (const auto& tupleKey : Registrar<Tensor>::getKeys()) {
backendsList.insert(std::get<0>(tupleKey)); backendsList.insert(std::get<0>(tupleKey));
}
return backendsList; return backendsList;
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// COORDINATES MANIPULATION
std::vector<std::size_t>
Aidge::Tensor::getCoord(const std::vector<Aidge::DimSize_t> &tensorDims,
std::size_t flatIdx) {
std::vector<std::size_t> coordIdx(tensorDims.size());
std::size_t i = tensorDims.size();
while (i-- > 0) {
coordIdx[i] = (flatIdx % tensorDims[i]);
flatIdx/=tensorDims[i];
}
return coordIdx;
}
std::size_t Aidge::Tensor::getIdx(const std::vector<Aidge::DimSize_t> &tensorDims, const std::vector<std::size_t>& coordIdx) {
AIDGE_ASSERT(coordIdx.size() <= tensorDims.size(), "Tensor::getIdx(): Coordinates does not match number of dimensions.\n\tCoords : {}\n\tDimensions: {}",coordIdx, tensorDims);
std::size_t flatIdx = 0;
for(std::size_t i = 0; i < tensorDims.size(); ++i) {
auto coord = i < coordIdx.size() ? coordIdx[i]: 0;
AIDGE_ASSERT(coord < tensorDims[i], "Coordinates dimensions does not fit the dimensions of the tensor");
auto nextDimSize = i + 1 < tensorDims.size() ? tensorDims[i + 1]: 1;
flatIdx = (flatIdx + coord) * nextDimSize;
}
return flatIdx;
}
template<typename T>
bool Aidge::Tensor::isInBounds(const std::vector<Aidge::DimSize_t>& tensorDims, const std::vector<T>& coords){
AIDGE_ASSERT(coords.size() == tensorDims.size(),
"Coordinates({}) to compare have not "
"the same number of dimension as tensor dimensions({}), aborting.",
coords,
tensorDims);
T i;
bool isInBound {true};
for(i = 0 ; i < static_cast<T>(coords.size()) && isInBound; ++i ){
isInBound = coords[i] >= 0 && coords[i] < static_cast<T>(tensorDims[i]) ;
}
return isInBound;
}
template bool Tensor::isInBounds(const std::vector<DimSize_t>& tensorDims, const std::vector<int16_t>& coords);
template bool Tensor::isInBounds(const std::vector<DimSize_t>& tensorDims, const std::vector<int32_t>& coords);
template bool Tensor::isInBounds(const std::vector<DimSize_t>& tensorDims, const std::vector<int64_t>& coords);
template bool Tensor::isInBounds(const std::vector<DimSize_t>& tensorDims, const std::vector<DimSize_t>& coords);
template bool Tensor::isInBounds(const std::vector<DimSize_t>& tensorDims, const std::vector<float>& coords);
template bool Tensor::isInBounds(const std::vector<DimSize_t>& tensorDims, const std::vector<double>& coords);
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
* *
********************************************************************************/ ********************************************************************************/
#include <array>
#include <cstddef> // std::size_t #include <cstddef> // std::size_t
#include <cstdint> // std::uint8_t, std::uint16_t, std::int32_t #include <cstdint> // std::uint8_t, std::uint16_t, std::int32_t
#include <cstdlib>
#include <numeric> // std::accumulate, std::inner_product #include <numeric> // std::accumulate, std::inner_product
#include <functional> // std::multiplies #include <functional> // std::multiplies
#include <random> // std::mt19937, #include <random> // std::mt19937,
...@@ -365,7 +365,40 @@ TEST_CASE("[core/data] Tensor(other)", "[Tensor][extract][zeros][print]") { ...@@ -365,7 +365,40 @@ TEST_CASE("[core/data] Tensor(other)", "[Tensor][extract][zeros][print]") {
} }
} }
} }
SECTION("Index & coord manipulation"){
Tensor tensor;
std::vector<DimSize_t> dims {2,2};
int nbVal = std::accumulate(dims.begin(),
dims.end(),
1,
std::multiplies<DimSize_t>());
float* values = static_cast<float*>(malloc(nbVal * sizeof(float)));
values[0] = 0;
values[1] = 1;
values[2] = 2;
values[3] = 3;
tensor.setDataType(DataType::Int32);
tensor.setBackend("cpu");
tensor.resize(dims);
tensor.getImpl()->setRawPtr(values, 4);
std::vector<std::size_t> coords;
SECTION("getIdx"){
CHECK(Tensor::getIdx(tensor.dims(), std::vector<std::size_t>({1,1}) ) == 3);
CHECK(Tensor::getIdx(tensor.dims(), std::vector<std::size_t>({1,0}) ) == 2);
// No check to ensure if value is in bounds
CHECK_THROWS(Tensor::getIdx(tensor.dims(), std::vector<std::size_t>({0,2}) ));
}
SECTION("getCoord"){
CHECK(Tensor::getCoord(tensor.dims(), 3 ) ==std::vector<std::size_t>({1,1}));
CHECK(Tensor::getCoord(tensor.dims(), 2 ) ==std::vector<std::size_t>({1,0}));
}
SECTION("isInBound"){
CHECK_THROWS(Tensor::isInBounds(dims, std::vector<DimSize_t>({1,2,4,5})) == true);
CHECK(Tensor::isInBounds(dims, std::vector<DimSize_t>({1,2})) == false);
CHECK(Tensor::isInBounds(dims, std::vector<int>({-1,1})) == false);
CHECK(Tensor::isInBounds(dims, std::vector<DimSize_t>({1,1})) == true);
}
}
SECTION("Tensor extract") { SECTION("Tensor extract") {
bool equal; bool equal;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment