LCOV - code coverage report
Current view: top level - core/Descriptors - PartitionDescriptor.cpp (source / functions) Hit Total Coverage
Test: test_coverage.info.cleaned Lines: 0 82 0.0 %
Date: 2022-08-04 03:43:28 Functions: 0 9 0.0 %

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

Generated by: LCOV version 1.14