Skip to content

Instantly share code, notes, and snippets.

@eddieavd
Created May 29, 2024 13:39
Show Gist options
  • Save eddieavd/4cc712bbd061fea7c71f0c550a0524c8 to your computer and use it in GitHub Desktop.
Save eddieavd/4cc712bbd061fea7c71f0c550a0524c8 to your computer and use it in GitHub Desktop.

generic prefix_array::range

prefix sum array
uti::prefix_array

1D base case

value_type range ( ssize_type x1, ssize_type x2 ) const noexcept
{
    return x1 == 0 ? at( x1     )
                   : at( x1     )
                   - at( x0 - 1 ) ;
}

2D

decltype( auto ) range ( ssize_type x1, ssize_type y1,
                         ssize_type x2, ssize_type y2 ) const noexcept
    requires( is_2d_range_container_v< _self > )
{
    return x1 == 0 ? at( x2     ).range( y1, y2 )
                   : at( x2     ).range( y1, y2 )
                   - at( x1 - 1 ).range( y1, y2 ) ;
}

3D

decltype( auto ) range ( ssize_type x1, ssize_type y1, ssize_type z1,
                         ssize_type x2, ssize_type y2, ssize_type z2 ) const noexcept
    requires( is_3d_range_container_v< _self > )
{
    return x1 == 0 ? at( x2     ).range( y1, z1, y2, z2 )
                   : at( x2     ).range( y1, z1, y2, z2 )
                   - at( x1 - 1 ).range( y1, z1, y2, z2 ) ;
}

fully generic in terms of dimensions

// need this cause the 'concept any' approach doesn't deduce lhs and rhs as expected
template< ssize_t >
struct index
{
    ssize_t idx ;
    
    template< ssize_t Idx_ >
    constexpr index ( index< Idx_ > other ) : idx( other.idx  ) {}
    constexpr index ( ssize_t       _idx_ ) : idx(      _idx_ ) {}
    
    constexpr operator ssize_t () const noexcept { return idx ; }
}

decltype( auto ) range ( auto&&... coords ) const noexcept
    requires( sizeof...( coords ) % 2 == 0 &&
              is_n_dimensional_container_v< _self, sizeof...( coords ) / 2 > )
{
    constexpr auto Dim = sizeof...( coords ) / 2 ;
    
    if constexpr( Dim == 1 )
    {
        return [ & ]( ssize_type x1, ssize_type x2 )
        {
            return x1 == 0 ? at( x2     )
                           : at( x2     )
                           - at( x1 - 1 ) ;
        }( coords... ) ;
    }
    else
    {
        return [ & ]< ssize_type... Idxs >( uti::index_sequence< Idxs... > )
        {
            return [ & ]( ssize_type x1, index< Idxs >&&... lhs ,
                          ssize_type x2, index< Idxs >&&... rhs )
            {
                return x1 == 0 ? at( x2     ).range( lhs..., rhs... )
                               : at( x2     ).range( lhs..., rhs... )
                               - at( x1 - 1 ).range( lhs..., rhs... ) ;
            }( coords... ) ;
        }( uti::make_index_sequence< Dim - 1 >{} ) ;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment