#ifndef PYTHONIC_NUMPY_NDARRAY_RESHAPE_HPP #define PYTHONIC_NUMPY_NDARRAY_RESHAPE_HPP #include "pythonic/include/numpy/ndarray/reshape.hpp" #include "pythonic/utils/functor.hpp" #include "pythonic/utils/numpy_conversion.hpp" #include "pythonic/types/ndarray.hpp" #include "pythonic/builtins/ValueError.hpp" PYTHONIC_NS_BEGIN namespace numpy { namespace ndarray { namespace misc { template void set(P &p, long i, long v, utils::index_sequence) { (void)std::initializer_list{ (i == Is && (sutils::assign(std::get(p), v), true))...}; } } template typename std::enable_if::value, types::ndarray>::type reshape(types::ndarray const &expr, NpS const &new_shape) { long where = sutils::sfind( new_shape, -1, std::integral_constant::value>(), [](long a, long b) { return a <= b; }); long next = sutils::sfind(new_shape, -1, where, [](long a, long b) { return a <= b; }); if (next >= 0) { throw pythonic::types::ValueError( "Reshape: can only specify one unknown dimension"); } if (where >= 0) { auto auto_shape = new_shape; misc::set(auto_shape, where, expr.flat_size() / -sutils::sprod(new_shape), utils::make_index_sequence::value>()); return expr.reshape(auto_shape); } else { auto nshape = sutils::sprod(new_shape); auto n = expr.flat_size(); if (n < nshape) { types::ndarray out(new_shape, builtins::None); auto iter = std::copy(expr.fbegin(), expr.fend(), out.fbegin()); for (long i = 1; i < nshape / n; ++i) iter = std::copy(out.fbegin(), out.fbegin() + n, iter); std::copy(out.fbegin(), out.fbegin() + nshape % n, iter); return out; } else { return expr.reshape(new_shape); } } } template typename std::enable_if::value, types::ndarray>>::type reshape(types::ndarray const &expr, NpS const &new_shape) { auto n = expr.flat_size(); if (new_shape <= -1) { return expr.reshape(types::pshape(n)); } if (n < new_shape) { types::ndarray> out( types::pshape{new_shape}, builtins::None); auto iter = std::copy(expr.fbegin(), expr.fend(), out.fbegin()); for (long i = 1; i < new_shape / n; ++i) iter = std::copy(out.fbegin(), out.fbegin() + n, iter); std::copy(out.fbegin(), out.fbegin() + new_shape % n, iter); return out; } else { return expr.reshape(types::pshape(new_shape)); } } template auto reshape(types::ndarray const &expr, S0 i0, S1 i1, S const &... indices) -> decltype(reshape(expr, types::pshape{i0, i1, indices...})) { return reshape(expr, types::pshape{i0, i1, indices...}); } NUMPY_EXPR_TO_NDARRAY0_IMPL(reshape); } } PYTHONIC_NS_END #endif