Program Listing for File tinymatrix.hpp

Return to documentation for file (/home/docs/checkouts/readthedocs.org/user_builds/intel-qs/checkouts/docs/include/tinymatrix.hpp)

// Copyright (C) 2015 Theoretical Physics, ETH Zurich
//
// Licensed under the Apache License, Version 2.0 (the "License");
// 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.

#ifndef IQS_TINYMATRIX_HPP
#define IQS_TINYMATRIX_HPP

#include <cassert>
#include <initializer_list>
#include <iostream>



namespace qhipster {



template <class ValueType, unsigned M, unsigned N = M, unsigned align = alignof(ValueType)>
class TinyMatrix
{
 public:
  using value_type = ValueType;
  using pointer = ValueType*;
  using const_pointer = ValueType const*;
  using reference = ValueType&;
  using size_type = unsigned;

  using RowType = ValueType[N];

  TinyMatrix() { static_assert(N * M != 0, "a zero-dimensional matrix is not allowed"); }


  template <class U>
  // TinyMatrix(U const (init)[M][N])
  TinyMatrix(U init[M][N])
  {
    for (size_type i = 0; i < this->numRows(); ++i)
      for (size_type j = 0; j < this->numCols(); ++j) data_[i][j] = init[i][j];
  }

  template <class U>
  TinyMatrix(std::initializer_list<std::initializer_list<U>> const& init)
  {
    unsigned i = 0;
    for (auto const& line : init) {
      unsigned j = 0;
      for (auto const& elem : line) data_[i][j++] = elem;
      ++i;
    }
  }


  template <class U, unsigned alignrhs>
  TinyMatrix(TinyMatrix<U, M, N, alignrhs> const& rhs)
  {
    for (size_type i = 0; i < this->numRows(); ++i)
      for (size_type j = 0; j < this->numCols(); ++j) data_[i][j] = rhs(i, j);
  }


  TinyMatrix(TinyMatrix const&) = default;

  TinyMatrix& operator=(TinyMatrix const&) = default;


  template <class U, unsigned alignrhs>
  TinyMatrix& operator=(TinyMatrix<U, M, N, alignrhs> const& rhs)
  {
    for (size_type i = 0; i < this->numRows(); ++i)
      for (size_type j = 0; j < this->numCols(); ++j) data_[i][j] = rhs(i, j);
    return *this;
  }

  template <class U>
  TinyMatrix& operator=(U const (&rhs)[M][N])
  {
    for (size_type i = 0; i < this->numRows(); ++i)
      for (size_type j = 0; j < this->numCols(); ++j) data_[i][j] = rhs[i][j];
    return *this;
  }


  constexpr size_type numRows() const { return M; }
  constexpr size_type numCols() const { return N; }
  constexpr size_type size() const { return N * M; }
  value_type operator()(unsigned i, unsigned j) const
  {
    assert(i < this->numRows() && j < this->numCols());
    return data_[i][j];
  }


  reference operator()(unsigned i, unsigned j)
  {
    assert(i < this->numRows() && j < this->numCols());
    return data_[i][j];
  }


  template <class U, unsigned alignrhs>
  bool operator==(TinyMatrix<U, M, N, alignrhs> const& rhs) const
  {
    for (size_type i = 0; i < this->numRows(); ++i)
      for (size_type j = 0; j < this->numCols(); ++j)
        if (data_[i][j] != rhs(i, j)) return false;
    return true;
  }


  template <class U, unsigned alignrhs>
  bool operator!=(TinyMatrix<U, M, N, alignrhs> const& rhs) const
  {
    return !(*this == rhs);
  }

  template <class U>
  bool operator==(U const (&rhs)[M][N])
  {
    for (size_type i = 0; i < this->numRows(); ++i)
      for (size_type j = 0; j < this->numCols(); ++j)
        if (data_[i][j] != rhs[i][j]) return false;
    return true;
  }

  template <class U>
  bool operator!=(U const (&rhs)[M][N])
  {
    return !(*this == rhs);
  }


  const_pointer getPtr() const { return &data_[0][0]; }

  RowType& operator[](unsigned i)
  {
    assert(i < this->numRows());
    return data_[i];
  }



  RowType const& operator[](unsigned i) const
  {
    assert(i < this->numRows());
    return data_[i];
  }



  template <unsigned MSub, unsigned NSub = MSub>
  TinyMatrix<ValueType, MSub, NSub, align> getSubMatrix(unsigned i_start = 0,
                                                        unsigned j_start = 0,
                                                        unsigned i_stride = 1,
                                                        unsigned j_stride = 1) const
  {
    assert(i_stride > 0 && j_stride > 0);
    assert((MSub - 1) * i_stride + i_start < M && (NSub - 1) * j_stride + j_start < N);

    TinyMatrix<ValueType, MSub, NSub, align> tmp;

    for (unsigned i = i_start, i_sub = 0; i_sub < MSub; i += i_stride, ++i_sub)
      for (unsigned j = j_start, j_sub = 0; j_sub < NSub; j += j_stride, ++j_sub)
        tmp(i_sub, j_sub) = (*this)(i, j);

    return tmp;
  }


 void print(std::string name)
 {
   printf("name: %s\n", (const char *)name.c_str());
   for (size_type i = 0; i < this->numRows(); ++i) {
     for (size_type j = 0; j < this->numCols(); ++j)
     {
        std::cout << data_[i][j].real() << " + i*" <<  data_[i][j].imag() << " ";
     }
     printf("\n");
   }
 }


 std::string tostr() const
 {
   std::string str;
   str = "{";
   for (size_type i = 0; i < this->numRows(); ++i) {
     str += "{";
     for (size_type j = 0; j < this->numCols(); ++j)
     {
       char s[2048];
       sprintf(s, "%.3lf+%.3lf ",  data_[i][j].real(), data_[i][j].imag());
       str += s;
     }
     str += "}";
   }
   str += "{";
   return str;
 }


 std::string name;
 private:
  alignas(align == 0 ? 8 : align) ValueType data_[M][N];
};


}   // end namespace qhipster


#endif  // header guard IQS_TINYMATRIX_HPP