class_docstr: Block Sparse Row matrix
  
  This can be instantiated in several ways:
      bsr_matrix(D, [blocksize=(R,C)])
          where D is a dense matrix or 2-D ndarray.
  
      bsr_matrix(S, [blocksize=(R,C)])
          with another sparse matrix S (equivalent to S.tobsr())
  
      bsr_matrix((M, N), [blocksize=(R,C), dtype])
          to construct an empty matrix with shape (M, N)
          dtype is optional, defaulting to dtype='d'.
  
      bsr_matrix((data, ij), [blocksize=(R,C), shape=(M, N)])
          where ``data`` and ``ij`` satisfy ``a[ij[0, k], ij[1, k]] = data[k]``
  
      bsr_matrix((data, indices, indptr), [shape=(M, N)])
          is the standard BSR representation where the block column
          indices for row i are stored in ``indices[indptr[i]:indptr[i+1]]``
          and their corresponding block values are stored in
          ``data[ indptr[i]: indptr[i+1] ]``. If the shape parameter is not
          supplied, the matrix dimensions are inferred from the index arrays.
  
  Attributes
  ----------
  dtype : dtype
      Data type of the matrix
  shape : 2-tuple
      Shape of the matrix
  ndim : int
      Number of dimensions (this is always 2)
  nnz
      Number of stored values, including explicit zeros
  data
      Data array of the matrix
  indices
      BSR format index array
  indptr
      BSR format index pointer array
  blocksize
      Block size of the matrix
  has_sorted_indices
      Whether indices are sorted
  
  Notes
  -----
  Sparse matrices can be used in arithmetic operations: they support
  addition, subtraction, multiplication, division, and matrix power.
  
  **Summary of BSR format**
  
  The Block Compressed Row (BSR) format is very similar to the Compressed
  Sparse Row (CSR) format. BSR is appropriate for sparse matrices with dense
  sub matrices like the last example below.  Block matrices often arise in
  vector-valued finite element discretizations. In such cases, BSR is
  considerably more efficient than CSR and CSC for many sparse arithmetic
  operations.
  
  **Blocksize**
  
  The blocksize (R,C) must evenly divide the shape of the matrix (M,N).
  That is, R and C must satisfy the relationship ``M % R = 0`` and
  ``N % C = 0``.
  
  If no blocksize is specified, a simple heuristic is applied to determine
  an appropriate blocksize.
  
  Examples
  --------
  >>> from scipy.sparse import bsr_matrix
  >>> bsr_matrix((3, 4), dtype=np.int8).toarray()
  array([[0, 0, 0, 0],
         [0, 0, 0, 0],
         [0, 0, 0, 0]], dtype=int8)
  
  >>> row = np.array([0, 0, 1, 2, 2, 2])
  >>> col = np.array([0, 2, 2, 0, 1, 2])
  >>> data = np.array([1, 2, 3 ,4, 5, 6])
  >>> bsr_matrix((data, (row, col)), shape=(3, 3)).toarray()
  array([[1, 0, 2],
         [0, 0, 3],
         [4, 5, 6]])
  
  >>> indptr = np.array([0, 2, 3, 6])
  >>> indices = np.array([0, 2, 2, 0, 1, 2])
  >>> data = np.array([1, 2, 3, 4, 5, 6]).repeat(4).reshape(6, 2, 2)
  >>> bsr_matrix((data,indices,indptr), shape=(6, 6)).toarray()
  array([[1, 1, 0, 0, 2, 2],
         [1, 1, 0, 0, 2, 2],
         [0, 0, 0, 0, 3, 3],
         [0, 0, 0, 0, 3, 3],
         [4, 4, 5, 5, 6, 6],
         [4, 4, 5, 5, 6, 6]])
