Program Listing for File vecn.hpp#

↰ Return to documentation for file (source/pele/vecn.hpp)

#ifndef _pele_vecn_h_
#define _pele_vecn_h_

#include <algorithm>
#include <cmath>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <vector>

#include "array.hpp"

namespace pele {

template <size_t N, typename dtype = double>
class VecN {
  dtype m_data[N];

 public:
  VecN() {}

  VecN(dtype const &d) { assign(d); }

  VecN(pele::Array<dtype> const &x) {
    if (x.size() != N) {
      throw std::runtime_error(
          "VecN constructor: array must have the same size as vector");
    }
    std::copy(x.begin(), x.end(), this->begin());
  }

  template <class input_iter>
  VecN(input_iter ibegin, input_iter iend) {
    std::copy(ibegin, iend, this->begin());
  }

  size_t size() const { return N; }

  inline dtype *data() { return m_data; }
  inline dtype const *data() const { return m_data; }

  typedef dtype *iterator;
  typedef dtype const *const_iterator;
  inline iterator begin() { return data(); }
  inline iterator end() { return data() + size(); }
  inline const_iterator begin() const { return data(); }
  inline const_iterator end() const { return data() + size(); }

  inline dtype &operator[](const size_t i) { return m_data[i]; }
  inline dtype const &operator[](const size_t i) const { return m_data[i]; }

  void assign(dtype const &d) { std::fill(begin(), end(), d); }

  void assign(const dtype *const rhs) { std::copy(rhs, rhs + N, begin()); }

  VecN<N, dtype> &operator=(pele::Array<dtype> const &rhs) {
    if (rhs.size() != N) {
      throw std::runtime_error("operator=: array must have the same size");
    }
    std::copy(rhs.begin(), rhs.end(), this->begin());
    return *this;
  }

  /*
   * Compound Assignment Operators += -= *=
   */
  VecN<N, dtype> &operator+=(const VecN<N, dtype> &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] += rhs[i];
    }
    return *this;
  }

  VecN<N, dtype> &operator+=(const dtype &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] += rhs;
    }
    return *this;
  }

  VecN<N, dtype> &operator-=(const VecN<N, dtype> &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] -= rhs[i];
    }
    return *this;
  }

  VecN<N, dtype> &operator-=(const dtype &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] -= rhs;
    }
    return *this;
  }

  VecN<N, dtype> &operator*=(const VecN<N, dtype> &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] *= rhs[i];
    }
    return *this;
  }

  VecN<N, dtype> &operator*=(const dtype &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] *= rhs;
    }
    return *this;
  }

  VecN<N, dtype> &operator/=(const VecN<N, dtype> &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] /= rhs[i];
    }
    return *this;
  }

  VecN<N, dtype> &operator/=(const dtype &rhs) {
    for (size_t i = 0; i < N; ++i) {
      m_data[i] /= rhs;
    }
    return *this;
  }

  VecN<N, dtype> operator-(VecN<N, dtype> const &rhs) const {
    VecN<N, dtype> v;
    for (size_t i = 0; i < N; ++i) {
      v[i] = m_data[i] - rhs[i];
    }
    return v;
  }

  VecN<N, dtype> operator*(const VecN<N, dtype> &rhs) const {
    VecN<N, dtype> v;
    for (size_t i = 0; i < N; ++i) {
      v[i] = m_data[i] * rhs[i];
    }
    return v;
  }

  VecN<N, dtype> operator*(const dtype rhs) const {
    VecN<N, dtype> v;
    for (size_t i = 0; i < N; ++i) {
      v[i] = m_data[i] * rhs;
    }
    return v;
  }

  dtype sum() const {
    dtype sum_array = 0;
    for (size_t i = 0; i < N; ++i) {
      sum_array += m_data[i];
    }
    return sum_array;
  }

  dtype prod() const {
    dtype p = 1;
    for (size_t i = 0; i < N; ++i) {
      p *= m_data[i];
    }
    return p;
  }

};  // close VecN

template <size_t N, size_t M, typename dtype = double>
class MatrixNM {
  static size_t const m_size = N * M;
  dtype m_data[m_size];

 public:
  MatrixNM() {}

  MatrixNM(dtype const &d) { assign(d); }

  MatrixNM(pele::Array<dtype> const &x) {
    if (x.size() != m_size) {
      std::stringstream ss;
      ss << "MatrixNM constructor: array (size " << x.size()
         << ") must have the same size as matrix " << m_size;
      throw std::runtime_error(ss.str());
    }
    for (size_t i = 0; i < m_size; ++i) {
      m_data[i] = x[i];
    }
  }

