14 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
15 void SparseMatrix<T, indexT, compressionLevel, columnMajor>::encodeValueType() {
16 uint8_t byte0 =
sizeof(T);
17 uint8_t byte1 = std::is_floating_point<T>::value ? 1 : 0;
18 uint8_t byte2 = std::is_signed_v<T> ? 1 : 0;
19 uint8_t byte3 = columnMajor ? 1 : 0;
21 val_t = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
25 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
26 void SparseMatrix<T, indexT, compressionLevel, columnMajor>::checkValueType() {
27 uint8_t byte0 = val_t & 0xFF;
28 uint8_t byte1 = (val_t >> 8) & 0xFF;
29 uint8_t byte2 = (val_t >> 16) & 0xFF;
30 uint8_t byte3 = (val_t >> 24) & 0xFF;
31 assert(byte0 ==
sizeof(T) &&
"Value type size does not match");
32 assert(byte1 == std::is_floating_point_v<T> &&
"Value type is not floating point");
33 assert(byte2 == std::is_signed_v<T> &&
"Value type is not signed");
34 assert(byte3 == columnMajor &&
"Major direction does not match");
38 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
39 void SparseMatrix<T, indexT, compressionLevel, columnMajor>::userChecks() {
40 assert((innerDim >= 1 || outerDim >= 1) &&
"The matrix must have at least one row, column, and nonzero value");
41 assert(std::is_floating_point<indexT>::value ==
false &&
"The index type must be a non-floating point type");
42 assert((compressionLevel == 3) &&
"The compression level must be 3");
43 assert((std::is_arithmetic<T>::value && std::is_arithmetic<indexT>::value) &&
"The value and index types must be numeric types");
44 assert((std::is_same<indexT, bool>::value ==
false) &&
"The index type must not be bool");
45 assert((innerDim < std::numeric_limits<indexT>::max() && outerDim < std::numeric_limits<indexT>::max()) &&
"The number of rows and columns must be less than the maximum value of the index type");
50 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
51 void SparseMatrix<T, indexT, compressionLevel, columnMajor>::calculateCompSize() {
56 compSize += META_DATA_SIZE;
59 compSize += (
sizeof(
void *) * outerDim) * 2;
62 for (uint32_t i = 0; i < outerDim; i++) { compSize += *((uint8_t **)endPointers + i) - *((uint8_t **)data + i); }
66 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
67 template <
typename T2,
typename indexT2>
68 void SparseMatrix<T, indexT, compressionLevel, columnMajor>::compressCSC(T2 *vals, indexT2 *innerIndices, indexT2 *outerPointers) {
73 index_t =
sizeof(indexT);
76 metadata =
new uint32_t[NUM_META_DATA];
77 metadata[0] = compressionLevel;
78 metadata[1] = innerDim;
79 metadata[2] = outerDim;
82 metadata[5] = index_t;
91 data = (
void **)malloc(outerDim *
sizeof(
void *));
92 endPointers = (
void **)malloc(outerDim *
sizeof(
void *));
93 }
catch (std::bad_alloc &e) {
94 std::cout <<
"Error: " << e.what() << std::endl;
102 #pragma omp parallel for
104 for (uint32_t i = 0; i < outerDim; i++) {
106 std::map<T2, std::vector<indexT2>> dict;
109 if (outerPointers[i] == outerPointers[i + 1]) {
111 endPointers[i] =
nullptr;
116 for (indexT2 j = outerPointers[i]; j < outerPointers[i + 1]; j++) {
119 if (dict.find(vals[j]) != dict.end()) {
124 dict[vals[j]].push_back(innerIndices[j] - dict[vals[j]][1]);
127 dict[vals[j]][1] = innerIndices[j];
130 if (dict[vals[j]][dict[vals[j]].size() - 1] > dict[vals[j]][0]) {
131 dict[vals[j]][0] = dict[vals[j]][dict[vals[j]].size() - 1];
137 dict[vals[j]] = std::vector<indexT2>{innerIndices[j]};
140 dict[vals[j]].push_back(innerIndices[j]);
141 dict[vals[j]].push_back(innerIndices[j]);
149 size_t outerByteSize = 0;
152 for (
auto &pair : dict) {
154 pair.second[0] = byteWidth(pair.second[0]);
158 outerByteSize +=
sizeof(T) + 1 + (pair.second[0] * (pair.second.size() - 2)) + pair.second[0];
163 data[i] = malloc(outerByteSize);
164 }
catch (std::bad_alloc &e) {
165 std::cout <<
"Error: " << e.what() << std::endl;
172 void *helpPtr = data[i];
175 for (
auto &pair : dict) {
177 *(T *)helpPtr = (T)pair.first;
178 helpPtr = (T *)helpPtr + 1;
181 *(uint8_t *)helpPtr = (uint8_t)pair.second[0];
182 helpPtr = (uint8_t *)helpPtr + 1;
185 for (
size_t k = 0; k < pair.second.size(); k++) {
188 if (k == 0 || k == 1) {
continue; }
191 switch (pair.second[0]) {
193 *(uint8_t *)helpPtr = (uint8_t)pair.second[k];
194 helpPtr = (uint8_t *)helpPtr + 1;
197 *(uint16_t *)helpPtr = (uint16_t)pair.second[k];
198 helpPtr = (uint16_t *)helpPtr + 1;
201 *(uint32_t *)helpPtr = (uint32_t)pair.second[k];
202 helpPtr = (uint32_t *)helpPtr + 1;
205 *(uint64_t *)helpPtr = (uint64_t)pair.second[k];
206 helpPtr = (uint64_t *)helpPtr + 1;
213 switch (pair.second[0]) {
215 *(uint8_t *)helpPtr = (uint8_t)DELIM;
216 helpPtr = (uint8_t *)helpPtr + 1;
219 *(uint16_t *)helpPtr = (uint16_t)DELIM;
220 helpPtr = (uint16_t *)helpPtr + 1;
223 *(uint32_t *)helpPtr = (uint32_t)DELIM;
224 helpPtr = (uint32_t *)helpPtr + 1;
227 *(uint64_t *)helpPtr = (uint64_t)DELIM;
228 helpPtr = (uint64_t *)helpPtr + 1;
232 endPointers[i] = helpPtr;