code: def __init__(
      self, arg1, shape=None, dtype=None, copy=False, blocksize=None
  ):
      _data_matrix.__init__(self)
  
      if isspmatrix(arg1):
          if isspmatrix_bsr(arg1) and copy:
              arg1 = arg1.copy()
          else:
              arg1 = arg1.tobsr(blocksize=blocksize)
          self._set_self(arg1)
  
      elif isinstance(arg1, tuple):
          if isshape(arg1):
              # it's a tuple of matrix dimensions (M,N)
              self._shape = check_shape(arg1)
              M, N = self.shape
              # process blocksize
              if blocksize is None:
                  blocksize = (1, 1)
              else:
                  if not isshape(blocksize):
                      raise ValueError(
                          "invalid blocksize=%s" % blocksize
                      )
                  blocksize = tuple(blocksize)
              self.data = np.zeros(
                  (0,) + blocksize, getdtype(dtype, default=float)
              )
  
              R, C = blocksize
              if (M % R) != 0 or (N % C) != 0:
                  raise ValueError(
                      "shape must be multiple of blocksize"
                  )
  
              # Select index dtype large enough to pass array and
              # scalar parameters to sparsetools
              idx_dtype = get_index_dtype(
                  maxval=max(M // R, N // C, R, C)
              )
              self.indices = np.zeros(0, dtype=idx_dtype)
              self.indptr = np.zeros(M // R + 1, dtype=idx_dtype)
  
          elif len(arg1) == 2:
              # (data,(row,col)) format
              from .coo import coo_matrix
  
              self._set_self(
                  coo_matrix(arg1, dtype=dtype, shape=shape).tobsr(
                      blocksize=blocksize
                  )
              )
  
          elif len(arg1) == 3:
              # (data,indices,indptr) format
              (data, indices, indptr) = arg1
  
              # Select index dtype large enough to pass array and
              # scalar parameters to sparsetools
              maxval = 1
              if shape is not None:
                  maxval = max(shape)
              if blocksize is not None:
                  maxval = max(maxval, max(blocksize))
              idx_dtype = get_index_dtype(
                  (indices, indptr), maxval=maxval, check_contents=True
              )
              self.indices = np.array(
                  indices, copy=copy, dtype=idx_dtype
              )
              self.indptr = np.array(indptr, copy=copy, dtype=idx_dtype)
              self.data = getdata(data, copy=copy, dtype=dtype)
              if self.data.ndim != 3:
                  raise ValueError(
                      "BSR data must be 3-dimensional, got shape=%s"
                      % (self.data.shape,)
                  )
              if blocksize is not None:
                  if not isshape(blocksize):
                      raise ValueError(
                          "invalid blocksize=%s" % (blocksize,)
                      )
                  if tuple(blocksize) != self.data.shape[1:]:
                      raise ValueError(
                          "mismatching blocksize=%s vs %s"
                          % (blocksize, self.data.shape[1:])
                      )
          else:
              raise ValueError(
                  "unrecognized bsr_matrix constructor usage"
              )
      else:
          # must be dense
          try:
              arg1 = np.asarray(arg1)
          except Exception as e:
              raise ValueError(
                  "unrecognized form for"
                  " %s_matrix constructor" % self.format
              ) from e
          from .coo import coo_matrix
  
          arg1 = coo_matrix(arg1, dtype=dtype).tobsr(
              blocksize=blocksize
          )
          self._set_self(arg1)
  
      if shape is not None:
          self._shape = check_shape(shape)
      else:
          if self.shape is None:
              # shape not already set, try to infer dimensions
              try:
                  M = len(self.indptr) - 1
                  N = self.indices.max() + 1
              except Exception as e:
                  raise ValueError(
                      "unable to infer matrix dimensions"
                  ) from e
              else:
                  R, C = self.blocksize
                  self._shape = check_shape((M * R, N * C))
  
      if self.shape is None:
          if shape is None:
              # TODO infer shape here
              raise ValueError("need to infer shape")
          else:
              self._shape = check_shape(shape)
  
      if dtype is not None:
          self.data = self.data.astype(dtype, copy=False)
  
      self.check_format(full_check=False)
  
imports: from warnings import warn
  import numpy
  from .data import _data_matrix, _minmax_mixin
  from .compressed import _cs_matrix
  from .base import isspmatrix, _formats, spmatrix
  from .sputils import isshape, getdtype, getdata, to_native, upcast, get_index_dtype, check_shape
  from .None import _sparsetools
  from ._sparsetools import bsr_matvec, bsr_matvecs, csr_matmat_maxnnz, bsr_matmat, bsr_transpose, bsr_sort_indices, bsr_tocsr
label_desc: Use image node_id 1 to create a new bsr_matrix object from inherited base classes: _cs_matrix, _minmax_mixin with example: obj = bsr_matrix(arg1, shape, dtype, copy, blocksize)