Line data Source code
1 : #include "PartitionDescriptor.h" 2 : #include "Error.h" 3 : #include "TypeCasts.hpp" 4 : 5 : #include <unordered_map> 6 : #include <type_traits> 7 : 8 : namespace elsa 9 : { 10 : PartitionDescriptor::PartitionDescriptor(const DataDescriptor& dataDescriptor, 11 : index_t numberOfBlocks) 12 : : BlockDescriptor{dataDescriptor}, 13 : _indexMap(numberOfBlocks), 14 : _blockDescriptors(0), 15 : _blockOffsets(numberOfBlocks) 16 34765 : { 17 34765 : if (numberOfBlocks < 2) 18 1 : throw InvalidArgumentError( 19 1 : "PartitionDescriptor: number of blocks must be greater than one"); 20 : 21 34764 : index_t lastDimSize = _numberOfCoefficientsPerDimension[_numberOfDimensions - 1]; 22 : 23 34764 : if (numberOfBlocks > lastDimSize) 24 1 : throw InvalidArgumentError( 25 1 : "PartitionDescriptor: number of blocks too large for given descriptor"); 26 : 27 34763 : index_t rest = lastDimSize % numberOfBlocks; 28 : 29 34763 : auto blockDesc = generateDescriptorOfPartition(lastDimSize / numberOfBlocks); 30 34763 : _blockDescriptors.push_back(std::move(blockDesc)); 31 34763 : _indexMap.head(numberOfBlocks - rest).setZero(); 32 1071232 : for (index_t i = 0; i < numberOfBlocks && i <= numberOfBlocks - rest; i++) 33 1036469 : _blockOffsets[i] = i * _blockDescriptors[0]->getNumberOfCoefficients(); 34 : 35 34763 : if (rest > 0) { 36 13 : blockDesc = generateDescriptorOfPartition(lastDimSize / numberOfBlocks + 1); 37 13 : _blockDescriptors.push_back(std::move(blockDesc)); 38 13 : _indexMap.tail(rest).array().setConstant(1); 39 13 : auto numCoeffs = _blockDescriptors[1]->getNumberOfCoefficients(); 40 62 : for (index_t i = numberOfBlocks - rest + 1; i < numberOfBlocks; i++) 41 49 : _blockOffsets[i] = _blockOffsets[i - 1] + numCoeffs; 42 13 : } 43 34763 : } 44 : 45 : PartitionDescriptor::PartitionDescriptor(const DataDescriptor& dataDescriptor, 46 : IndexVector_t slicesInBlock) 47 : : BlockDescriptor{dataDescriptor}, 48 : _indexMap(slicesInBlock.size()), 49 : _blockDescriptors(0), 50 : _blockOffsets(slicesInBlock.size()) 51 87 : { 52 87 : if (slicesInBlock.size() < 2) 53 1 : throw InvalidArgumentError( 54 1 : "PartitionDescriptor: number of blocks must be greater than one"); 55 : 56 86 : if ((slicesInBlock.array() <= 0).any()) 57 1 : throw InvalidArgumentError( 58 1 : "PartitionDescriptor: non-positive number of coefficients not allowed"); 59 : 60 85 : if (slicesInBlock.sum() != _numberOfCoefficientsPerDimension[_numberOfDimensions - 1]) 61 1 : throw InvalidArgumentError("PartitionDescriptor: cumulative size of partitioned " 62 1 : "descriptor does not match size of original descriptor"); 63 : 64 84 : std::unordered_map<index_t, index_t> sizeToIndex; 65 84 : _blockOffsets[0] = 0; 66 434 : for (index_t i = 0; i < getNumberOfBlocks(); i++) { 67 350 : auto it = sizeToIndex.find(slicesInBlock[i]); 68 350 : index_t numCoeffs; 69 : 70 350 : if (it != sizeToIndex.end()) { 71 208 : _indexMap[i] = it->second; 72 208 : auto index = static_cast<size_t>(it->second); 73 208 : numCoeffs = _blockDescriptors[index]->getNumberOfCoefficients(); 74 208 : } else { 75 142 : sizeToIndex.insert({slicesInBlock[i], _blockDescriptors.size()}); 76 142 : _indexMap[i] = static_cast<index_t>(_blockDescriptors.size()); 77 142 : _blockDescriptors.push_back(generateDescriptorOfPartition(slicesInBlock[i])); 78 142 : numCoeffs = _blockDescriptors.back()->getNumberOfCoefficients(); 79 142 : } 80 : 81 350 : if (i != getNumberOfBlocks() - 1) 82 266 : _blockOffsets[i + 1] = _blockOffsets[i] + numCoeffs; 83 350 : } 84 84 : } 85 : 86 : PartitionDescriptor::PartitionDescriptor(const PartitionDescriptor& other) 87 : : BlockDescriptor(other), _indexMap(other._indexMap), _blockOffsets{other._blockOffsets} 88 36404 : { 89 36404 : for (const auto& blockDesc : other._blockDescriptors) 90 36598 : _blockDescriptors.push_back(blockDesc->clone()); 91 36404 : } 92 : 93 : index_t PartitionDescriptor::getNumberOfBlocks() const 94 109908 : { 95 109908 : return _indexMap.size(); 96 109908 : } 97 : 98 : const DataDescriptor& PartitionDescriptor::getDescriptorOfBlock(index_t i) const 99 36892 : { 100 36923 : if (i < 0 || i >= getNumberOfBlocks()) 101 8 : throw InvalidArgumentError("BlockDescriptor: index i is out of bounds"); 102 : 103 36884 : auto index = asUnsigned(_indexMap[i]); 104 36884 : return *_blockDescriptors[index]; 105 36884 : } 106 : 107 : index_t PartitionDescriptor::getOffsetOfBlock(index_t i) const 108 36375 : { 109 36398 : if (i < 0 || i >= getNumberOfBlocks()) 110 4 : throw InvalidArgumentError("BlockDescriptor: index i is out of bounds"); 111 : 112 36371 : return _blockOffsets[i]; 113 36371 : } 114 : 115 : PartitionDescriptor* PartitionDescriptor::cloneImpl() const 116 36339 : { 117 36339 : return new PartitionDescriptor(*this); 118 36339 : } 119 : 120 : bool PartitionDescriptor::isEqual(const DataDescriptor& other) const 121 55 : { 122 55 : if (!BlockDescriptor::isEqual(other)) 123 11 : return false; 124 : 125 : // static cast as type checked in base comparison 126 44 : auto otherBlock = static_cast<const PartitionDescriptor*>(&other); 127 : 128 44 : return _blockOffsets == otherBlock->_blockOffsets; 129 44 : } 130 : 131 : std::unique_ptr<VolumeDescriptor> 132 : PartitionDescriptor::generateDescriptorOfPartition(index_t numberOfSlices) const 133 35387 : { 134 35387 : auto coeffsPerDim = getNumberOfCoefficientsPerDimension(); 135 35387 : coeffsPerDim[_numberOfDimensions - 1] = numberOfSlices; 136 35387 : return std::make_unique<VolumeDescriptor>(coeffsPerDim, getSpacingPerDimension()); 137 35387 : } 138 : } // namespace elsa