#ifndef PYTHONIC_NUMPY_UNIQUE_HPP #define PYTHONIC_NUMPY_UNIQUE_HPP #include "pythonic/include/numpy/unique.hpp" #include "pythonic/utils/functor.hpp" #include "pythonic/types/ndarray.hpp" #include "pythonic/types/tuple.hpp" #include #include PYTHONIC_NS_BEGIN namespace numpy { namespace { template void _unique1(I begin, I end, O &out, utils::int_<1>) { out.insert(begin, end); } template void _unique1(I begin, I end, O &out, utils::int_) { for (; begin != end; ++begin) _unique1((*begin).begin(), (*begin).end(), out, utils::int_()); } template void _unique2(I begin, I end, O0 &out0, O1 &out1, long &i, utils::int_<1>) { for (; begin != end; ++begin, ++i) { auto pair = out0.insert(*begin); if (pair.second) out1.push_back(i); } } template void _unique2(I begin, I end, O0 &out0, O1 &out1, long &i, utils::int_) { for (; begin != end; ++begin) _unique2((*begin).begin(), (*begin).end(), out0, out1, i, utils::int_()); } template void _unique3(I begin, I end, O0 &out0, O1 &out1, O2 &out2, long &i, utils::int_<1>) { for (; begin != end; ++begin, ++i) { auto pair = out0.insert(*begin); out2[i] = std::distance(out0.begin(), pair.first); if (pair.second) out1.push_back(i); } } template void _unique3(I begin, I end, O0 &out0, O1 &out1, O2 &out2, long &i, utils::int_) { for (; begin != end; ++begin) _unique3((*begin).begin(), (*begin).end(), out0, out1, out2, i, utils::int_()); } template void _unique4(I begin, I end, O1 &out1, O2 &out2, O3 &out3, long &i, utils::int_<1>) { for (; begin != end; ++begin, ++i) { auto res = out3.insert(std::make_pair(*begin, 0)); res.first->second += 1; out2[i] = std::distance(out3.begin(), res.first); if (res.second) { out1.push_back(i); } } } template void _unique4(I begin, I end, O1 &out1, O2 &out2, O3 &out3, long &i, utils::int_) { for (; begin != end; ++begin) _unique4((*begin).begin(), (*begin).end(), out1, out2, out3, i, utils::int_()); } template void _unique5(I begin, I end, O0 &out0, O2 &out2, long &i, utils::int_<1>) { for (; begin != end; ++begin, ++i) { auto pair = out0.insert(*begin); out2[i] = std::distance(out0.begin(), pair.first); } } template void _unique5(I begin, I end, O0 &out0, O2 &out2, long &i, utils::int_) { for (; begin != end; ++begin) _unique5((*begin).begin(), (*begin).end(), out0, out2, i, utils::int_()); } template void _unique6(I begin, I end, O1 &out1, O3 &out3, long &i, utils::int_<1>) { for (; begin != end; ++begin, ++i) { auto res = out3.insert(std::make_pair(*begin, 0)); res.first->second += 1; if (res.second) { out1.push_back(i); } } } template void _unique6(I begin, I end, O1 &out1, O3 &out3, long &i, utils::int_) { for (; begin != end; ++begin) _unique6((*begin).begin(), (*begin).end(), out1, out3, i, utils::int_()); } template void _unique7(I begin, I end, O2 &out2, O3 &out3, long &i, utils::int_<1>) { for (; begin != end; ++begin, ++i) { auto res = out3.insert(std::make_pair(*begin, 0)); res.first->second += 1; out2[i] = std::distance(out3.begin(), res.first); } } template void _unique7(I begin, I end, O2 &out2, O3 &out3, long &i, utils::int_) { for (; begin != end; ++begin) _unique7((*begin).begin(), (*begin).end(), out2, out3, i, utils::int_()); } template void _unique8(I begin, I end, O3 &out3, long &i, utils::int_<1>) { for (; begin != end; ++begin, ++i) { auto res = out3.insert(std::make_pair(*begin, 0)); res.first->second += 1; } } template void _unique8(I begin, I end, O3 &out3, long &i, utils::int_) { for (; begin != end; ++begin) _unique8((*begin).begin(), (*begin).end(), out3, i, utils::int_()); } } template types::ndarray> unique(E const &expr) { std::set res; _unique1(expr.begin(), expr.end(), res, utils::int_()); return {res}; } template std::tuple>, types::ndarray>> unique(E const &expr, types::true_immediate return_index) { std::set res; std::vector return_index_res; long i = 0; _unique2(expr.begin(), expr.end(), res, return_index_res, i, utils::int_()); return std::make_tuple( types::ndarray>(res), types::ndarray>(return_index_res)); } template types::ndarray> unique(E const &expr, types::false_immediate return_index) { std::set res; _unique1(expr.begin(), expr.end(), res, utils::int_()); return {res}; } template std::tuple>, types::ndarray>> unique(E const &expr, types::false_immediate return_index, types::true_immediate return_inverse) { std::set res; types::ndarray> return_inverse_res( types::pshape{expr.flat_size()}, builtins::None); long i = 0; _unique5(expr.begin(), expr.end(), res, return_inverse_res, i, utils::int_()); return std::make_tuple( types::ndarray>(res), return_inverse_res); } template types::ndarray> unique(E const &expr, types::false_immediate return_index, types::false_immediate return_inverse) { std::set res; _unique1(expr.begin(), expr.end(), res, utils::int_()); return {res}; } template std::tuple>, types::ndarray>> unique(E const &expr, types::true_immediate return_index, types::false_immediate return_inverse) { return unique(expr, return_index); } template std::tuple>, types::ndarray>, types::ndarray>> unique(E const &expr, types::true_immediate return_index, types::true_immediate return_inverse) { assert(return_inverse && "invalid signature otherwise"); std::set res; std::vector return_index_res; types::ndarray> return_inverse_res( types::pshape{expr.flat_size()}, builtins::None); long i = 0; _unique3(expr.begin(), expr.end(), res, return_index_res, return_inverse_res, i, utils::int_()); return std::make_tuple( types::ndarray>(res), types::ndarray>(return_index_res), return_inverse_res); } template std::tuple>, types::ndarray>, types::ndarray>, types::ndarray>> unique(E const &expr, types::true_immediate return_index, types::true_immediate return_inverse, types::true_immediate return_counts) { assert(return_counts && "invalid signature otherwise"); std::vector return_index_res; types::ndarray> return_inverse_res( types::pshape{expr.flat_size()}, builtins::None); std::map return_counts_map; { long i = 0; _unique4(expr.begin(), expr.end(), return_index_res, return_inverse_res, return_counts_map, i, utils::int_()); } types::pshape shp{(long)return_counts_map.size()}; types::ndarray> unique_array(shp, builtins::None); types::ndarray> return_counts_array( shp, builtins::None); { long i = 0; for (auto it = return_counts_map.begin(); it != return_counts_map.end(); ++i, ++it) { unique_array.fast(i) = it->first; return_counts_array.fast(i) = it->second; } } return std::make_tuple( unique_array, types::ndarray>(return_index_res), return_inverse_res, return_counts_array); } template std::tuple>, types::ndarray>, types::ndarray>> unique(E const &expr, types::true_immediate return_index, types::true_immediate return_inverse, types::false_immediate return_counts) { return unique(expr, return_index, return_inverse); } template std::tuple>, types::ndarray>> unique(E const &expr, types::true_immediate return_index, types::false_immediate return_inverse, types::false_immediate return_counts) { return unique(expr, return_index); } template std::tuple>, types::ndarray>, types::ndarray>> unique(E const &expr, types::true_immediate return_index, types::false_immediate return_inverse, types::true_immediate return_counts) { std::vector return_index_res; std::map return_counts_map; { long i = 0; _unique6(expr.begin(), expr.end(), return_index_res, return_counts_map, i, utils::int_()); } types::pshape shp{(long)return_counts_map.size()}; types::ndarray> unique_array(shp, builtins::None); types::ndarray> return_counts_array( shp, builtins::None); { long i = 0; for (auto it = return_counts_map.begin(); it != return_counts_map.end(); ++i, ++it) { unique_array.fast(i) = it->first; return_counts_array.fast(i) = it->second; } } return std::make_tuple( unique_array, types::ndarray>(return_index_res), return_counts_array); } template std::tuple>, types::ndarray>> unique(E const &expr, types::false_immediate return_index, types::true_immediate return_inverse, types::false_immediate return_counts) { return unique(expr, return_index, return_inverse); } template std::tuple>, types::ndarray>, types::ndarray>> unique(E const &expr, types::false_immediate return_index, types::true_immediate return_inverse, types::true_immediate return_counts) { types::ndarray> return_inverse_res( types::pshape{expr.flat_size()}, builtins::None); std::map return_counts_map; { long i = 0; _unique7(expr.begin(), expr.end(), return_inverse_res, return_counts_map, i, utils::int_()); } types::pshape shp{(long)return_counts_map.size()}; types::ndarray> unique_array(shp, builtins::None); types::ndarray> return_counts_array( shp, builtins::None); { long i = 0; for (auto it = return_counts_map.begin(); it != return_counts_map.end(); ++i, ++it) { unique_array.fast(i) = it->first; return_counts_array.fast(i) = it->second; } } return std::make_tuple(unique_array, return_inverse_res, return_counts_array); } template types::ndarray> unique(E const &expr, types::false_immediate return_index, types::false_immediate return_inverse, types::false_immediate return_counts) { return unique(expr); } template std::tuple>, types::ndarray>> unique(E const &expr, types::false_immediate return_index, types::false_immediate return_inverse, types::true_immediate return_counts) { std::map return_counts_map; { long i = 0; _unique8(expr.begin(), expr.end(), return_counts_map, i, utils::int_()); } types::pshape shp{(long)return_counts_map.size()}; types::ndarray> unique_array(shp, builtins::None); types::ndarray> return_counts_array( shp, builtins::None); { long i = 0; for (auto it = return_counts_map.begin(); it != return_counts_map.end(); ++i, ++it) { unique_array.fast(i) = it->first; return_counts_array.fast(i) = it->second; } } return std::make_tuple(unique_array, return_counts_array); } } PYTHONIC_NS_END #endif