20#ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_FILE_H
21#define MLIR_EXECUTIONENGINE_SPARSETENSOR_FILE_H
49template <
typename V,
bool IsPattern>
50inline std::enable_if_t<!is_complex<V>::value, V>
readValue(
char **linePtr) {
54 if constexpr (IsPattern)
56 return strtod(*linePtr, linePtr);
62template <
typename V,
bool IsPattern>
63inline std::enable_if_t<is_complex<V>::value, V>
readValue(
char **linePtr) {
68 if constexpr (IsPattern)
70 double re = strtod(*linePtr, linePtr);
71 double im = strtod(*linePtr, linePtr);
109 assert(filename &&
"Received nullptr for filename");
120 const uint64_t *dimShape,
127 "Tensor element type %d not compatible with values in file %s\n",
128 static_cast<int>(valTp), filename);
162 assert(
isValid() &&
"Attempt to isPattern() before readHeader()");
169 assert(
isValid() &&
"Attempt to isSymmetric() before readHeader()");
176 assert(
isValid() &&
"Attempt to getRank() before readHeader()");
183 assert(
isValid() &&
"Attempt to getNSE() before readHeader()");
195 assert(d <
getRank() &&
"Dimension out of bounds");
206 template <
typename P,
typename C,
typename V>
209 const LevelType *lvlTypes,
const uint64_t *dim2lvl,
210 const uint64_t *lvl2dim) {
211 const uint64_t dimRank =
getRank();
212 MapRef map(dimRank, lvlRank, dim2lvl, lvl2dim);
213 auto *lvlCOO = readCOO<V>(map, lvlSizes);
215 dimRank,
getDimSizes(), lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim,
224 template <
typename C,
typename V>
225 bool readToBuffers(uint64_t lvlRank,
const uint64_t *dim2lvl,
226 const uint64_t *lvl2dim, C *lvlCoordinates, V *values);
235 template <
typename C>
236 char *readCoords(C *dimCoords) {
239 char *linePtr = line;
240 for (uint64_t dimRank =
getRank(), d = 0; d < dimRank; ++d) {
242 while (std::isspace(
static_cast<unsigned char>(*linePtr)))
245 char *coordinateEnd =
nullptr;
246 unsigned long long coordinate = strtoull(linePtr, &coordinateEnd, 10);
247 if (*linePtr ==
'-' || coordinateEnd == linePtr || errno == ERANGE ||
248 coordinate > std::numeric_limits<uint64_t>::max()) {
250 "Cannot parse coordinate for dimension %" PRIu64
" in %s\n", d,
254 linePtr = coordinateEnd;
255 uint64_t c = coordinate;
258 "Coordinate %" PRIu64
" is out of bounds for dimension %" PRIu64
259 " with size %" PRIu64
" in %s\n",
263 if (c - 1 > std::numeric_limits<C>::max()) {
265 "Coordinate %" PRIu64
266 " cannot be represented by the requested coordinate type in "
272 dimCoords[d] =
static_cast<C>(c - 1);
278 template <
typename V>
279 SparseTensorCOO<V> *readCOO(
const MapRef &map,
const uint64_t *lvlSizes);
283 template <
typename V,
bool IsPattern>
284 void readCOOLoop(
const MapRef &map, SparseTensorCOO<V> *coo);
289 template <
typename C,
typename V,
bool IsPattern>
290 bool readToBuffersLoop(
const MapRef &map, C *lvlCoordinates, V *values);
293 void readMMEHeader();
299 void readExtFROSTTHeader();
301 static constexpr uint64_t kMaxRank = 510;
302 static constexpr int kColWidth = 1025;
303 const char *
const filename;
304 FILE *file =
nullptr;
306 bool isSymmetric_ =
false;
307 uint64_t idata[kMaxRank + 2];
308 char line[kColWidth];
319 const uint64_t *lvlSizes) {
320 assert(
isValid() &&
"Attempt to readCOO() before readHeader()");
322 auto *coo =
new SparseTensorCOO<V>(map.getLvlRank(), lvlSizes,
getNSE());
325 readCOOLoop<V, true>(map, coo);
327 readCOOLoop<V, false>(map, coo);
333template <
typename V,
bool IsPattern>
334void SparseTensorReader::readCOOLoop(
const MapRef &map,
336 const uint64_t dimRank = map.getDimRank();
337 const uint64_t lvlRank = map.getLvlRank();
339 std::vector<uint64_t> dimCoords(dimRank);
340 std::vector<uint64_t> lvlCoords(lvlRank);
341 for (uint64_t k = 0, nse =
getNSE(); k < nse; k++) {
342 char *linePtr = readCoords(dimCoords.data());
344 map.pushforward(dimCoords.data(), lvlCoords.data());
345 coo->add(lvlCoords, value);
349template <
typename C,
typename V>
351 const uint64_t *dim2lvl,
352 const uint64_t *lvl2dim,
353 C *lvlCoordinates, V *values) {
354 assert(
isValid() &&
"Attempt to readCOO() before readHeader()");
357 isPattern() ? readToBuffersLoop<C, V, true>(map, lvlCoordinates, values)
358 : readToBuffersLoop<C, V, false>(map, lvlCoordinates, values);
363template <
typename C,
typename V,
bool IsPattern>
364bool SparseTensorReader::readToBuffersLoop(
const MapRef &map, C *lvlCoordinates,
368 const uint64_t nse =
getNSE();
370 std::vector<C> dimCoords(dimRank);
371 bool isSorted =
false;
373 const auto readNextElement = [&]() {
374 linePtr = readCoords<C>(dimCoords.data());
380 C *prevLvlCoords = lvlCoordinates - lvlRank;
381 for (uint64_t l = 0; l < lvlRank; ++l) {
382 if (prevLvlCoords[l] != lvlCoordinates[l]) {
383 if (prevLvlCoords[l] > lvlCoordinates[l])
389 lvlCoordinates += lvlRank;
394 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
A memory-resident sparse tensor in coordinate-scheme representation (a collection of Elements).
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.
SparseTensorStorage< P, C, 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...
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.
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.
const uint64_t * getDimSizes() const
Gets the dimension-sizes array.
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.
SparseTensorReader & operator=(const SparseTensorReader &)=delete
uint64_t getRank() const
Gets the dimension-rank of the tensor.
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...
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.
This file contains the declaration of the mlir::NonFloatComplex type and mlir::Complex type alias.
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.