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> &&
33 "Value type is not floating point");
34 assert(byte2 == std::is_signed_v<T> &&
"Value type is not signed");
35 assert(byte3 == columnMajor &&
"Major direction does not match");
39 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
40 void SparseMatrix<T, indexT, compressionLevel, columnMajor>::userChecks() {
41 assert((innerDim >= 1 || outerDim >= 1) &&
42 "The matrix must have at least one row, column, and nonzero value");
43 assert(std::is_floating_point<indexT>::value ==
false &&
44 "The index type must be a non-floating point type");
45 assert((compressionLevel == 3) &&
"The compression level must be 3");
46 assert((std::is_arithmetic<T>::value && std::is_arithmetic<indexT>::value) &&
47 "The value and index types must be numeric types");
48 assert((std::is_same<indexT, bool>::value ==
false) &&
49 "The index type must not be bool");
50 assert((innerDim < std::numeric_limits<indexT>::max() &&
51 outerDim < std::numeric_limits<indexT>::max()) &&
52 "The number of rows and columns must be less than the maximum value "
58 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
59 void SparseMatrix<T, indexT, compressionLevel, columnMajor>::calculateCompSize() {
64 compSize += META_DATA_SIZE;
67 compSize += (
sizeof(
void *) * outerDim) * 2;
70 for (uint32_t i = 0; i < outerDim; i++) {
71 compSize += *((uint8_t **)endPointers + i) - *((uint8_t **)data + i);
76 template <
typename T,
typename indexT, u
int8_t compressionLevel,
bool columnMajor>
77 template <
typename T2,
typename indexT2>
void SparseMatrix<T, indexT, compressionLevel, columnMajor>::compressCSC(
78 T2 *vals, indexT2 *innerIndices, indexT2 *outerPointers) {
84 index_t =
sizeof(indexT);
87 metadata =
new uint32_t[NUM_META_DATA];
88 metadata[0] = compressionLevel;
89 metadata[1] = innerDim;
90 metadata[2] = outerDim;
93 metadata[5] = index_t;
102 data = (
void **)malloc(outerDim *
sizeof(
void *));
103 endPointers = (
void **)malloc(outerDim *
sizeof(
void *));
104 }
catch (std::bad_alloc &e) {
105 std::cout <<
"Error: " << e.what() << std::endl;
114 #ifdef IVSPARSE_HAS_OPENMP
115 #pragma omp parallel for
117 for (uint32_t i = 0; i < outerDim; i++) {
119 std::map<T2, std::vector<indexT2>>
123 if (outerPointers[i] == outerPointers[i + 1]) {
125 endPointers[i] =
nullptr;
130 for (indexT2 j = outerPointers[i]; j < outerPointers[i + 1]; j++) {
132 if (dict.find(vals[j]) != dict.end()) {
136 dict[vals[j]].push_back(innerIndices[j] - dict[vals[j]][1]);
139 dict[vals[j]][1] = innerIndices[j];
142 if (dict[vals[j]][dict[vals[j]].size() - 1] > dict[vals[j]][0]) {
143 dict[vals[j]][0] = dict[vals[j]][dict[vals[j]].size() - 1];
149 dict[vals[j]] = std::vector<indexT2>{innerIndices[j]};
152 dict[vals[j]].push_back(innerIndices[j]);
153 dict[vals[j]].push_back(innerIndices[j]);
161 size_t outerByteSize = 0;
164 for (
auto &pair : dict) {
166 pair.second[0] = byteWidth(pair.second[0]);
170 outerByteSize +=
sizeof(T) + 1 +
171 (pair.second[0] * (pair.second.size() - 2)) +
177 data[i] = malloc(outerByteSize);
178 }
catch (std::bad_alloc &e) {
179 std::cout <<
"Error: " << e.what() << std::endl;
186 void *helpPtr = data[i];
189 for (
auto &pair : dict) {
191 *(T *)helpPtr = (T)pair.first;
192 helpPtr = (T *)helpPtr + 1;
195 *(uint8_t *)helpPtr = (uint8_t)pair.second[0];
196 helpPtr = (uint8_t *)helpPtr + 1;
199 for (
size_t k = 0; k < pair.second.size(); k++) {
201 if (k == 0 || k == 1) {
206 switch (pair.second[0]) {
208 *(uint8_t *)helpPtr = (uint8_t)pair.second[k];
209 helpPtr = (uint8_t *)helpPtr + 1;
212 *(uint16_t *)helpPtr = (uint16_t)pair.second[k];
213 helpPtr = (uint16_t *)helpPtr + 1;
216 *(uint32_t *)helpPtr = (uint32_t)pair.second[k];
217 helpPtr = (uint32_t *)helpPtr + 1;
220 *(uint64_t *)helpPtr = (uint64_t)pair.second[k];
221 helpPtr = (uint64_t *)helpPtr + 1;
228 switch (pair.second[0]) {
230 *(uint8_t *)helpPtr = (uint8_t)DELIM;
231 helpPtr = (uint8_t *)helpPtr + 1;
234 *(uint16_t *)helpPtr = (uint16_t)DELIM;
235 helpPtr = (uint16_t *)helpPtr + 1;
238 *(uint32_t *)helpPtr = (uint32_t)DELIM;
239 helpPtr = (uint32_t *)helpPtr + 1;
242 *(uint64_t *)helpPtr = (uint64_t)DELIM;
243 helpPtr = (uint64_t *)helpPtr + 1;
247 endPointers[i] = helpPtr;