20 #ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_FILE_H
21 #define MLIR_EXECUTIONENGINE_SPARSETENSOR_FILE_H
29 namespace sparse_tensor {
37 struct is_complex<std::complex<T>> final :
public std::true_type {};
42 template <
typename V,
bool IsPattern>
43 inline std::enable_if_t<!is_complex<V>::value, V>
readValue(
char **linePtr) {
47 if constexpr (IsPattern)
49 return strtod(*linePtr, linePtr);
55 template <
typename V,
bool IsPattern>
56 inline std::enable_if_t<is_complex<V>::value, V>
readValue(
char **linePtr) {
61 if constexpr (IsPattern)
63 double re = strtod(*linePtr, linePtr);
64 double im = strtod(*linePtr, linePtr);
73 inline V
readValue(
char **linePtr,
bool isPattern) {
74 return isPattern ? readValue<V, true>(linePtr) : readValue<V, false>(linePtr);
102 assert(filename &&
"Received nullptr for filename");
113 const uint64_t *dimShape,
120 "Tensor element type %d not compatible with values in file %s\n",
121 static_cast<int>(valTp), filename);
155 assert(
isValid() &&
"Attempt to isPattern() before readHeader()");
162 assert(
isValid() &&
"Attempt to isSymmetric() before readHeader()");
169 assert(
isValid() &&
"Attempt to getRank() before readHeader()");
176 assert(
isValid() &&
"Attempt to getNSE() before readHeader()");
188 assert(d <
getRank() &&
"Dimension out of bounds");
199 template <
typename P,
typename I,
typename V>
202 const LevelType *lvlTypes,
const uint64_t *dim2lvl,
203 const uint64_t *lvl2dim) {
204 const uint64_t dimRank =
getRank();
205 MapRef map(dimRank, lvlRank, dim2lvl, lvl2dim);
206 auto *lvlCOO = readCOO<V>(map, lvlSizes);
208 dimRank,
getDimSizes(), lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim,
217 template <
typename C,
typename V>
218 bool readToBuffers(uint64_t lvlRank,
const uint64_t *dim2lvl,
219 const uint64_t *lvl2dim, C *lvlCoordinates, V *values);
228 template <
typename C>
229 char *readCoords(C *dimCoords) {
232 char *linePtr = line;
233 for (uint64_t dimRank =
getRank(), d = 0; d < dimRank; ++d) {
235 uint64_t c = strtoul(linePtr, &linePtr, 10);
237 dimCoords[d] =
static_cast<C
>(c - 1);
243 template <
typename V>
244 SparseTensorCOO<V> *readCOO(
const MapRef &map,
const uint64_t *lvlSizes);
248 template <
typename V,
bool IsPattern>
249 void readCOOLoop(
const MapRef &map, SparseTensorCOO<V> *coo);
254 template <
typename C,
typename V,
bool IsPattern>
255 bool readToBuffersLoop(
const MapRef &map, C *lvlCoordinates, V *values);
258 void readMMEHeader();
264 void readExtFROSTTHeader();
266 static constexpr
int kColWidth = 1025;
267 const char *
const filename;
268 FILE *file =
nullptr;
270 bool isSymmetric_ =
false;
272 char line[kColWidth];
281 template <
typename V>
282 SparseTensorCOO<V> *SparseTensorReader::readCOO(
const MapRef &map,
283 const uint64_t *lvlSizes) {
284 assert(
isValid() &&
"Attempt to readCOO() before readHeader()");
286 auto *coo =
new SparseTensorCOO<V>(map.getLvlRank(), lvlSizes,
getNSE());
289 readCOOLoop<V, true>(map, coo);
291 readCOOLoop<V, false>(map, coo);
297 template <
typename V,
bool IsPattern>
298 void SparseTensorReader::readCOOLoop(
const MapRef &map,
299 SparseTensorCOO<V> *coo) {
300 const uint64_t dimRank = map.getDimRank();
301 const uint64_t lvlRank = map.getLvlRank();
303 std::vector<uint64_t> dimCoords(dimRank);
304 std::vector<uint64_t> lvlCoords(lvlRank);
305 for (uint64_t k = 0, nse =
getNSE(); k < nse; k++) {
306 char *linePtr = readCoords(dimCoords.data());
307 const V value = detail::readValue<V, IsPattern>(&linePtr);
308 map.pushforward(dimCoords.data(), lvlCoords.data());
309 coo->add(lvlCoords, value);
313 template <
typename C,
typename V>
315 const uint64_t *dim2lvl,
316 const uint64_t *lvl2dim,
317 C *lvlCoordinates, V *values) {
318 assert(
isValid() &&
"Attempt to readCOO() before readHeader()");
321 isPattern() ? readToBuffersLoop<C, V, true>(map, lvlCoordinates, values)
322 : readToBuffersLoop<C, V, false>(map, lvlCoordinates, values);
327 template <
typename C,
typename V,
bool IsPattern>
328 bool SparseTensorReader::readToBuffersLoop(
const MapRef &map, C *lvlCoordinates,
332 const uint64_t nse =
getNSE();
334 std::vector<C> dimCoords(dimRank);
335 bool isSorted =
false;
337 const auto readNextElement = [&]() {
338 linePtr = readCoords<C>(dimCoords.data());
340 *values = detail::readValue<V, IsPattern>(&linePtr);
344 C *prevLvlCoords = lvlCoordinates - lvlRank;
345 for (uint64_t l = 0; l < lvlRank; ++l) {
346 if (prevLvlCoords[l] != lvlCoordinates[l]) {
347 if (prevLvlCoords[l] > lvlCoordinates[l])
353 lvlCoordinates += lvlRank;
358 for (uint64_t n = 1; n < nse; ++n)
A class for capturing the sparse tensor type map with a compact encoding.
void pushforward(const T *in, T *out) const
uint64_t getLvlRank() const
uint64_t getDimRank() const
This class abstracts over the information stored in file headers, as well as providing the buffers an...
void assertMatchesShape(uint64_t rank, const uint64_t *shape) const
Asserts the shape subsumes the actual dimension sizes.
bool isPattern() const
Gets the MME "pattern" property setting.
void closeFile()
Closes the file.
SparseTensorReader & operator=(const SparseTensorReader &)=delete
uint64_t getDimSize(uint64_t d) const
Safely gets the size of the given dimension.
SparseTensorReader(const SparseTensorReader &)=delete
void readHeader()
Reads and parses the file's header.
const uint64_t * getDimSizes() const
Gets the dimension-sizes array.
bool canReadAs(PrimaryType valTy) const
Checks if the file's ValueKind can be converted into the given tensor PrimaryType.
uint64_t getNSE() const
Gets the number of stored elements.
bool isValid() const
Checks if a header has been successfully read.
ValueKind getValueKind() const
Returns the stored value kind.
SparseTensorStorage< P, I, V > * readSparseTensor(uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, const uint64_t *lvl2dim)
Allocates a new sparse-tensor storage object with the given encoding, initializes it by reading all t...
bool readToBuffers(uint64_t lvlRank, const uint64_t *dim2lvl, const uint64_t *lvl2dim, C *lvlCoordinates, V *values)
Reads the COO tensor from the file, stores the coordinates and values to the given buffers,...
bool isSymmetric() const
Gets the MME "symmetric" property setting.
static SparseTensorReader * create(const char *filename, uint64_t dimRank, const uint64_t *dimShape, PrimaryType valTp)
Factory method to allocate a new reader, open the file, read the header, and validate that the actual...
uint64_t getRank() const
Gets the dimension-rank of the tensor.
SparseTensorReader(const char *filename)
void openFile()
Opens the file for reading.
A memory-resident sparse tensor using a storage scheme based on per-level sparse/dense annotations.
static SparseTensorStorage< P, C, V > * newFromCOO(uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, const uint64_t *lvl2dim, SparseTensorCOO< V > *lvlCOO)
Allocates a new sparse tensor and initializes it from the given COO.
std::enable_if_t<!is_complex< V >::value, V > readValue(char **linePtr)
Returns an element-value of non-complex type.
PrimaryType
Encoding of the elemental type, for "overloading" @newSparseTensor.
Include the generated interface declarations.
This enum defines all the sparse representations supportable by the SparseTensor dialect.