1010#include < algorithm>
1111#include < compare>
1212#include < iterator>
13+ #include < memory>
1314#include < vector>
1415
1516namespace nx ::core
@@ -410,6 +411,44 @@ class AbstractDataStore : public IDataStore
410411 */
411412 virtual void setValue (usize index, value_type value) = 0;
412413
414+ /* *
415+ * @brief Reads a contiguous range of values from the DataStore into a buffer.
416+ * Reads buffer.size() elements starting from startIndex.
417+ * @param startIndex The first flat element index to read from
418+ * @param buffer Span to write values into; buffer.size() determines count
419+ */
420+ virtual void getValues (usize startIndex, nonstd::span<T> buffer) const
421+ {
422+ const usize count = buffer.size ();
423+ if (startIndex + count > getSize ())
424+ {
425+ throw std::out_of_range (fmt::format (" AbstractDataStore::getValues: range [{}, {}) exceeds size {}" , startIndex, startIndex + count, getSize ()));
426+ }
427+ for (usize i = 0 ; i < count; i++)
428+ {
429+ buffer[i] = getValue (startIndex + i);
430+ }
431+ }
432+
433+ /* *
434+ * @brief Writes a contiguous range of values from a buffer into the DataStore.
435+ * Writes buffer.size() elements starting at startIndex.
436+ * @param startIndex The first flat element index to write to
437+ * @param buffer Span of values to write; buffer.size() determines count
438+ */
439+ virtual void setValues (usize startIndex, nonstd::span<const T> buffer)
440+ {
441+ const usize count = buffer.size ();
442+ if (startIndex + count > getSize ())
443+ {
444+ throw std::out_of_range (fmt::format (" AbstractDataStore::setValues: range [{}, {}) exceeds size {}" , startIndex, startIndex + count, getSize ()));
445+ }
446+ for (usize i = 0 ; i < count; i++)
447+ {
448+ setValue (startIndex + i, buffer[i]);
449+ }
450+ }
451+
413452 /* *
414453 * @brief Returns the value found at the specified index of the DataStore.
415454 * This cannot be used to edit the value found at the specified index.
@@ -584,7 +623,16 @@ class AbstractDataStore : public IDataStore
584623 */
585624 virtual void fill (value_type value)
586625 {
587- std::fill (begin (), end (), value);
626+ const usize totalSize = getSize ();
627+ constexpr usize k_BulkBufferSize = 8192 ;
628+ const usize bufSize = (std::min)(totalSize, k_BulkBufferSize);
629+ auto buffer = std::make_unique<T[]>(bufSize);
630+ std::fill_n (buffer.get (), bufSize, value);
631+ for (usize offset = 0 ; offset < totalSize; offset += bufSize)
632+ {
633+ const usize batchSize = (std::min)(bufSize, totalSize - offset);
634+ setValues (offset, nonstd::span<const T>(buffer.get (), batchSize));
635+ }
588636 }
589637
590638 /* *
@@ -599,7 +647,17 @@ class AbstractDataStore : public IDataStore
599647 {
600648 return false ;
601649 }
602- std::copy (other.begin (), other.end (), begin ());
650+ const usize totalSize = getSize ();
651+ constexpr usize k_BulkBufferSize = 8192 ;
652+ const usize bufSize = (std::min)(totalSize, k_BulkBufferSize);
653+ auto buffer = std::make_unique<T[]>(bufSize);
654+ for (usize offset = 0 ; offset < totalSize; offset += bufSize)
655+ {
656+ const usize batchSize = (std::min)(bufSize, totalSize - offset);
657+ nonstd::span<T> bufSpan (buffer.get (), batchSize);
658+ other.getValues (offset, bufSpan);
659+ setValues (offset, nonstd::span<const T>(buffer.get (), batchSize));
660+ }
603661 return true ;
604662 }
605663
@@ -677,10 +735,25 @@ class AbstractDataStore : public IDataStore
677735 totalSrcTuples * sourceNumComponents, destTupleOffset * numComponents, getSize ()));
678736 }
679737
680- auto srcBegin = source.begin () + (srcTupleOffset * sourceNumComponents);
681- auto srcEnd = srcBegin + (totalSrcTuples * sourceNumComponents);
682- auto dstBegin = begin () + (destTupleOffset * numComponents);
683- std::copy (srcBegin, srcEnd, dstBegin);
738+ const usize totalElements = totalSrcTuples * sourceNumComponents;
739+ const usize srcStartIndex = srcTupleOffset * sourceNumComponents;
740+ const usize dstStartIndex = destTupleOffset * numComponents;
741+ constexpr usize k_BulkBufferSize = 8192 ;
742+ const usize bufSize = (std::min)(totalElements, k_BulkBufferSize);
743+ auto tempBuffer = std::make_unique<T[]>(bufSize);
744+ usize remaining = totalElements;
745+ usize srcOffset = srcStartIndex;
746+ usize dstOffset = dstStartIndex;
747+ while (remaining > 0 )
748+ {
749+ const usize batchSize = (std::min)(remaining, bufSize);
750+ nonstd::span<T> bufSpan (tempBuffer.get (), batchSize);
751+ source.getValues (srcOffset, bufSpan);
752+ setValues (dstOffset, nonstd::span<const T>(tempBuffer.get (), batchSize));
753+ srcOffset += batchSize;
754+ dstOffset += batchSize;
755+ remaining -= batchSize;
756+ }
684757 return {};
685758 }
686759
@@ -693,10 +766,9 @@ class AbstractDataStore : public IDataStore
693766 {
694767 usize numComponents = getNumberOfComponents ();
695768 index_type offset = tupleIndex * numComponents;
696- for (usize i = 0 ; i < numComponents; i++)
697- {
698- setValue (offset + i, value);
699- }
769+ auto tupleValues = std::make_unique<T[]>(numComponents);
770+ std::fill_n (tupleValues.get (), numComponents, value);
771+ setValues (offset, nonstd::span<const T>(tupleValues.get (), numComponents));
700772 }
701773
702774 /* *
@@ -743,13 +815,8 @@ class AbstractDataStore : public IDataStore
743815 throw std::runtime_error (ss);
744816 }
745817
746- index_type numComponents = getNumberOfComponents ();
747- index_type offset = tupleIndex * numComponents;
748- usize count = values.size ();
749- for (usize i = 0 ; i < count; i++)
750- {
751- setValue (offset + i, values[i]);
752- }
818+ index_type offset = tupleIndex * getNumberOfComponents ();
819+ setValues (offset, values);
753820 }
754821
755822 /* *
0 commit comments