// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file Base/Axis/Frame.cpp //! @brief Implements class Frame. //! //! @homepage http://www.bornagainproject.org //! @license GNU General Public License v3 or higher (see COPYING) //! @copyright Forschungszentrum Jülich GmbH 2018 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) // // ************************************************************************************************ #include "Base/Axis/Frame.h" #include "Base/Axis/FrameUtil.h" #include "Base/Axis/Scale.h" #include "Base/Util/Assert.h" Frame::Frame(std::vector<const Scale*>&& axes) : m_axes(std::move(axes)) , m_size(FrameUtil::product_size(m_axes.reference())) { } Frame* Frame::clone() const { return new Frame(m_axes.cloned_vector()); } Frame::~Frame() = default; size_t Frame::rank() const { return m_axes.size(); } size_t Frame::size() const { return m_size; } const Scale& Frame::axis(size_t k_axis) const { return *m_axes.at(k_axis); } const Scale& Frame::xAxis() const { return *m_axes.at(0); } const Scale& Frame::yAxis() const { return *m_axes.at(1); } size_t Frame::projectedSize(size_t k_axis) const { return m_axes[k_axis]->size(); } double Frame::projectedCoord(size_t i_flat, size_t k_axis) const { auto axis_index = projectedIndex(i_flat, k_axis); return m_axes[k_axis]->binCenter(axis_index); } std::vector<int> Frame::allIndices(size_t i_flat) const { std::vector<int> result(rank()); for (size_t k = 0; k < rank(); ++k) result[k] = projectedIndex(i_flat, k); return result; } size_t Frame::projectedIndex(size_t i_flat, size_t k_axis) const { if (rank() == 1) return i_flat; if (rank() == 2) { if (k_axis == 0) return (i_flat / m_axes[1]->size()) % m_axes[0]->size(); if (k_axis == 1) return i_flat % m_axes[1]->size(); ASSERT(false); } ASSERT(false); } size_t Frame::toGlobalIndex(const std::vector<unsigned>& axes_indices) const { ASSERT(axes_indices.size() == rank()); size_t result = 0; size_t step_size = 1; for (int k = rank() - 1; k >= 0; --k) { ASSERT(axes_indices[k] < m_axes[k]->size()); result += axes_indices[k] * step_size; step_size *= m_axes[k]->size(); } return result; } bool Frame::operator==(const Frame& o) const { if (rank() != o.rank()) return false; for (size_t k = 0; k < rank(); ++k) if (axis(k) != o.axis(k)) return false; return true; } std::vector<const Scale*> Frame::clonedAxes() const { return m_axes.cloned_vector(); } bool Frame::hasSameSizes(const Frame& o) const { if (rank() != o.rank()) return false; for (size_t k = 0; k < rank(); ++k) if (axis(k).size() != o.axis(k).size()) return false; return true; }