# blocked_range2d Template Class

## Summary

Template class that represents recursively divisible two-dimensional half-open interval.

## Header

    #include "tbb/blocked_range2d.h"

## Syntax

    template<typename RowValue, typename ColValue> class blocked_range2d;

## Description

A `blocked_range2d<RowValue ,ColValue >` represents a half-open two dimensional range`[i 0,j 0)×[i 1,j 1)`. Each axis of the range has its own splitting threshold. The RowValue and ColValue must meet the requirements in the table in the blocked_range Template Class section. A `blocked_range` is splittable if either axis is splittable. A`blocked_range` models the Range concept.

## Members

    namespace tbb {
    template<typename RowValue, typename ColValue=RowValue>
        class blocked_range2d {
        public:
            // Types
            typedef blocked_range<RowValue> row_range_type;
            typedef blocked_range<ColValue> col_range_type;

            // Constructors
            blocked_range2d(
                RowValue row_begin, RowValue row_end,
                typename row_range_type::size_type row_grainsize,
                ColValue col_begin, ColValue col_end,
                typename col_range_type::size_type col_grainsize);
            blocked_range2d( RowValue row_begin, RowValue row_end,
                             ColValue col_begin, ColValue col_end);
            blocked_range2d( blocked_range2d& r, split );

            // Capacity
            bool empty() const;

            // Access
            bool is_divisible() const;
            const row_range_type& rows() const;
            const col_range_type& cols() const;
        };
    }

## Example

The code that follows shows a serial matrix multiply, and the corresponding parallel matrix multiply that uses a `blocked_range2d` to specify the iteration space.

    const size_t L = 150;
    const size_t M = 225;
    const size_t N = 300;

    void SerialMatrixMultiply( float c[M][N], float a[M][L], float b[L][N] ) {
        for( size_t i=0; i<M; ++i ) {
            for( size_t j=0; j<N; ++j ) {
                float sum = 0;
                for( size_t k=0; k<L; ++k )
                    sum += a[i][k]*b[k][j];
                c[i][j] = sum;
            }
        }
    }

    #include "tbb/parallel_for.h"
    #include "tbb/blocked_range2d.h"

    using namespace tbb;

    const size_t L = 150;
    const size_t M = 225;
    const size_t N = 300;

    class MatrixMultiplyBody2D {
        float (*my_a)[L];
        float (*my_b)[N];
        float (*my_c)[N];
    public:
        void operator()( const blocked_range2d<size_t>& r ) const {
            float (*a)[L] = my_a;
            float (*b)[N] = my_b;
            float (*c)[N] = my_c;
            for( size_t i=r.rows().begin(); i!=r.rows().end(); ++i ){
                for( size_t j=r.cols().begin(); j!=r.cols().end(); ++j ) {
                    float sum = 0;
                    for( size_t k=0; k<L; ++k )
                        sum += a[i][k]*b[k][j];
                    c[i][j] = sum;
                }
            }
        }
        MatrixMultiplyBody2D( float c[M][N], float a[M][L], float b[L][N] ) :
            my_a(a), my_b(b), my_c(c)
        {}
    };

    void ParallelMatrixMultiply(float c[M][N], float a[M][L], float b[L][N]){
        parallel_for( blocked_range2d<size_t>(0, M, 16, 0, N, 32),
                      MatrixMultiplyBody2D(c,a,b) );
    }

The`blocked_range2d` enables the two outermost loops of the serial version to become parallel loops. The`parallel_for` recursively splits the `blocked_range2d` until the pieces are no larger than 16x32. It invokes `MatrixMultiplyBody2D::operator(`) on each piece.

The following table provides additional information on the members of this template class.
Member | Description
--- | ---
row_range_type | A `blocked_range<RowValue>`. That is, the type of the row values.
col_range_type | A`blocked_range<ColValue>`. That is, the type of the column values.
blocked_range2d<RowValue,ColValue>( RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize ) | Effects: Constructs a `blocked_range2d` representing a two dimensional space of values. The space is the half-open Cartesian product`[ row_begin, row_end) x [ col_begin, col_end)`, with the given grain sizes for the rows and columns. Example: The statement `" blocked_range2d<char,int> r('a', 'z'+1, 3, 0, 10, 2 );"` constructs a two-dimensional space that contains all value pairs of the form `(i, j)`, where`i` ranges from `'a`' to `'z`' with a grain size of 3, and`j` ranges from 0 to 9 with a grain size of 2.
blocked_range2d<RowValue,ColValue>( RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end ) | Same as `blocked_range2d(row_begin,row_end,1,col_begin,col_end,1)`.
blocked_range2d<RowValue,ColValue> ( blocked_range2d& range, split ) | Partitions range into two subranges. The newly constructed `blocked_range2d` is approximately the second half of the original `range`, and `range` is updated to be the remainder. Each subrange has the same grain size as the original `range`. The split is either by rows or columns. The choice of which axis to split is intended to cause, after repeated splitting, the subranges to approach the aspect ratio of the respective row and column grain sizes. For example, if the `row_grainsize` is twice `col_grainsize`, the subranges will tend towards having twice as many rows as columns.
bool empty() const | Determines if range is empty. Returns: `rows().empty()||cols().empty()`
bool is_divisible() const | Determines if range can be split into subranges.. Returns: `rows().is_divisible()||cols().is_divisible()`
const row_range_type& rows() const | Returns: Range containing the rows of the value space.
const col_range_type& cols() const | Returns: Range containing the columns of the value space.

Parent topic: Range Concept