Skip to content
Snippets Groups Projects

Low bit support for ARM Cortex-M export

Merged Thibault Allenet requested to merge low_bit_support_arm into dev
All threads resolved!
3 files
+ 265
0
Compare changes
  • Side-by-side
  • Inline
Files
3
+ 105
0
#ifndef __CONVERT_CUSTOM_DATA_H__
#define __CONVERT_CUSTOM_DATA_H__
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <cmath>
#include "aidge/utils/ErrorHandling.hpp"
namespace Aidge {
/**
* @brief Calculates the required size for the 8-bits`compactData` vector.
*
* This function determines the minimum number of bytes needed in `compactData`
* to store `dataSize` elements compacted to `nb_bits` bits each.
*
* @param dataSize The total number of elements in the input data array.
* @param nb_bits The number of bits to use for each compacted element (from 1 to 7).
* @return std::size_t The required size in bytes for `compactData`.
*/
std::size_t compactDataSize(std::size_t dataSize, std::uint8_t nb_bits) {
AIDGE_ASSERT(nb_bits > 0 && nb_bits < 8, "nb_bits must be between 1 and 4"); // Ensure valid bit width
// Calculate the number of `nb_bits` segments that can fit in an 8-bit byte.
const unsigned int nbSlot = 8 / nb_bits;
// Calculate the number of compacted bytes needed to store all data elements.
// The formula (dataSize + nbSlot - 1) / nbSlot effectively rounds up the division, ensuring that any remaining elements that don't fully fill a byte are accounted for.
std::size_t requiredSize = (dataSize + nbSlot - 1) / nbSlot;
return requiredSize;
}
/**
* @brief Compacts 8-bit data into a smaller bit-width representation.
*
* This function takes an array of 8-bit data and compacts it into smaller chunks
* based on the specified bit-width `nb_bits`. Each element in `compactData` will
* store multiple packed `nb_bits` segments extracted from `data`.
*
* @param data The input array of 8-bit values to be compacted.
* @param dataSize The size of the input `data` array.
* @param compactData The output array storing the compacted data.
* @param nb_bits The number of bits to extract from each `data` element (must be less than 8).
*/
void compact_data(const std::int8_t* data, std::size_t dataSize, std::int8_t* compactData, std::uint8_t nb_bits) {
AIDGE_ASSERT(nb_bits > 0 && nb_bits < 5, "Cannot compact with the given nb_bits"); // Ensure valid bit width
// Mask to extract `nb_bits` from each data element
const unsigned int mask = (1U << nb_bits) - 1;
// Calculate the number of `nb_bits` segments that fit into an 8-bit compacted value
const unsigned int nbSlot = 8 / nb_bits;
// Case nb_bits=3 or 4, then shift is 4
// Case nb_bits=2, then shift is 2
// Case nb_bits=1, then shift is 1
std::uint8_t shift = 8 / nbSlot;
const unsigned int nbFullCompactbytes = dataSize / nbSlot;
// Main loop to process data in groups of `nbSlot`
for (std::size_t i = 0; i < nbFullCompactbytes; ++i) {
std::int8_t compact = 0;
for (unsigned int j = 0; j < nbSlot; ++j) {
compact |= (data[i * nbSlot + j] & mask); // Apply mask to keep `nb_bits` only
// Shift only if not on the last slot to make room for the next `nb_bits`
if (j < nbSlot - 1) {
compact <<= shift;
}
}
// Store the compacted value in the output array
compactData[i] = compact;
}
// Handle any remaining data elements (if dataSize is not a multiple of nbSlot).
std::size_t remaining = dataSize % nbSlot;
if (remaining != 0) {
std::int8_t compact = 0;
for (std::size_t j = 0; j < remaining; ++j) {
compact |= (data[nbFullCompactbytes*nbSlot + j] & mask);
if (j < remaining - 1) {
compact <<= shift;
}
}
compact <<= (shift*(nbSlot - remaining));
// Store the last compacted value
compactData[dataSize / nbSlot] = compact;
}
}
}
#endif
\ No newline at end of file
Loading