  size_t size() const { return m_size; }

  inline dtype *data() { return m_data; }
  inline dtype const *data() const { return m_data; }

  typedef dtype *iterator;
  typedef dtype const *const_iterator;
  inline iterator begin() { return data(); }
  inline iterator end() { return data() + size(); }
  inline const_iterator begin() const { return data(); }
  inline const_iterator end() const { return data() + size(); }

  void assign(dtype const &d) { std::fill(begin(), end(), d); }

  inline dtype const &operator()(size_t i, size_t j) const {
    return m_data[i * M + j];
  }
  inline dtype &operator()(size_t i, size_t j) { return m_data[i * M + j]; }

  inline std::pair<size_t, size_t> shape() const {
    return std::pair<size_t, size_t>(N, M);
  }

  MatrixNM<N, M, dtype> &operator*=(dtype const &rhs) {
    for (size_t i = 0; i < m_size; ++i) {
      m_data[i] *= rhs;
    }
    return *this;
  }

  dtype trace() {
    dtype t = 0;
    for (size_t i = 0; i < N; ++i) {
      t += (*this)(i, i);
    }
    return t;
  }

  MatrixNM<N, M, dtype> operator-(MatrixNM<N, M, dtype> const &rhs) const {
    MatrixNM<N, M, dtype> v;
    for (size_t i = 0; i < m_size; ++i) {
      v.m_data[i] = m_data[i] - rhs.m_data[i];
    }
    return v;
  }

};  // close MatrixNM

template <size_t N, typename dtype>
inline double dot(VecN<N, dtype> const &v1, VecN<N, dtype> const &v2) {
  double dot = 0.;
  for (size_t i = 0; i < N; ++i) {
    dot += v1[i] * v2[i];
  }
  return dot;
}

template <size_t N, typename dtype>
inline double norm(VecN<N, dtype> const &v) {
  return sqrt(dot(v, v));
}

template <size_t N, size_t L, size_t M, typename dtype>
MatrixNM<N, M, dtype> dot(MatrixNM<N, L, dtype> const &A,
                          MatrixNM<L, M, dtype> const &B) {
  MatrixNM<N, M, dtype> C(0);
  for (size_t i = 0; i < N; ++i) {
    for (size_t j = 0; j < M; ++j) {
      double val = 0;
      for (size_t k = 0; k < L; ++k) {
        val += A(i, k) * B(k, j);
      }
      C(i, j) = val;
    }
  }
  return C;
}

template <size_t N, size_t M, typename dtype>
pele::VecN<N, dtype> dot(MatrixNM<N, M, dtype> const &A,
                         pele::VecN<M, dtype> const &v) {
  pele::VecN<N, dtype> C(0);
  for (size_t i = 0; i < N; ++i) {
    double val = 0;
    for (size_t k = 0; k < M; ++k) {
      val += A(i, k) * v[k];
    }
    C[i] = val;
  }
  return C;
}

template <size_t N, size_t M, typename dtype>
pele::MatrixNM<M, N, dtype> transpose(MatrixNM<N, M, dtype> const &A) {
  pele::MatrixNM<M, N, dtype> mat;
  for (size_t i = 0; i < N; ++i) {
    for (size_t k = 0; k < M; ++k) {
      mat(k, i) = A(i, k);
    }
  }
  return mat;
}

template <size_t N, typename dtype = double>
pele::MatrixNM<N, N, dtype> identity() {
  pele::MatrixNM<N, N, dtype> A(0.);
  for (size_t i = 0; i < N; ++i) {
    A(i, i) = 1.;
  }
  return A;
}

// for matrix printing
template <size_t N, size_t M, typename dtype>
inline std::ostream &operator<<(std::ostream &out,
                                const MatrixNM<N, M, dtype> &a) {
  out << "[ ";
  for (size_t n = 0; n < N; ++n) {
    for (size_t m = 0; m < M; ++m) {
      if (m > 0) out << ", ";
      out << a(n, m);
    }
    if (n < N - 1) out << ",\n  ";
  }
  out << " ]";
  return out;
}

// for vector printing
template <size_t N, typename dtype>
inline std::ostream &operator<<(std::ostream &out, const VecN<N, dtype> &a) {
  out << "[ ";
  for (size_t i = 0; i < a.size(); ++i) {
    if (i > 0) out << ", ";
    out << a[i];
  }
  out << " ]";
  return out;
}

}  // namespace pele
#endif