LCOV - code coverage report
Current view: top level - elsa/core/Descriptors - PartitionDescriptor.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 84 84 100.0 %
Date: 2024-05-16 04:22:26 Functions: 9 9 100.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             :     PartitionDescriptor::PartitionDescriptor(const DataDescriptor& dataDescriptor,
      11             :                                              index_t numberOfBlocks)
      12             :         : BlockDescriptor{dataDescriptor},
      13             :           _indexMap(numberOfBlocks),
      14             :           _blockDescriptors(0),
      15             :           _blockOffsets(numberOfBlocks)
      16       34749 :     {
      17       34749 :         if (numberOfBlocks < 2)
      18           1 :             throw InvalidArgumentError(
      19           1 :                 "PartitionDescriptor: number of blocks must be greater than one");
      20             : 
      21       34748 :         index_t lastDimSize = _numberOfCoefficientsPerDimension[_numberOfDimensions - 1];
      22             : 
      23       34748 :         if (numberOfBlocks > lastDimSize)
      24           1 :             throw InvalidArgumentError(
      25           1 :                 "PartitionDescriptor: number of blocks too large for given descriptor");
      26             : 
      27       34747 :         index_t rest = lastDimSize % numberOfBlocks;
      28             : 
      29       34747 :         auto blockDesc = generateDescriptorOfPartition(lastDimSize / numberOfBlocks);
      30       34747 :         _blockDescriptors.push_back(std::move(blockDesc));
      31       34747 :         _indexMap.head(numberOfBlocks - rest).setZero();
      32     1075231 :         for (index_t i = 0; i < numberOfBlocks && i <= numberOfBlocks - rest; i++)
      33     1040484 :             _blockOffsets[i] = i * _blockDescriptors[0]->getNumberOfCoefficients();
      34             : 
      35       34747 :         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       34747 :     }
      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       36326 :     {
      89       36326 :         for (const auto& blockDesc : other._blockDescriptors)
      90       36573 :             _blockDescriptors.push_back(blockDesc->clone());
      91       36326 :     }
      92             : 
      93             :     index_t PartitionDescriptor::getNumberOfBlocks() const
      94      110084 :     {
      95      110084 :         return _indexMap.size();
      96      110084 :     }
      97             : 
      98             :     const DataDescriptor& PartitionDescriptor::getDescriptorOfBlock(index_t i) const
      99       36949 :     {
     100       36969 :         if (i < 0 || i >= getNumberOfBlocks())
     101           8 :             throw InvalidArgumentError("BlockDescriptor: index i is out of bounds");
     102             : 
     103       36941 :         auto index = asUnsigned(_indexMap[i]);
     104       36941 :         return *_blockDescriptors[index];
     105       36941 :     }
     106             : 
     107             :     index_t PartitionDescriptor::getOffsetOfBlock(index_t i) const
     108       36418 :     {
     109       36441 :         if (i < 0 || i >= getNumberOfBlocks())
     110           4 :             throw InvalidArgumentError("BlockDescriptor: index i is out of bounds");
     111             : 
     112       36414 :         return _blockOffsets[i];
     113       36414 :     }
     114             : 
     115             :     PartitionDescriptor* PartitionDescriptor::cloneImpl() const
     116       36248 :     {
     117       36248 :         return new PartitionDescriptor(*this);
     118       36248 :     }
     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       35408 :     {
     134       35408 :         auto coeffsPerDim = getNumberOfCoefficientsPerDimension();
     135       35408 :         coeffsPerDim[_numberOfDimensions - 1] = numberOfSlices;
     136       35408 :         return std::make_unique<VolumeDescriptor>(coeffsPerDim, getSpacingPerDimension());
     137       35408 :     }
     138             : } // namespace elsa

Generated by: LCOV version 1.14