text: /* file: csr_numeric_table.h */
  /*******************************************************************************
  * Copyright 2014-2017 Intel Corporation
  * All Rights Reserved.
  *
  * If this  software was obtained  under the  Intel Simplified  Software License,
  * the following terms apply:
  *
  * The source code,  information  and material  ("Material") contained  herein is
  * owned by Intel Corporation or its  suppliers or licensors,  and  title to such
  * Material remains with Intel  Corporation or its  suppliers or  licensors.  The
  * Material  contains  proprietary  information  of  Intel or  its suppliers  and
  * licensors.  The Material is protected by  worldwide copyright  laws and treaty
  * provisions.  No part  of  the  Material   may  be  used,  copied,  reproduced,
  * modified, published,  uploaded, posted, transmitted,  distributed or disclosed
  * in any way without Intel's prior express written permission.  No license under
  * any patent,  copyright or other  intellectual property rights  in the Material
  * is granted to  or  conferred  upon  you,  either   expressly,  by implication,
  * inducement,  estoppel  or  otherwise.  Any  license   under such  intellectual
  * property rights must be express and approved by Intel in writing.
  *
  * Unless otherwise agreed by Intel in writing,  you may not remove or alter this
  * notice or  any  other  notice   embedded  in  Materials  by  Intel  or Intel's
  * suppliers or licensors in any way.
  *
  *
  * If this  software  was obtained  under the  Apache License,  Version  2.0 (the
  * "License"), the following terms apply:
  *
  * You may  not use this  file except  in compliance  with  the License.  You may
  * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  *
  *
  * Unless  required  by   applicable  law  or  agreed  to  in  writing,  software
  * distributed under the License  is distributed  on an  "AS IS"  BASIS,  WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *
  * See the   License  for the   specific  language   governing   permissions  and
  * limitations under the License.
  *******************************************************************************/
  
  /*
  //++
  //  Implementation of a compressed sparse row (CSR) numeric table.
  //--
  */
  
  #ifndef __CSR_NUMERIC_TABLE_H__
  #define __CSR_NUMERIC_TABLE_H__
  
  #include "services/base.h"
  #include "data_management/data/numeric_table.h"
  #include "data_management/data/data_serialize.h"
  
  namespace daal
  {
  namespace data_management
  {
  
  namespace interface1
  {
  /**
   * @ingroup numeric_tables
   * @{
   */
  /**
   *  <a name="DAAL-CLASS-DATA_MANAGEMENT__CSRBLOCKDESCRIPTOR"></a>
   *  \brief %Base class that manages buffer memory for read/write operations required by CSR numeric tables.
   */
  template<typename DataType = DAAL_DATA_TYPE>
  class DAAL_EXPORT CSRBlockDescriptor
  {
  public:
      /** \private */
      CSRBlockDescriptor();
  
      /** \private */
      ~CSRBlockDescriptor() { freeValuesBuffer(); freeRowsBuffer(); }
  
      /**
       *  Gets a pointer to the buffer
       *  \return Pointer to the block
       */
      inline DataType *getBlockValuesPtr() const
      {
          if(_rawPtr)
          {
              return (DataType *)_rawPtr;
          }
          return _values_ptr.get();
      }
  
      inline size_t *getBlockColumnIndicesPtr() const { return _cols_ptr.get(); }
      inline size_t *getBlockRowIndicesPtr() const { return _rows_ptr.get(); }
  
      /**
       *  Gets a pointer to the buffer
       *  \return Pointer to the block
       */
      inline services::SharedPtr<DataType> getBlockValuesSharedPtr() const
      {
          if(_rawPtr)
          {
              return services::SharedPtr<DataType>(services::reinterpretPointerCast<DataType, byte>(*_pPtr), (DataType *)_rawPtr);
          }
          return _values_ptr;
      }
  
      inline services::SharedPtr<size_t> getBlockColumnIndicesSharedPtr() const { return _cols_ptr; }
      inline services::SharedPtr<size_t> getBlockRowIndicesSharedPtr() const { return _rows_ptr; }
  
      /**
       *  Returns the number of columns in the block
       *  \return Number of columns
       */
      inline size_t getNumberOfColumns() const { return _ncols; }
  
      /**
       *  Returns the number of rows in the block
       *  \return Number of rows
       */
      inline size_t getNumberOfRows() const { return _nrows; }
  
      /**
       *  Returns number of elements in values array.
       *  \return Number of elements in values array.
       */
      inline size_t getDataSize() const
      {
          return ((_nrows > 0) ? _rows_ptr.get()[_nrows] - _rows_ptr.get()[0] : 0);
      }
  public:
      inline void setValuesPtr( DataType *ptr, size_t nValues )
      {
          _values_ptr = services::SharedPtr<DataType>(ptr, services::EmptyDeleter());
          _nvalues    = nValues;
      }
  
      inline void setColumnIndicesPtr( size_t *ptr, size_t nValues )
      {
          _cols_ptr   = services::SharedPtr<size_t>(ptr, services::EmptyDeleter());
          _nvalues    = nValues;
      }
  
      /**
       *  \param[in] ptr      Pointer to the buffer
       *  \param[in] nRows    Number of rows
       */
      inline void setRowIndicesPtr( size_t *ptr, size_t nRows )
      {
          _rows_ptr   = services::SharedPtr<size_t>(ptr, services::EmptyDeleter());
          _nrows = nRows;
      }
  
      inline void setValuesPtr( services::SharedPtr<DataType> ptr, size_t nValues )
      {
          _values_ptr = ptr;
          _nvalues    = nValues;
      }
  
      inline void setValuesPtr( services::SharedPtr<byte> *pPtr, byte* rawPtr, size_t nValues)
      {
          _pPtr = pPtr;
          _rawPtr = rawPtr;
          _nvalues = nValues;
      }
  
      inline void setColumnIndicesPtr( services::SharedPtr<size_t> ptr, size_t nValues )
      {
          _cols_ptr   = ptr;
          _nvalues    = nValues;
      }
  
      /**
       *  \param[in] ptr      Pointer to the buffer
       *  \param[in] nRows    Number of rows
       */
      inline void setRowIndicesPtr( services::SharedPtr<size_t> ptr, size_t nRows )
      {
          _rows_ptr = ptr;
          _nrows = nRows;
      }
  
      /**
       * Reset internal values and pointers to zero values
       */
      inline void reset()
      {
          _ncols = 0;
          _rowsOffset = 0;
          _rwFlag = 0;
          _pPtr = NULL;
          _rawPtr = NULL;
      }
  
      /**
       *  \param[in] nValues  Number of values
       */
      inline bool resizeValuesBuffer( size_t nValues )
      {
          size_t newSize = nValues * sizeof(DataType);
          if ( newSize > _values_capacity )
          {
              freeValuesBuffer();
              _values_buffer = services::SharedPtr<DataType>((DataType *)daal::services::daal_malloc(newSize), services::ServiceDeleter()) ;
              if ( _values_buffer )
              {
                  _values_capacity = newSize;
              }
              else
              {
                  return false;
              }
          }
  
          _values_ptr = _values_buffer;
  
          return true;
      }
  
      /**
       *  \param[in] nRows    Number of rows
       */
      inline bool resizeRowsBuffer( size_t nRows )
      {
          _nrows = nRows;
          size_t newSize = (nRows + 1) * sizeof(size_t);
          if ( newSize > _rows_capacity )
          {
              freeRowsBuffer();
              _rows_buffer = services::SharedPtr<size_t>((size_t *)daal::services::daal_malloc(newSize), services::ServiceDeleter()) ;
              if ( _rows_buffer )
              {
                  _rows_capacity = newSize;
              }
              else
              {
                  return false;
              }
  
          }
  
          _rows_ptr = _rows_buffer;
  
          return true;
      }
  
      inline void setDetails( size_t nColumns, size_t rowIdx, int rwFlag )
      {
          _ncols      = nColumns;
          _rowsOffset = rowIdx;
          _rwFlag     = rwFlag;
      }
  
      inline size_t getRowsOffset() const { return _rowsOffset; }
      inline size_t getRWFlag() const { return _rwFlag; }
  
  protected:
      /**
       *  Frees the values buffer
       */
      void freeValuesBuffer()
      {
          if(_values_buffer)
          {
              _values_buffer = services::SharedPtr<DataType>();
          }
          _values_capacity = 0;
      }
  
      /**
       *  Frees the rows buffer
       */
      void freeRowsBuffer()
      {
          _rows_buffer = services::SharedPtr<size_t>();
          _rows_capacity = 0;
      }
  
  private:
      services::SharedPtr<DataType> _values_ptr;
      services::SharedPtr<size_t> _cols_ptr;
      services::SharedPtr<size_t> _rows_ptr;
      size_t    _nrows;
      size_t    _ncols;
      size_t    _nvalues;
  
      size_t _rowsOffset;
      int    _rwFlag;
  
      services::SharedPtr<DataType> _values_buffer; /*<! Pointer to the buffer */
      size_t _values_capacity; /*<! Buffer size in bytes */
  
      services::SharedPtr<size_t> _rows_buffer; /*<! Pointer to the buffer */
      size_t _rows_capacity; /*<! Buffer size in bytes */
  
      services::SharedPtr<byte> *_pPtr;
      byte *_rawPtr;
  };
  
  /**
   *  <a name="DAAL-CLASS-DATA_MANAGEMENT__CSRNUMERICTABLEIFACE"></a>
   *  \brief Abstract class that defines the interface of CSR numeric tables
   */
  class CSRNumericTableIface
  {
  public:
      /**
       * <a name="DAAL-ENUM-DATA_MANAGEMENT__CSRINDEXING"></a>
       * \brief Enumeration to specify the indexing scheme for access to data in the CSR layout
       */
      enum CSRIndexing
      {
          zeroBased = 0, /*!< 0-based indexing */
          oneBased  = 1  /*!< 1-based indexing */
      };
  
  public:
  
      virtual ~CSRNumericTableIface() {}
  
      /**
       *  Returns number of elements in values array.
       *
       *  \return Number of elements in values array.
       */
      virtual size_t getDataSize() = 0;
      /**
       *  Gets a block of feature vectors in the CSR layout.
       *
       *  \param[in] vector_idx       Index of the first row to include into the block.
       *  \param[in] vector_num       Number of rows in the block.
       *  \param[in] rwflag           Flag specifying read/write access to the block of feature vectors.
       *  \param[out] block           The block of feature values.
       *
       *  \return Actual number of feature vectors returned by the method.
       */
      virtual services::Status getSparseBlock(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, CSRBlockDescriptor<double> &block) = 0;
  
      /**
       *  Gets a block of feature vectors in the CSR layout.
       *
       *  \param[in] vector_idx       Index of the first row to include into the block.
       *  \param[in] vector_num       Number of rows in the block.
       *  \param[in] rwflag           Flag specifying read/write access to the block of feature vectors.
       *  \param[out] block           The block of feature values.
       *
       *  \return Actual number of feature vectors returned by the method.
       */
      virtual services::Status getSparseBlock(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, CSRBlockDescriptor<float> &block) = 0;
  
      /**
       *  Gets a block of feature vectors in the CSR layout.
       *
       *  \param[in] vector_idx       Index of the first row to include into the block.
       *  \param[in] vector_num       Number of rows in the block.
       *  \param[in] rwflag           Flag specifying read/write access to the block of feature vectors.
       *  \param[out] block           The block of feature values.
       *
       *  \return Actual number of feature vectors returned by the method.
       */
      virtual services::Status getSparseBlock(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, CSRBlockDescriptor<int> &block) = 0;
  
      /**
       *  Releases a block of feature vectors in the CSR layout.
       *  \param[in] block           The block of feature values.
       */
      virtual services::Status releaseSparseBlock(CSRBlockDescriptor<double> &block) = 0;
  
      /**
       *  Releases a block of feature vectors in the CSR layout.
       *  \param[in] block           The block of feature values.
       */
      virtual services::Status releaseSparseBlock(CSRBlockDescriptor<float> &block) = 0;
  
      /**
       *  Releases a block of feature vectors in the CSR layout.
       *  \param[in] block           The block of feature values.
       */
      virtual services::Status releaseSparseBlock(CSRBlockDescriptor<int> &block) = 0;
  };
  
  /**
   *  <a name="DAAL-CLASS-DATA_MANAGEMENT__CSRNUMERICTABLE"></a>
   *  \brief Class that provides methods to access data stored in the CSR layout.
   */
  class DAAL_EXPORT CSRNumericTable : public NumericTable, public CSRNumericTableIface
  {
  public:
      DECLARE_SERIALIZABLE_TAG();
      DECLARE_SERIALIZABLE_IMPL();
  
      DAAL_CAST_OPERATOR(CSRNumericTable)
      /**
       *  Constructor for an empty CSR Numeric Table
       *  \DAAL_DEPRECATED_USE{ CSRNumericTable::create }
       */
      CSRNumericTable(): NumericTable(0, 0, DictionaryIface::equal), _indexing(oneBased)
      {
          _layout = csrArray;
          this->_status |= setArrays<double>( 0, 0, 0 ); //data type doesn't matter
      }
  
      /**
       *  Constructor for a Numeric Table with user-allocated memory
       *  \tparam   DataType        Type of values in the Numeric Table
       *  \param[in]    ptr         Array of values in the CSR layout. Let ptr_size denote the size of an array ptr
       *  \param[in]    colIndices  Array of column indices in the CSR layout. Values of indices are determined by the index base
       *  \param[in]    rowOffsets  Array of row indices in the CSR layout. Size of the array is nrow+1. The first element is 0/1
       *                            in zero-/one-based indexing. The last element is ptr_size+0/1 in zero-/one-based indexing
       *  \param[in]    nColumns    Number of columns in the corresponding dense table
       *  \param[in]    nRows       Number of rows in the corresponding dense table
       *  \param[in]    indexing    Indexing scheme used to access data in the CSR layout
       *  \note Present version of Intel(R) Data Analytics Acceleration Library supports 1-based indexing only
       *  \DAAL_DEPRECATED_USE{ CSRNumericTable::create }
       */
      template<typename DataType>
      CSRNumericTable( DataType *const ptr, size_t *colIndices = 0, size_t *rowOffsets = 0,
                       size_t nColumns = 0, size_t nRows = 0, CSRIndexing indexing = oneBased ):
          NumericTable(nColumns, nRows, DictionaryIface::equal), _indexing(indexing)
      {
          _layout = csrArray;
          this->_status |= setArrays<DataType>(ptr, colIndices, rowOffsets);
  
          _defaultFeature.setType<DataType>();
          this->_status |= _ddict->setAllFeatures( _defaultFeature );
      }
  
  
      /**
       *  Constructs CSR numeric table with user-allocated memory
       *  \tparam   DataType        Type of values in the numeric table
       *  \param[in]    ptr         Array of values in the CSR layout. Let ptr_size denote the size of an array ptr
       *  \param[in]    colIndices  Array of column indices in the CSR layout. Values of indices are determined by the index base
       *  \param[in]    rowOffsets  Array of row indices in the CSR layout. Size of the array is nrow+1. The first element is 0/1
       *                            in zero-/one-based indexing. The last element is ptr_size+0/1 in zero-/one-based indexing
       *  \param[in]    nColumns    Number of columns in the corresponding dense table
       *  \param[in]    nRows       Number of rows in the corresponding dense table
       *  \param[in]    indexing    Indexing scheme used to access data in the CSR layout
       *  \param[out]   stat        Status of the numeric table construction
       *  \return CSR numeric table with user-allocated memory
       *  \note Present version of Intel(R) Data Analytics Acceleration Library supports 1-based indexing only
       */
      template<typename DataType>
      static services::SharedPtr<CSRNumericTable> create(DataType *const ptr, size_t *colIndices = 0, size_t *rowOffsets = 0,
                                                         size_t nColumns = 0, size_t nRows = 0, CSRIndexing indexing = oneBased,
                                                         services::Status *stat = NULL)
      {
          return create<DataType>(services::SharedPtr<DataType>(ptr, services::EmptyDeleter()),
                                  services::SharedPtr<size_t>(colIndices, services::EmptyDeleter()),
                                  services::SharedPtr<size_t>(rowOffsets, services::EmptyDeleter()),
                                  nColumns, nRows, indexing, stat);
      }
  
      /**
       *  Constructor for a Numeric Table with user-allocated memory
       *  \tparam   DataType        Type of values in the Numeric Table
       *  \param[in]    ptr         Array of values in the CSR layout. Let ptr_size denote the size of an array ptr
       *  \param[in]    colIndices  Array of column indices in the CSR layout. Values of indices are determined by the index base
       *  \param[in]    rowOffsets  Array of row indices in the CSR layout. Size of the array is nrow+1. The first element is 0/1
       *                            in zero-/one-based indexing. The last element is ptr_size+0/1 in zero-/one-based indexing
       *  \param[in]    nColumns    Number of columns in the corresponding dense table
       *  \param[in]    nRows       Number of rows in the corresponding dense table
       *  \param[in]    indexing    Indexing scheme used to access data in the CSR layout
       *  \note Present version of Intel(R) Data Analytics Acceleration Library supports 1-based indexing only
       *  \DAAL_DEPRECATED_USE{ CSRNumericTable::create }
       */
      template<typename DataType>
      CSRNumericTable( const services::SharedPtr<DataType>& ptr, const services::SharedPtr<size_t>& colIndices, const services::SharedPtr<size_t>& rowOffsets,
                       size_t nColumns, size_t nRows, CSRIndexing indexing = oneBased ):
          NumericTable(nColumns, nRows, DictionaryIface::equal), _indexing(indexing)
      {
          _layout = csrArray;
          this->_status |= setArrays<DataType>(ptr, colIndices, rowOffsets);
  
          _defaultFeature.setType<DataType>();
          this->_status |= _ddict->setAllFeatures( _defaultFeature );
      }
  
      /**
       *  Constructs CSR numeric table with user-allocated memory
       *  \tparam   DataType        Type of values in the Numeric Table
       *  \param[in]    ptr         Array of values in the CSR layout. Let ptr_size denote the size of an array ptr
       *  \param[in]    colIndices  Array of column indices in the CSR layout. Values of indices are determined by the index base
       *  \param[in]    rowOffsets  Array of row indices in the CSR layout. Size of the array is nrow+1. The first element is 0/1
       *                            in zero-/one-based indexing. The last element is ptr_size+0/1 in zero-/one-based indexing
       *  \param[in]    nColumns    Number of columns in the corresponding dense table
       *  \param[in]    nRows       Number of rows in the corresponding dense table
       *  \param[in]    indexing    Indexing scheme used to access data in the CSR layout
       *  \param[out]   stat        Status of the numeric table construction
       *  \return       CSR numeric table with user-allocated memory
       *  \note Present version of Intel(R) Data Analytics Acceleration Library supports 1-based indexing only
       */
      template<typename DataType>
      static services::SharedPtr<CSRNumericTable> create(const services::SharedPtr<DataType>& ptr,
                                                         const services::SharedPtr<size_t>& colIndices,
                                                         const services::SharedPtr<size_t>& rowOffsets,
                                                         size_t nColumns, size_t nRows, CSRIndexing indexing = oneBased,
                                                         services::Status *stat = NULL)
      {
          DAAL_DEFAULT_CREATE_IMPL_EX(CSRNumericTable, ptr, colIndices, rowOffsets, nColumns, nRows, indexing);
      }
  
      virtual ~CSRNumericTable()
      {
          freeDataMemoryImpl();
      }
  
      virtual services::Status resize(size_t nrows) DAAL_C11_OVERRIDE
      {
          return setNumberOfRowsImpl(nrows);
      }
  
      /**
       *  Returns  pointers to a data set stored in the CSR layout
       *  \param[out]    ptr         Array of values in the CSR layout
       *  \param[out]    colIndices  Array of column indices in the CSR layout
       *  \param[out]    rowOffsets  Array of row indices in the CSR layout
       */
      template<typename DataType>
      services::Status getArrays(DataType **ptr, size_t **colIndices, size_t **rowOffsets) const
      {
          if (ptr) { *ptr = (DataType*)_ptr.get(); }
          if (colIndices) { *colIndices = _colIndices.get(); }
          if (rowOffsets) { *rowOffsets = _rowOffsets.get(); }
          return services::Status();
      }
  
      /**
       *  Returns  pointers to a data set stored in the CSR layout
       *  \param[out]    ptr         Array of values in the CSR layout
       *  \param[out]    colIndices  Array of column indices in the CSR layout
       *  \param[out]    rowOffsets  Array of row indices in the CSR layout
       */
      template<typename DataType>
      services::Status getArrays(services::SharedPtr<DataType> &ptr, services::SharedPtr<size_t> &colIndices, services::SharedPtr<size_t> &rowOffsets) const
      {
          if(ptr) { *ptr = _ptr; }
          if (colIndices) { *colIndices = _colIndices; }
          if (rowOffsets) { *rowOffsets = _rowOffsets; }
          return services::Status();
      }
  
      /**
       *  Sets a pointer to a CSR data set
       *  \param[in]    ptr         Array of values in the CSR layout
       *  \param[in]    colIndices  Array of column indices in the CSR layout
       *  \param[in]    rowOffsets  Array of row indices in the CSR layout
       *  \param[in]    indexing    The indexing scheme for access to data in the CSR layout
       */
      template<typename DataType>
      services::Status setArrays(DataType *const ptr, size_t *colIndices, size_t *rowOffsets, CSRIndexing indexing = oneBased)
      {
          freeDataMemoryImpl();
  
          //if( ptr == 0 || colIndices == 0 || rowOffsets == 0 ) return services::Status(services::ErrorEmptyCSRNumericTable);
  
          _ptr = services::SharedPtr<byte>((byte*)ptr, services::EmptyDeleter());
          _colIndices = services::SharedPtr<size_t>(colIndices, services::EmptyDeleter());
          _rowOffsets = services::SharedPtr<size_t>(rowOffsets, services::EmptyDeleter());
          _indexing = indexing;
  
          if( ptr != 0 && colIndices != 0 && rowOffsets != 0 ) { _memStatus  = userAllocated; }
          return services::Status();
      }
  
      /**
       *  Sets a pointer to a CSR data set
       *  \param[in]    ptr         Array of values in the CSR layout
       *  \param[in]    colIndices  Array of column indices in the CSR layout
       *  \param[in]    rowOffsets  Array of row indices in the CSR layout
       *  \param[in]    indexing    The indexing scheme for access to data in the CSR layout
       */
      template<typename DataType>
      services::Status setArrays(const services::SharedPtr<DataType>& ptr, const services::SharedPtr<size_t>& colIndices, const services::SharedPtr<size_t>& rowOffsets, CSRIndexing indexing = oneBased)
      {
          freeDataMemoryImpl();
  
          //if( ptr == 0 || colIndices == 0 || rowOffsets == 0 ) return services::Status(services::ErrorEmptyCSRNumericTable);
  
          _ptr = services::reinterpretPointerCast<byte, DataType>(ptr);
          _colIndices = colIndices;
          _rowOffsets = rowOffsets;
          _indexing = indexing;
  
          if( ptr && colIndices && rowOffsets ) { _memStatus  = userAllocated; }
          return services::Status();
      }
  
      services::Status getBlockOfRows(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, BlockDescriptor<double> &block) DAAL_C11_OVERRIDE
      {
          return getTBlock<double>(vector_idx, vector_num, rwflag, block);
      }
      services::Status getBlockOfRows(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, BlockDescriptor<float> &block) DAAL_C11_OVERRIDE
      {
          return getTBlock<float>(vector_idx, vector_num, rwflag, block);
      }
      services::Status getBlockOfRows(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, BlockDescriptor<int> &block) DAAL_C11_OVERRIDE
      {
          return getTBlock<int>(vector_idx, vector_num, rwflag, block);
      }
  
      services::Status releaseBlockOfRows(BlockDescriptor<double> &block) DAAL_C11_OVERRIDE
      {
           return releaseTBlock<double>(block);
      }
      services::Status releaseBlockOfRows(BlockDescriptor<float> &block) DAAL_C11_OVERRIDE
      {
           return releaseTBlock<float>(block);
      }
      services::Status releaseBlockOfRows(BlockDescriptor<int> &block) DAAL_C11_OVERRIDE
      {
           return releaseTBlock<int>(block);
      }
  
      services::Status getBlockOfColumnValues(size_t feature_idx, size_t vector_idx, size_t value_num,
                                  ReadWriteMode rwflag, BlockDescriptor<double> &block) DAAL_C11_OVERRIDE
      {
          return getTFeature<double>(feature_idx, vector_idx, value_num, rwflag, block);
      }
      services::Status getBlockOfColumnValues(size_t feature_idx, size_t vector_idx, size_t value_num,
                                  ReadWriteMode rwflag, BlockDescriptor<float> &block) DAAL_C11_OVERRIDE
      {
          return getTFeature<float>(feature_idx, vector_idx, value_num, rwflag, block);
      }
      services::Status getBlockOfColumnValues(size_t feature_idx, size_t vector_idx, size_t value_num,
                                  ReadWriteMode rwflag, BlockDescriptor<int> &block) DAAL_C11_OVERRIDE
      {
          return getTFeature<int>(feature_idx, vector_idx, value_num, rwflag, block);
      }
  
      services::Status releaseBlockOfColumnValues(BlockDescriptor<double> &block) DAAL_C11_OVERRIDE
      {
           return releaseTFeature<double>(block);
      }
      services::Status releaseBlockOfColumnValues(BlockDescriptor<float> &block) DAAL_C11_OVERRIDE
      {
           return releaseTFeature<float>(block);
      }
      services::Status releaseBlockOfColumnValues(BlockDescriptor<int> &block) DAAL_C11_OVERRIDE
      {
           return releaseTFeature<int>(block);
      }
  
  
      services::Status getSparseBlock(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, CSRBlockDescriptor<double> &block) DAAL_C11_OVERRIDE
      {
          return getSparseTBlock<double>(vector_idx, vector_num, rwflag, block);
      }
      services::Status getSparseBlock(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, CSRBlockDescriptor<float> &block) DAAL_C11_OVERRIDE
      {
          return getSparseTBlock<float>(vector_idx, vector_num, rwflag, block);
      }
      services::Status getSparseBlock(size_t vector_idx, size_t vector_num, ReadWriteMode rwflag, CSRBlockDescriptor<int> &block) DAAL_C11_OVERRIDE
      {
          return getSparseTBlock<int>(vector_idx, vector_num, rwflag, block);
      }
  
      services::Status releaseSparseBlock(CSRBlockDescriptor<double> &block) DAAL_C11_OVERRIDE
      {
          return releaseSparseTBlock<double>(block);
      }
      services::Status releaseSparseBlock(CSRBlockDescriptor<float> &block) DAAL_C11_OVERRIDE
      {
          return releaseSparseTBlock<float>(block);
      }
      services::Status releaseSparseBlock(CSRBlockDescriptor<int> &block) DAAL_C11_OVERRIDE
      {
          return releaseSparseTBlock<int>(block);
      }
  
      /**
       *  Allocates memory for a data set
       *  \param[in]    dataSize     Number of non-zero values
       *  \param[in]    type         Memory type
       */
      services::Status allocateDataMemory(size_t dataSize, daal::MemType type = daal::dram)
      {
          freeDataMemoryImpl();
  
          size_t nrow = getNumberOfRows();
  
          if( nrow == 0 )
              return services::Status(services::ErrorIncorrectNumberOfObservations);
  
          NumericTableFeature &f = (*_ddict)[0];
  
          _ptr        = services::SharedPtr<byte>  (   (byte*)daal::services::daal_malloc( dataSize   * f.typeSize     ), services::ServiceDeleter  ());
          _colIndices = services::SharedPtr<size_t>((size_t *)daal::services::daal_malloc( dataSize   * sizeof(size_t) ), services::ServiceDeleter());
          _rowOffsets = services::SharedPtr<size_t>((size_t *)daal::services::daal_malloc( (nrow + 1) * sizeof(size_t) ), services::ServiceDeleter());
  
          _memStatus = internallyAllocated;
  
          if( !_ptr || !_colIndices || !_rowOffsets )
          {
              freeDataMemoryImpl();
              return services::Status(services::ErrorMemoryAllocationFailed);
          }
  
          _rowOffsets.get()[0] = ((_indexing == oneBased) ? 1 : 0);
          return services::Status();
      }
  
      /**
       * Returns the indexing scheme for access to data in the CSR layout
       * \return  CSR layout indexing
       */
      CSRIndexing getCSRIndexing() const
      {
          return _indexing;
      }
  
      /**
       * \copydoc NumericTableIface::check
       */
      virtual services::Status check(const char *description, bool checkDataAllocation = true) const DAAL_C11_OVERRIDE
      {
          services::Status s;
          DAAL_CHECK_STATUS(s, data_management::NumericTable::check(description, checkDataAllocation));
  
          if( _indexing != oneBased )
          {
              return services::Status(services::Error::create(services::ErrorUnsupportedCSRIndexing, services::ArgumentName, description));
          }
  
          return services::Status();
      }
  
  protected:
      NumericTableFeature _defaultFeature;
      CSRIndexing _indexing;
  
      services::SharedPtr<byte> _ptr;
      services::SharedPtr<size_t> _colIndices;
      services::SharedPtr<size_t> _rowOffsets;
  
      template<typename DataType>
      CSRNumericTable(const services::SharedPtr<DataType>& ptr, const services::SharedPtr<size_t>& colIndices, const services::SharedPtr<size_t>& rowOffsets,
                      size_t nColumns, size_t nRows, CSRIndexing indexing,
                      services::Status &st):
          NumericTable(nColumns, nRows, DictionaryIface::equal, st), _indexing(indexing)
      {
          _layout = csrArray;
          st |= setArrays<DataType>(ptr, colIndices, rowOffsets);
  
          _defaultFeature.setType<DataType>();
          st |= _ddict->setAllFeatures( _defaultFeature );
      }
  
      services::Status allocateDataMemoryImpl(daal::MemType type = daal::dram) DAAL_C11_OVERRIDE
      {
          return services::Status(services::ErrorMethodNotSupported);
      }
  
      void freeDataMemoryImpl() DAAL_C11_OVERRIDE
      {
          _ptr = services::SharedPtr<byte>();
          _colIndices = services::SharedPtr<size_t>();
          _rowOffsets = services::SharedPtr<size_t>();
  
          _memStatus  = notAllocated;
      }
  
  
      /** \private */
      template<typename Archive, bool onDeserialize>
      services::Status serialImpl( Archive *arch )
      {
          NumericTable::serialImpl<Archive, onDeserialize>( arch );
  
          size_t dataSize = 0;
          if( !onDeserialize )
          {
              dataSize = getDataSize();
          }
          arch->set( dataSize );
  
          if( onDeserialize )
          {
              allocateDataMemory( dataSize );
          }
  
          size_t nfeat = getNumberOfColumns();
          size_t nobs  = getNumberOfRows();
  
          if( nfeat > 0 )
          {
              NumericTableFeature &f = (*_ddict)[0];
  
              arch->set( (char *)_ptr.get(), dataSize * f.typeSize );
              arch->set( _colIndices.get(), dataSize );
              arch->set( _rowOffsets.get(), nobs + 1   );
          }
  
          return services::Status();
      }
  
  
  public:
      size_t getDataSize() DAAL_C11_OVERRIDE
      {
          size_t nobs  = getNumberOfRows();
          if( nobs > 0)
          {
              return _rowOffsets.get()[nobs] - _rowOffsets.get()[0];
          }
          else
          {
              return 0;
          }
      }
  
  protected:
  
      template <typename T>
      services::Status getTBlock(size_t idx, size_t nrows, int rwFlag, BlockDescriptor<T> &block)
      {
          size_t ncols = getNumberOfColumns();
          size_t nobs  = getNumberOfRows();
          block.setDetails( 0, idx, rwFlag );
          size_t* rowOffsets = _rowOffsets.get();
  
          if (idx >= nobs)
          {
              block.resizeBuffer( ncols, 0 );
              return services::Status();
          }
  
          NumericTableFeature &f = (*_ddict)[0];
  
          T* buffer;
          T* castingBuffer;
          T* location = (T*)(_ptr.get() + (rowOffsets[idx] - 1) * f.typeSize);
  
          if( data_feature_utils::getIndexNumType<T>() == f.indexType )
          {
              castingBuffer = location;
  
              if( !block.resizeBuffer( ncols, nrows ) )
                  return services::Status(services::ErrorMemoryAllocationFailed);
              buffer = block.getBlockPtr();
          }
          else
          {
              size_t sparseBlockSize = rowOffsets[idx + nrows] - rowOffsets[idx];
  
              if( !block.resizeBuffer( ncols, nrows, sparseBlockSize * sizeof(T) ) )
                  return services::Status(services::ErrorMemoryAllocationFailed);
              buffer = block.getBlockPtr();
  
              castingBuffer = (T*)block.getAdditionalBufferPtr();
  
              data_feature_utils::getVectorUpCast(f.indexType,data_feature_utils::getInternalNumType<T>())
              ( sparseBlockSize, location, castingBuffer );
          }
  
          T *bufRowCursor       = castingBuffer;
          size_t *indicesCursor = _colIndices.get() + rowOffsets[idx] - 1;
  
          for( size_t i = 0; i < ncols * nrows; i++ ) { buffer[i] = (T)0; }
  
          for( size_t i = 0; i < nrows; i++ )
          {
              size_t sparseRowSize = rowOffsets[idx + i + 1] - rowOffsets[idx + i];
  
              for( size_t k = 0; k < sparseRowSize; k++ )
              {
                  buffer[i * ncols + indicesCursor[k] - 1] = bufRowCursor[k];
              }
  
              bufRowCursor  += sparseRowSize;
              indicesCursor += sparseRowSize;
          }
          return services::Status();
      }
  
      template <typename T>
      services::Status releaseTBlock( BlockDescriptor<T> &block )
      {
          if (!(block.getRWFlag() & (int)writeOnly))
              block.reset();
          return services::Status();
      }
  
      template <typename T>
      services::Status getTFeature(size_t feat_idx, size_t idx, size_t nrows, int rwFlag, BlockDescriptor<T> &block)
      {
          size_t ncols = getNumberOfColumns();
          size_t nobs = getNumberOfRows();
          block.setDetails( feat_idx, idx, rwFlag );
          size_t* rowOffsets = _rowOffsets.get();
  
          if (idx >= nobs)
          {
              block.resizeBuffer( 1, 0 );
              return services::Status();
          }
  
          nrows = ( idx + nrows < nobs ) ? nrows : nobs - idx;
  
          if( !block.resizeBuffer( 1, nrows ) )
              return services::Status(services::ErrorMemoryAllocationFailed);
  
          NumericTableFeature &f = (*_ddict)[0];
  
          char   *rowCursor     = (char *)_ptr.get() + (rowOffsets[idx] - 1) * f.typeSize;
          size_t *indicesCursor = _colIndices.get() + (rowOffsets[idx] - 1);
  
          T* bufferPtr = block.getBlockPtr();
  
          for(size_t i = 0; i < nrows; i++)
          {
              bufferPtr[i] = (T)0;
  
              size_t sparseRowSize = rowOffsets[idx + i + 1] - rowOffsets[idx + i];
  
              for(size_t k = 0; k < sparseRowSize; k++)
              {
                  if( indicesCursor[k] - 1 == feat_idx )
                  {
                      data_feature_utils::getVectorUpCast(f.indexType, data_feature_utils::getInternalNumType<T>())
                      ( 1, rowCursor + k * f.typeSize, bufferPtr + i );
                  }
              }
  
              rowCursor     += sparseRowSize * f.typeSize;
              indicesCursor += sparseRowSize;
          }
          return services::Status();
      }
  
      template <typename T>
      services::Status releaseTFeature( BlockDescriptor<T> &block )
      {
          if(block.getRWFlag() & (int)writeOnly)
              return services::Status();
          block.reset();
          return services::Status();
      }
  
      template <typename T>
      services::Status getSparseTBlock( size_t idx, size_t nrows, int rwFlag, CSRBlockDescriptor<T> &block )
      {
          size_t ncols = getNumberOfColumns();
          size_t nobs  = getNumberOfRows();
          block.setDetails( ncols, idx, rwFlag );
          size_t* rowOffsets = _rowOffsets.get();
  
          if (idx >= nobs)
          {
              block.resizeValuesBuffer( 0 );
              return services::Status();
          }
  
          nrows = ( idx + nrows < nobs ) ? nrows : nobs - idx;
  
          NumericTableFeature &f = (*_ddict)[0];
  
  
          size_t nValues = rowOffsets[idx + nrows] - rowOffsets[idx];
  
          if( data_feature_utils::getIndexNumType<T>() == f.indexType )
          {
              block.setValuesPtr(&_ptr, _ptr.get() +(rowOffsets[idx] - 1) * f.typeSize, nValues);
          }
          else
          {
              if( !block.resizeValuesBuffer(nValues) ) { return  services::Status(); }
  
              services::SharedPtr<byte> location(_ptr, _ptr.get() +(rowOffsets[idx] - 1) * f.typeSize);
              data_feature_utils::getVectorUpCast(f.indexType, data_feature_utils::getInternalNumType<T>())
              ( nValues, location.get(), block.getBlockValuesPtr() );
          }
  
          services::SharedPtr<size_t> shiftedColumns(_colIndices, _colIndices.get() + (rowOffsets[idx] - 1));
          block.setColumnIndicesPtr( shiftedColumns, nValues );
  
          if( idx == 0 )
          {
              block.setRowIndicesPtr( _rowOffsets, nrows );
          }
          else
          {
              if( !block.resizeRowsBuffer(nrows) ) { return  services::Status(); }
  
              size_t *row_offsets = block.getBlockRowIndicesSharedPtr().get();
  
              for(size_t i = 0; i < nrows + 1; i++)
              {
                  row_offsets[i] = rowOffsets[idx + i] - rowOffsets[idx] + 1;
              }
          }
          return services::Status();
      }
  
      template <typename T>
      services::Status releaseSparseTBlock(CSRBlockDescriptor<T> &block)
      {
          if (block.getRWFlag() & (int)writeOnly)
          {
              NumericTableFeature &f = (*_ddict)[0];
              if (f.indexType != data_feature_utils::getIndexNumType<T>())
              {
                  size_t nrows = block.getNumberOfRows();
                  size_t idx   = block.getRowsOffset();
                  size_t nValues = _rowOffsets.get()[idx + nrows] - _rowOffsets.get()[idx];
  
                  services::SharedPtr<byte> ptr = services::reinterpretPointerCast<byte, T>(block.getBlockValuesSharedPtr());
                  services::SharedPtr<byte> location = services::SharedPtr<byte>(ptr, _ptr.get() + (_rowOffsets.get()[idx] - 1) * f.typeSize);
  
                  data_feature_utils::getVectorDownCast(f.indexType, data_feature_utils::getInternalNumType<T>())
                          (nValues, ptr.get(), location.get());
              }
          }
          block.reset();
          return services::Status();
      }
  
      virtual services::Status setNumberOfColumnsImpl(size_t ncol) DAAL_C11_OVERRIDE
      {
          _ddict->setNumberOfFeatures( ncol );
          _ddict->setAllFeatures( _defaultFeature );
          return services::Status();
      }
  
  };
  typedef services::SharedPtr<CSRNumericTableIface> CSRNumericTableIfacePtr;
  typedef services::SharedPtr<CSRNumericTable> CSRNumericTablePtr;
  /** @} */
  } // namespace interface1
  using interface1::CSRNumericTableIface;
  using interface1::CSRNumericTableIfacePtr;
  using interface1::CSRBlockDescriptor;
  using interface1::CSRNumericTable;
  using interface1::CSRNumericTablePtr;
  
  }
  } // namespace daal
  #endif
  