@@ -301,8 +301,8 @@ class SparseTensorStorage final : public SparseTensorStorageBase {
301
301
uint64_t lvlRank = getLvlRank ();
302
302
uint64_t valIdx = 0 ;
303
303
// Linearize the address.
304
- for (uint64_t lvl = 0 ; lvl < lvlRank; lvl ++)
305
- valIdx = valIdx * getLvlSize (lvl ) + lvlCoords[lvl ];
304
+ for (uint64_t l = 0 ; l < lvlRank; l ++)
305
+ valIdx = valIdx * getLvlSize (l ) + lvlCoords[l ];
306
306
values[valIdx] = val;
307
307
return ;
308
308
}
@@ -472,9 +472,10 @@ class SparseTensorStorage final : public SparseTensorStorageBase {
472
472
uint64_t assembledSize (uint64_t parentSz, uint64_t l) const {
473
473
if (isCompressedLvl (l))
474
474
return positions[l][parentSz];
475
- if (isSingletonLvl (l))
476
- return parentSz; // New size is same as the parent.
477
- // TODO: support levels assignment for loose/2:4?
475
+ if (isLooseCompressedLvl (l))
476
+ return positions[l][2 * parentSz - 1 ];
477
+ if (isSingletonLvl (l) || is2OutOf4Lvl (l))
478
+ return parentSz; // new size same as the parent
478
479
assert (isDenseLvl (l));
479
480
return parentSz * getLvlSize (l);
480
481
}
@@ -766,40 +767,59 @@ SparseTensorStorage<P, C, V>::SparseTensorStorage(
766
767
const uint64_t *dim2lvl, const uint64_t *lvl2dim, const intptr_t *lvlBufs)
767
768
: SparseTensorStorage(dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes,
768
769
dim2lvl, lvl2dim) {
770
+ // Note that none of the buffers can be reused because ownership
771
+ // of the memory passed from clients is not necessarily transferred.
772
+ // Therefore, all data is copied over into a new SparseTensorStorage.
773
+ //
774
+ // TODO: this needs to be generalized to all formats AND
775
+ // we need a proper audit of e.g. double compressed
776
+ // levels where some are not filled
777
+ //
769
778
uint64_t trailCOOLen = 0 , parentSz = 1 , bufIdx = 0 ;
770
779
for (uint64_t l = 0 ; l < lvlRank; l++) {
771
- if (!isUniqueLvl (l) && isCompressedLvl (l)) {
772
- // A `compressed_nu` level marks the start of trailing COO start level.
773
- // Since the coordinate buffer used for trailing COO are passed in as AoS
774
- // scheme, and SparseTensorStorage uses a SoA scheme, we can not simply
775
- // copy the value from the provided buffers.
780
+ if (!isUniqueLvl (l) && ( isCompressedLvl (l) || isLooseCompressedLvl (l) )) {
781
+ // A `(loose) compressed_nu` level marks the start of trailing COO
782
+ // start level. Since the coordinate buffer used for trailing COO
783
+ // is passed in as AoS scheme and SparseTensorStorage uses a SoA
784
+ // scheme, we cannot simply copy the value from the provided buffers.
776
785
trailCOOLen = lvlRank - l;
777
786
break ;
778
787
}
779
- assert (!isSingletonLvl (l) &&
780
- " Singleton level not following a compressed_nu level" );
781
- if (isCompressedLvl (l)) {
788
+ if (isCompressedLvl (l) || isLooseCompressedLvl (l)) {
782
789
P *posPtr = reinterpret_cast <P *>(lvlBufs[bufIdx++]);
783
790
C *crdPtr = reinterpret_cast <C *>(lvlBufs[bufIdx++]);
784
- // Copies the lvlBuf into the vectors. The buffer can not be simply reused
785
- // because the memory passed from users is not necessarily allocated on
786
- // heap.
787
- positions[l].assign (posPtr, posPtr + parentSz + 1 );
788
- coordinates[l].assign (crdPtr, crdPtr + positions[l][parentSz]);
791
+ if (isLooseCompressedLvl (l)) {
792
+ positions[l].assign (posPtr, posPtr + 2 * parentSz);
793
+ coordinates[l].assign (crdPtr, crdPtr + positions[l][2 * parentSz - 1 ]);
794
+ } else {
795
+ positions[l].assign (posPtr, posPtr + parentSz + 1 );
796
+ coordinates[l].assign (crdPtr, crdPtr + positions[l][parentSz]);
797
+ }
798
+ } else if (isSingletonLvl (l)) {
799
+ assert (0 && " general singleton not supported yet" );
800
+ } else if (is2OutOf4Lvl (l)) {
801
+ assert (0 && " 2Out4 not supported yet" );
789
802
} else {
790
- // TODO: support levels assignment for loose/2:4?
791
803
assert (isDenseLvl (l));
792
804
}
793
805
parentSz = assembledSize (parentSz, l);
794
806
}
795
807
808
+ // Handle Aos vs. SoA mismatch for COO.
796
809
if (trailCOOLen != 0 ) {
797
810
uint64_t cooStartLvl = lvlRank - trailCOOLen;
798
- assert (!isUniqueLvl (cooStartLvl) && isCompressedLvl (cooStartLvl));
811
+ assert (!isUniqueLvl (cooStartLvl) &&
812
+ (isCompressedLvl (cooStartLvl) || isLooseCompressedLvl (cooStartLvl)));
799
813
P *posPtr = reinterpret_cast <P *>(lvlBufs[bufIdx++]);
800
814
C *aosCrdPtr = reinterpret_cast <C *>(lvlBufs[bufIdx++]);
801
- positions[cooStartLvl].assign (posPtr, posPtr + parentSz + 1 );
802
- P crdLen = positions[cooStartLvl][parentSz];
815
+ P crdLen;
816
+ if (isLooseCompressedLvl (cooStartLvl)) {
817
+ positions[cooStartLvl].assign (posPtr, posPtr + 2 * parentSz);
818
+ crdLen = positions[cooStartLvl][2 * parentSz - 1 ];
819
+ } else {
820
+ positions[cooStartLvl].assign (posPtr, posPtr + parentSz + 1 );
821
+ crdLen = positions[cooStartLvl][parentSz];
822
+ }
803
823
for (uint64_t l = cooStartLvl; l < lvlRank; l++) {
804
824
coordinates[l].resize (crdLen);
805
825
for (uint64_t n = 0 ; n < crdLen; n++) {
@@ -809,6 +829,7 @@ SparseTensorStorage<P, C, V>::SparseTensorStorage(
809
829
parentSz = assembledSize (parentSz, cooStartLvl);
810
830
}
811
831
832
+ // Copy the values buffer.
812
833
V *valPtr = reinterpret_cast <V *>(lvlBufs[bufIdx]);
813
834
values.assign (valPtr, valPtr + parentSz);
814
835
}
0 commit comments