| //===------ 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 |