| //===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CODEGEN_PBQP_MATH_H |
| #define LLVM_CODEGEN_PBQP_MATH_H |
| |
| #include <cassert> |
| #include <algorithm> |
| #include <functional> |
| |
| namespace PBQP { |
| |
| typedef float PBQPNum; |
| |
| /// \brief PBQP Vector class. |
| class Vector { |
| public: |
| |
| /// \brief Construct a PBQP vector of the given size. |
| explicit Vector(unsigned length) : |
| length(length), data(new PBQPNum[length]) { |
| } |
| |
| /// \brief Construct a PBQP vector with initializer. |
| Vector(unsigned length, PBQPNum initVal) : |
| length(length), data(new PBQPNum[length]) { |
| std::fill(data, data + length, initVal); |
| } |
| |
| /// \brief Copy construct a PBQP vector. |
| Vector(const Vector &v) : |
| length(v.length), data(new PBQPNum[length]) { |
| std::copy(v.data, v.data + length, data); |
| } |
| |
| /// \brief Destroy this vector, return its memory. |
| ~Vector() { delete[] data; } |
| |
| /// \brief Assignment operator. |
| Vector& operator=(const Vector &v) { |
| delete[] data; |
| length = v.length; |
| data = new PBQPNum[length]; |
| std::copy(v.data, v.data + length, data); |
| return *this; |
| } |
| |
| /// \brief Return the length of the vector |
| unsigned getLength() const { |
| return length; |
| } |
| |
| /// \brief Element access. |
| PBQPNum& operator[](unsigned index) { |
| assert(index < length && "Vector element access out of bounds."); |
| return data[index]; |
| } |
| |
| /// \brief Const element access. |
| const PBQPNum& operator[](unsigned index) const { |
| assert(index < length && "Vector element access out of bounds."); |
| return data[index]; |
| } |
| |
| /// \brief Add another vector to this one. |
| Vector& operator+=(const Vector &v) { |
| assert(length == v.length && "Vector length mismatch."); |
| std::transform(data, data + length, v.data, data, std::plus<PBQPNum>()); |
| return *this; |
| } |
| |
| /// \brief Subtract another vector from this one. |
| Vector& operator-=(const Vector &v) { |
| assert(length == v.length && "Vector length mismatch."); |
| std::transform(data, data + length, v.data, data, std::minus<PBQPNum>()); |
| return *this; |
| } |
| |
| /// \brief Returns the index of the minimum value in this vector |
| unsigned minIndex() const { |
| return std::min_element(data, data + length) - data; |
| } |
| |
| private: |
| unsigned length; |
| PBQPNum *data; |
| }; |
| |
| /// \brief Output a textual representation of the given vector on the given |
| /// output stream. |
| template <typename OStream> |
| OStream& operator<<(OStream &os, const Vector &v) { |
| assert((v.getLength() != 0) && "Zero-length vector badness."); |
| |
| os << "[ " << v[0]; |
| for (unsigned i = 1; i < v.getLength(); ++i) { |
| os << ", " << v[i]; |
| } |
| os << " ]"; |
| |
| return os; |
| } |
| |
| |
| /// \brief PBQP Matrix class |
| class Matrix { |
| public: |
| |
| /// \brief Construct a PBQP Matrix with the given dimensions. |
| Matrix(unsigned rows, unsigned cols) : |
| rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { |
| } |
| |
| /// \brief Construct a PBQP Matrix with the given dimensions and initial |
| /// value. |
| Matrix(unsigned rows, unsigned cols, PBQPNum initVal) : |
| rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { |
| std::fill(data, data + (rows * cols), initVal); |
| } |
| |
| /// \brief Copy construct a PBQP matrix. |
| Matrix(const Matrix &m) : |
| rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) { |
| std::copy(m.data, m.data + (rows * cols), data); |
| } |
| |
| /// \brief Destroy this matrix, return its memory. |
| ~Matrix() { delete[] data; } |
| |
| /// \brief Assignment operator. |
| Matrix& operator=(const Matrix &m) { |
| delete[] data; |
| rows = m.rows; cols = m.cols; |
| data = new PBQPNum[rows * cols]; |
| std::copy(m.data, m.data + (rows * cols), data); |
| return *this; |
| } |
| |
| /// \brief Return the number of rows in this matrix. |
| unsigned getRows() const { return rows; } |
| |
| /// \brief Return the number of cols in this matrix. |
| unsigned getCols() const { return cols; } |
| |
| /// \brief Matrix element access. |
| PBQPNum* operator[](unsigned r) { |
| assert(r < rows && "Row out of bounds."); |
| return data + (r * cols); |
| } |
| |
| /// \brief Matrix element access. |
| const PBQPNum* operator[](unsigned r) const { |
| assert(r < rows && "Row out of bounds."); |
| return data + (r * cols); |
| } |
| |
| /// \brief Returns the given row as a vector. |
| Vector getRowAsVector(unsigned r) const { |
| Vector v(cols); |
| for (unsigned c = 0; c < cols; ++c) |
| v[c] = (*this)[r][c]; |
| return v; |
| } |
| |
| /// \brief Returns the given column as a vector. |
| Vector getColAsVector(unsigned c) const { |
| Vector v(rows); |
| for (unsigned r = 0; r < rows; ++r) |
| v[r] = (*this)[r][c]; |
| return v; |
| } |
| |
| /// \brief Reset the matrix to the given value. |
| Matrix& reset(PBQPNum val = 0) { |
| std::fill(data, data + (rows * cols), val); |
| return *this; |
| } |
| |
| /// \brief Set a single row of this matrix to the given value. |
| Matrix& setRow(unsigned r, PBQPNum val) { |
| assert(r < rows && "Row out of bounds."); |
| std::fill(data + (r * cols), data + ((r + 1) * cols), val); |
| return *this; |
| } |
| |
| /// \brief Set a single column of this matrix to the given value. |
| Matrix& setCol(unsigned c, PBQPNum val) { |
| assert(c < cols && "Column out of bounds."); |
| for (unsigned r = 0; r < rows; ++r) |
| (*this)[r][c] = val; |
| return *this; |
| } |
| |
| /// \brief Matrix transpose. |
| Matrix transpose() const { |
| Matrix m(cols, rows); |
| for (unsigned r = 0; r < rows; ++r) |
| for (unsigned c = 0; c < cols; ++c) |
| m[c][r] = (*this)[r][c]; |
| return m; |
| } |
| |
| /// \brief Returns the diagonal of the matrix as a vector. |
| /// |
| /// Matrix must be square. |
| Vector diagonalize() const { |
| assert(rows == cols && "Attempt to diagonalize non-square matrix."); |
| |
| Vector v(rows); |
| for (unsigned r = 0; r < rows; ++r) |
| v[r] = (*this)[r][r]; |
| return v; |
| } |
| |
| /// \brief Add the given matrix to this one. |
| Matrix& operator+=(const Matrix &m) { |
| assert(rows == m.rows && cols == m.cols && |
| "Matrix dimensions mismatch."); |
| std::transform(data, data + (rows * cols), m.data, data, |
| std::plus<PBQPNum>()); |
| return *this; |
| } |
| |
| /// \brief Returns the minimum of the given row |
| PBQPNum getRowMin(unsigned r) const { |
| assert(r < rows && "Row out of bounds"); |
| return *std::min_element(data + (r * cols), data + ((r + 1) * cols)); |
| } |
| |
| /// \brief Returns the minimum of the given column |
| PBQPNum getColMin(unsigned c) const { |
| PBQPNum minElem = (*this)[0][c]; |
| for (unsigned r = 1; r < rows; ++r) |
| if ((*this)[r][c] < minElem) minElem = (*this)[r][c]; |
| return minElem; |
| } |
| |
| /// \brief Subtracts the given scalar from the elements of the given row. |
| Matrix& subFromRow(unsigned r, PBQPNum val) { |
| assert(r < rows && "Row out of bounds"); |
| std::transform(data + (r * cols), data + ((r + 1) * cols), |
| data + (r * cols), |
| std::bind2nd(std::minus<PBQPNum>(), val)); |
| return *this; |
| } |
| |
| /// \brief Subtracts the given scalar from the elements of the given column. |
| Matrix& subFromCol(unsigned c, PBQPNum val) { |
| for (unsigned r = 0; r < rows; ++r) |
| (*this)[r][c] -= val; |
| return *this; |
| } |
| |
| /// \brief Returns true if this is a zero matrix. |
| bool isZero() const { |
| return find_if(data, data + (rows * cols), |
| std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) == |
| data + (rows * cols); |
| } |
| |
| private: |
| unsigned rows, cols; |
| PBQPNum *data; |
| }; |
| |
| /// \brief Output a textual representation of the given matrix on the given |
| /// output stream. |
| template <typename OStream> |
| OStream& operator<<(OStream &os, const Matrix &m) { |
| |
| assert((m.getRows() != 0) && "Zero-row matrix badness."); |
| |
| for (unsigned i = 0; i < m.getRows(); ++i) { |
| os << m.getRowAsVector(i); |
| } |
| |
| return os; |
| } |
| |
| } |
| |
| #endif // LLVM_CODEGEN_PBQP_MATH_H |