1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
/* Copyright (c) 2008-2022 the MRtrix3 contributors.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Covered Software is provided under this License on an "as is"
* basis, without warranty of any kind, either expressed, implied, or
* statutory, including, without limitation, warranties that the
* Covered Software is free of defects, merchantable, fit for a
* particular purpose or non-infringing.
* See the Mozilla Public License v. 2.0 for more details.
*
* For more details, see http://www.mrtrix.org/.
*/
#ifndef __adapter_permute_axes_h__
#define __adapter_permute_axes_h__
#include "adapter/base.h"
namespace MR
{
namespace Adapter
{
template <class ImageType>
class PermuteAxes :
public Base<PermuteAxes<ImageType>,ImageType>
{ MEMALIGN (PermuteAxes<ImageType>)
public:
using base_type = Base<PermuteAxes<ImageType>, ImageType>;
using value_type = typename ImageType::value_type;
using base_type::size;
using base_type::parent;
PermuteAxes (const ImageType& original, const vector<int>& axes) :
base_type (original),
axes_ (axes) {
for (int i = 0; i < static_cast<int> (parent().ndim()); ++i) {
for (size_t a = 0; a < axes_.size(); ++a) {
if (axes_[a] >= int (parent().ndim()))
throw Exception ("axis " + str(axes_[a]) + " exceeds image dimensionality");
if (axes_[a] == i)
goto next_axis;
}
if (parent().size (i) != 1)
throw Exception ("omitted axis \"" + str (i) + "\" has dimension greater than 1");
next_axis:
continue;
}
int non_existent_index = -1;
for (auto& a : axes_) {
if (a < 0) {
a = non_existent_index--;
non_existent_axes.push_back (0);
}
}
}
size_t ndim () const {
return axes_.size();
}
ssize_t size (size_t axis) const {
return axes_[axis] < 0 ? 1 : parent().size (axes_[axis]);
}
default_type spacing (size_t axis) const {
return axes_[axis] < 0 ? std::numeric_limits<default_type>::quiet_NaN() : parent().spacing (axes_[axis]);
}
ssize_t stride (size_t axis) const {
return axes_[axis] < 0 ? 0 : parent().stride (axes_[axis]);
}
void reset () { parent().reset(); }
ssize_t get_index (size_t axis) const { const auto a = axes_[axis]; return a < 0 ? non_existent_axes[-1-a] : parent().index (a); }
void move_index (size_t axis, ssize_t increment) {
const auto a = axes_[axis];
if (a < 0) non_existent_axes[-1-a] += increment;
else parent().index (a) += increment;
}
private:
vector<int> axes_;
vector<size_t> non_existent_axes;
};
}
}
#endif
|