diff --git a/include/aidge/data/Spikegen.hpp b/include/aidge/data/Spikegen.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1267fda9dffd4a49fd37e2f1c65a51072db4a8b4 --- /dev/null +++ b/include/aidge/data/Spikegen.hpp @@ -0,0 +1,10 @@ +#ifndef AIDGE_CORE_DATA_SPIKEGEN_H_ +#define AIDGE_CORE_DATA_SPIKEGEN_H_ + +// Spikegen algorithm : +// +// time_data = data.repeat(time_steps) +// spike_data = rate_conv(time_data) +// return spike_data + +#endif diff --git a/include/aidge/data/Tensor.hpp b/include/aidge/data/Tensor.hpp index 5df59becdc41f12768935544a42aac24ffb3a333..76295270e4081d45cf0289f2e9feba5e3e4855fb 100644 --- a/include/aidge/data/Tensor.hpp +++ b/include/aidge/data/Tensor.hpp @@ -13,9 +13,7 @@ #define AIDGE_CORE_DATA_TENSOR_H_ #include <algorithm> -#include <cstddef> // std::size_t -#include <cstring> -#include <functional> // std::multiplies +#include <cstddef> // std::size_t #include <cstring> #include <functional> // std::multiplies #include <set> #include <memory> #include <numeric> // std::accumulate @@ -989,6 +987,18 @@ public: return ref(fallback, targetReqs.dataType(), device.first, device.second); } + + /** + * @brief Repeat the tensor along a new first dimension. + * For example, if the current tensor has dimensions (n, m), + * calling repeat(10) returns a tensor of shape (10, n, m) + * with 10 copies of the original data. + * + * @param times number of repetitions (must be positive) + * @return Tensor new tensor containing the repeated data. + */ + Tensor repeat(int times) const; + private: /** * @brief Compute the number of elements in the Tensor. diff --git a/src/data/Tensor.cpp b/src/data/Tensor.cpp index b128833c9099385c72f25057400a65a6b9034c32..cf84306843d03cded0f5dd79dd58ecea9b5b7f4b 100644 --- a/src/data/Tensor.cpp +++ b/src/data/Tensor.cpp @@ -802,6 +802,43 @@ const Tensor& Tensor::ref(std::shared_ptr<Tensor>& fallback, } } +Tensor Tensor::repeat(int times) const { + AIDGE_ASSERT(times > 0, "repeat count must be positive"); + + // Ensure that the source tensor is contiguous. + Tensor src = *this; + if (not src.isContiguous()) { + src = src.clone(); + src.makeContiguous(); + } + + // Build new dimensions: new_dims = {times} followed by current dims. + std::vector<DimSize_t> newDims; + newDims.push_back(static_cast<DimSize_t>(times)); + for (const auto &d : dims()) { + newDims.push_back(d); + } + + // Create an output tensor with the new dimensions. + Tensor out(newDims); + out.setDataType(dataType(), false); + out.setDataFormat(dataFormat()); + if (hasImpl()) { + out.setBackend(getImpl()->backend(), device()); + } + + // Each "block" is a copy of the data from the original tensor. + const std::size_t block = src.size(); + // Loop over the repeat count and copy the block each time. + for (int i = 0; i < times; ++i) { + // out.getImpl()->copy(source pointer, number of elements, destination offset) + out.getImpl()->copy(src.getImpl()->rawPtr(src.getImplOffset()), + block, + i * block); + } + return out; +} + std::vector<std::size_t> Tensor::toCoord(const std::vector<DimSize_t>& dimensions, std::size_t index) {