#ifndef PYTHONIC_NUMPY_RANDOM_CHOICE_HPP #define PYTHONIC_NUMPY_RANDOM_CHOICE_HPP #include "pythonic/include/numpy/random/choice.hpp" #include "pythonic/include/numpy/random/generator.hpp" #include "pythonic/builtins/NotImplementedError.hpp" #include "pythonic/numpy/random/randint.hpp" #include "pythonic/types/ndarray.hpp" #include "pythonic/types/tuple.hpp" #include "pythonic/utils/functor.hpp" #include #include PYTHONIC_NS_BEGIN namespace numpy { namespace random { /*********************************************************** * Implementation with long as first argument **********************************************************/ template types::ndarray choice(long max, pS const &shape, bool replace, P const &p) { if (!replace) throw pythonic::builtins::NotImplementedError( "Choice without replacement is ! implemented, ask if you want " "it"); types::ndarray result{shape, types::none_type()}; std::discrete_distribution distribution{p.begin(), p.end()}; std::generate(result.fbegin(), result.fend(), [&]() { return distribution(details::generator); }); return result; } template types::ndarray> choice(long max, long size, bool replace, P &&p) { return choice(max, types::pshape{size}, replace, std::forward

(p)); } template auto choice(long max, T &&size) -> decltype(randint(0, max, std::forward(size))) { return randint(0, max, std::forward(size)); } long choice(long max) { return randint(max); } /*********************************************************** * Implementation with array as first argument **********************************************************/ template typename T::dtype choice(T const &a) { // This is a numpy constraint static_assert(T::value == 1, "ValueError: a must be 1-dimensional"); return a.fast(randint(a.size())); } template types::ndarray choice(T const &a, pS const &shape) { // This is a numpy constraint static_assert(T::value == 1, "ValueError: a must be 1-dimensional"); types::ndarray result{shape, types::none_type()}; std::uniform_int_distribution distribution{0, a.size() - 1}; std::generate(result.fbegin(), result.fend(), [&]() { return a[distribution(details::generator)]; }); return result; } template types::ndarray> choice(T &&a, long size) { return choice(std::forward(a), types::pshape{size}); } template types::ndarray choice(T const &a, pS const &shape, bool replace, P const &p) { // This is a numpy constraint static_assert(T::value == 1, "ValueError: a must be 1-dimensional"); if (!replace) throw pythonic::builtins::NotImplementedError( "Choice without replacement is ! implemented, ask if you want " "it"); types::ndarray result{shape, types::none_type()}; std::discrete_distribution distribution{p.begin(), p.end()}; std::generate(result.fbegin(), result.fend(), [&]() { return a[distribution(details::generator)]; }); return result; } template types::ndarray> choice(T &&a, long size, bool replace, P &&p) { return choice(std::forward(a), types::pshape{size}, replace, std::forward

(p)); } } } PYTHONIC_NS_END #endif