1408dcd3ebe187e2c098928caf9c4ce8928a30ba0Lang Hames//===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===//
225e9651afb26a004a9debda42da3f90234cc05e2Lang Hames//
325e9651afb26a004a9debda42da3f90234cc05e2Lang Hames//                     The LLVM Compiler Infrastructure
425e9651afb26a004a9debda42da3f90234cc05e2Lang Hames//
525e9651afb26a004a9debda42da3f90234cc05e2Lang Hames// This file is distributed under the University of Illinois Open Source
625e9651afb26a004a9debda42da3f90234cc05e2Lang Hames// License. See LICENSE.TXT for details.
725e9651afb26a004a9debda42da3f90234cc05e2Lang Hames//
825e9651afb26a004a9debda42da3f90234cc05e2Lang Hames//===----------------------------------------------------------------------===//
925e9651afb26a004a9debda42da3f90234cc05e2Lang Hames
10408dcd3ebe187e2c098928caf9c4ce8928a30ba0Lang Hames#ifndef LLVM_CODEGEN_PBQP_MATH_H
11408dcd3ebe187e2c098928caf9c4ce8928a30ba0Lang Hames#define LLVM_CODEGEN_PBQP_MATH_H
123ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
133ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames#include <cassert>
143ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames#include <algorithm>
153ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames#include <functional>
163ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
173ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hamesnamespace PBQP {
183ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
19408dcd3ebe187e2c098928caf9c4ce8928a30ba0Lang Hamestypedef float PBQPNum;
203ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
213ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames/// \brief PBQP Vector class.
223ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hamesclass Vector {
233ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  public:
243ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
253ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Construct a PBQP vector of the given size.
263ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    explicit Vector(unsigned length) :
273ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      length(length), data(new PBQPNum[length]) {
283ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      }
293ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
303ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Construct a PBQP vector with initializer.
313ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector(unsigned length, PBQPNum initVal) :
323ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      length(length), data(new PBQPNum[length]) {
333ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        std::fill(data, data + length, initVal);
343ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      }
353ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
363ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Copy construct a PBQP vector.
373ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector(const Vector &v) :
383ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      length(v.length), data(new PBQPNum[length]) {
393ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        std::copy(v.data, v.data + length, data);
403ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      }
413ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
423ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Destroy this vector, return its memory.
433ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    ~Vector() { delete[] data; }
443ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
453ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Assignment operator.
463ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector& operator=(const Vector &v) {
473ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      delete[] data;
483ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      length = v.length;
493ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      data = new PBQPNum[length];
503ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::copy(v.data, v.data + length, data);
513ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
523ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
533ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
543ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Return the length of the vector
55d1e9ec57081f3b62d3595d9e3a66dd0d35fc02d4Dan Gohman    unsigned getLength() const {
563ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return length;
573ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
583ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
593ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Element access.
603ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    PBQPNum& operator[](unsigned index) {
613ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(index < length && "Vector element access out of bounds.");
623ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return data[index];
633ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
643ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
653ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Const element access.
663ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    const PBQPNum& operator[](unsigned index) const {
673ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(index < length && "Vector element access out of bounds.");
683ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return data[index];
693ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
703ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
713ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Add another vector to this one.
723ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector& operator+=(const Vector &v) {
733ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(length == v.length && "Vector length mismatch.");
743ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::transform(data, data + length, v.data, data, std::plus<PBQPNum>());
753ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
763ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
773ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
783ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Subtract another vector from this one.
793ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector& operator-=(const Vector &v) {
803ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(length == v.length && "Vector length mismatch.");
813ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::transform(data, data + length, v.data, data, std::minus<PBQPNum>());
823ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
833ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
843ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
853ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Returns the index of the minimum value in this vector
863ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    unsigned minIndex() const {
873ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return std::min_element(data, data + length) - data;
883ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
893ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
903ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  private:
913ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    unsigned length;
923ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    PBQPNum *data;
933ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames};
943ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
953ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames/// \brief Output a textual representation of the given vector on the given
963ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames///        output stream.
973ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hamestemplate <typename OStream>
983ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang HamesOStream& operator<<(OStream &os, const Vector &v) {
993ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  assert((v.getLength() != 0) && "Zero-length vector badness.");
1003ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1013ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  os << "[ " << v[0];
1023ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  for (unsigned i = 1; i < v.getLength(); ++i) {
1033ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    os << ", " << v[i];
1043ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  }
1053ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  os << " ]";
1063ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1073ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  return os;
1083ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames}
1093ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1103ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1113ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames/// \brief PBQP Matrix class
1123ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hamesclass Matrix {
1133ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  public:
1143ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1153ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Construct a PBQP Matrix with the given dimensions.
1163ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix(unsigned rows, unsigned cols) :
1173ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
1183ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1193ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1203ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Construct a PBQP Matrix with the given dimensions and initial
1213ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// value.
1223ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix(unsigned rows, unsigned cols, PBQPNum initVal) :
1233ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
1243ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        std::fill(data, data + (rows * cols), initVal);
1253ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1263ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1273ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Copy construct a PBQP matrix.
1283ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix(const Matrix &m) :
1293ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) {
1303ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        std::copy(m.data, m.data + (rows * cols), data);
1313ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1323ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1333ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Destroy this matrix, return its memory.
1343ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    ~Matrix() { delete[] data; }
1353ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1363ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Assignment operator.
1373ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix& operator=(const Matrix &m) {
1383ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      delete[] data;
1393ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      rows = m.rows; cols = m.cols;
1403ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      data = new PBQPNum[rows * cols];
1413ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::copy(m.data, m.data + (rows * cols), data);
1423ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
1433ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1443ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1453ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Return the number of rows in this matrix.
146d1e9ec57081f3b62d3595d9e3a66dd0d35fc02d4Dan Gohman    unsigned getRows() const { return rows; }
1473ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1483ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Return the number of cols in this matrix.
149d1e9ec57081f3b62d3595d9e3a66dd0d35fc02d4Dan Gohman    unsigned getCols() const { return cols; }
1503ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1513ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Matrix element access.
1523ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    PBQPNum* operator[](unsigned r) {
1533ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(r < rows && "Row out of bounds.");
1543ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return data + (r * cols);
1553ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1563ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1573ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Matrix element access.
1583ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    const PBQPNum* operator[](unsigned r) const {
1593ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(r < rows && "Row out of bounds.");
1603ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return data + (r * cols);
1613ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1623ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1633ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Returns the given row as a vector.
1643ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector getRowAsVector(unsigned r) const {
1653ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      Vector v(cols);
1663ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      for (unsigned c = 0; c < cols; ++c)
1673ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        v[c] = (*this)[r][c];
1683ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return v;
1693ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1703ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1713ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Returns the given column as a vector.
1723ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector getColAsVector(unsigned c) const {
1733ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      Vector v(rows);
1743ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      for (unsigned r = 0; r < rows; ++r)
1753ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        v[r] = (*this)[r][c];
1763ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return v;
1773ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1783ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1793ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Reset the matrix to the given value.
1803ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix& reset(PBQPNum val = 0) {
1813ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::fill(data, data + (rows * cols), val);
1823ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
1833ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1843ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1853ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Set a single row of this matrix to the given value.
1863ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix& setRow(unsigned r, PBQPNum val) {
1873ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(r < rows && "Row out of bounds.");
1883ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::fill(data + (r * cols), data + ((r + 1) * cols), val);
1893ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
1903ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1913ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
1923ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Set a single column of this matrix to the given value.
1933ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix& setCol(unsigned c, PBQPNum val) {
1943ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(c < cols && "Column out of bounds.");
1953ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      for (unsigned r = 0; r < rows; ++r)
1963ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        (*this)[r][c] = val;
1973ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
1983ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
1993ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2003ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Matrix transpose.
2013ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix transpose() const {
2023ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      Matrix m(cols, rows);
2033ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      for (unsigned r = 0; r < rows; ++r)
2043ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        for (unsigned c = 0; c < cols; ++c)
2053ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames          m[c][r] = (*this)[r][c];
2063ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return m;
2073ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2083ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2093ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Returns the diagonal of the matrix as a vector.
2103ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    ///
2113ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// Matrix must be square.
2123ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Vector diagonalize() const {
2133ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(rows == cols && "Attempt to diagonalize non-square matrix.");
2143ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2153ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      Vector v(rows);
2163ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      for (unsigned r = 0; r < rows; ++r)
2173ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        v[r] = (*this)[r][r];
2183ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return v;
2193ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2203ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2213ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Add the given matrix to this one.
2223ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix& operator+=(const Matrix &m) {
2233ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(rows == m.rows && cols == m.cols &&
2243ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames          "Matrix dimensions mismatch.");
2253ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::transform(data, data + (rows * cols), m.data, data,
2263ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames          std::plus<PBQPNum>());
2273ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
2283ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2293ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2303ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Returns the minimum of the given row
2313ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    PBQPNum getRowMin(unsigned r) const {
2323ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(r < rows && "Row out of bounds");
2333ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *std::min_element(data + (r * cols), data + ((r + 1) * cols));
2343ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2353ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2363ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Returns the minimum of the given column
2373ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    PBQPNum getColMin(unsigned c) const {
2383ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      PBQPNum minElem = (*this)[0][c];
2393ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      for (unsigned r = 1; r < rows; ++r)
2403ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        if ((*this)[r][c] < minElem) minElem = (*this)[r][c];
2413ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return minElem;
2423ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2433ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2443ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Subtracts the given scalar from the elements of the given row.
2453ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix& subFromRow(unsigned r, PBQPNum val) {
2463ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      assert(r < rows && "Row out of bounds");
2473ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      std::transform(data + (r * cols), data + ((r + 1) * cols),
2483ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames          data + (r * cols),
2493ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames          std::bind2nd(std::minus<PBQPNum>(), val));
2503ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
2513ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2523ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2533ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Subtracts the given scalar from the elements of the given column.
2543ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    Matrix& subFromCol(unsigned c, PBQPNum val) {
2553ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      for (unsigned r = 0; r < rows; ++r)
2563ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        (*this)[r][c] -= val;
2573ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return *this;
2583ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2593ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2603ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    /// \brief Returns true if this is a zero matrix.
2613ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    bool isZero() const {
2623ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames      return find_if(data, data + (rows * cols),
2633ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames          std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
2643ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames        data + (rows * cols);
2653ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    }
2663ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2673ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  private:
2683ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    unsigned rows, cols;
2693ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    PBQPNum *data;
2703ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames};
2713ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2723ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames/// \brief Output a textual representation of the given matrix on the given
2733ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames///        output stream.
2743ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hamestemplate <typename OStream>
2753ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang HamesOStream& operator<<(OStream &os, const Matrix &m) {
2763ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2773ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  assert((m.getRows() != 0) && "Zero-row matrix badness.");
2783ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2793ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  for (unsigned i = 0; i < m.getRows(); ++i) {
2803ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames    os << m.getRowAsVector(i);
2813ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  }
2823ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2833ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames  return os;
2843ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames}
2853ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
2863ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames}
2873ca9a5bb440033db33cc5fa3318fa7f6f7c6a1ebLang Hames
288408dcd3ebe187e2c098928caf9c4ce8928a30ba0Lang Hames#endif // LLVM_CODEGEN_PBQP_MATH_H
289