Program Listing for File AssignPerfectHypercube.hpp

Return to documentation for file (include/netuit/assign/AssignPerfectHypercube.hpp)

#pragma once
#ifndef NETUIT_ASSIGN_ASSIGNPERFECTHYPERCUBE_HPP_INCLUDE
#define NETUIT_ASSIGN_ASSIGNPERFECTHYPERCUBE_HPP_INCLUDE

#include <cassert>
#include <functional>
#include <numeric>
#include <stddef.h>

#include "../../uitsl/debug/uitsl_assert.hpp"
#include "../../uitsl/math/is_perfect_hypercube.hpp"
#include "../../uitsl/math/mapping_utils.hpp"

namespace netuit {

template<typename RETURN_TYPE>
struct AssignPerfectHypercube {

  uitsl::Dims item_dims;
  uitsl::Dims partition_dims;

  AssignPerfectHypercube(
    const size_t n_dims, const size_t n_items, const size_t n_partitions
  ) : item_dims( n_dims, std::pow( n_items, 1.0/n_dims ) )
  , partition_dims(n_dims, std::pow( n_partitions, 1.0/n_dims ) ) {

    assert( uitsl::is_perfect_hypercube( n_items, n_dims) );
    assert( uitsl::is_perfect_hypercube( n_partitions, n_dims) );
    assert( std::accumulate(
      std::begin(item_dims), std::end(item_dims), 1ul, std::multiplies<size_t>{}
    ) == n_items );
    assert( std::accumulate(
      std::begin(partition_dims), std::end(partition_dims),
      1ul, std::multiplies<size_t>{}
    ) == n_partitions );
  }

  RETURN_TYPE operator()(const size_t& node_id) {

    // get item coordinates
    auto coordinates = uitsl::linear_decode( node_id, item_dims );

    assert( item_dims.front() % partition_dims.front() == 0 );

    // transform into partition coordinates
    for (auto& coord : coordinates) {
      coord /= ( item_dims.front() / partition_dims.front() );
    }
    // get partition id
    const auto res = uitsl::linear_encode( coordinates, partition_dims );

    uitsl_assert(
      res < std::accumulate(
        std::begin(partition_dims), std::end(partition_dims),
        1ul, std::multiplies<size_t>{}
      ),
      node_id
        << res
        << coordinates
        << uitsl::linear_decode( node_id, item_dims )
        << item_dims
        << partition_dims
    );

    return res;
  }

};

} // namespace netuit

#endif // #ifndef NETUIT_ASSIGN_ASSIGNPERFECTHYPERCUBE_HPP_INCLUDE