//===- Math.h - PBQP Vector and Matrix classes ------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_PBQP_MATH_H #define LLVM_CODEGEN_PBQP_MATH_H #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" #include #include #include #include namespace llvm { namespace PBQP { using PBQPNum = float; /// PBQP Vector class. class Vector { friend hash_code hash_value(const Vector &); public: /// Construct a PBQP vector of the given size. explicit Vector(unsigned Length) : Length(Length), Data(std::make_unique(Length)) {} /// Construct a PBQP vector with initializer. Vector(unsigned Length, PBQPNum InitVal) : Length(Length), Data(std::make_unique(Length)) { std::fill(Data.get(), Data.get() + Length, InitVal); } /// Copy construct a PBQP vector. Vector(const Vector &V) : Length(V.Length), Data(std::make_unique(Length)) { std::copy(V.Data.get(), V.Data.get() + Length, Data.get()); } /// Move construct a PBQP vector. Vector(Vector &&V) : Length(V.Length), Data(std::move(V.Data)) { V.Length = 0; } /// Comparison operator. bool operator==(const Vector &V) const { assert(Length != 0 && Data && "Invalid vector"); if (Length != V.Length) return false; return std::equal(Data.get(), Data.get() + Length, V.Data.get()); } /// Return the length of the vector unsigned getLength() const { assert(Length != 0 && Data && "Invalid vector"); return Length; } /// Element access. PBQPNum& operator[](unsigned Index) { assert(Length != 0 && Data && "Invalid vector"); assert(Index < Length && "Vector element access out of bounds."); return Data[Index]; } /// Const element access. const PBQPNum& operator[](unsigned Index) const { assert(Length != 0 && Data && "Invalid vector"); assert(Index < Length && "Vector element access out of bounds."); return Data[Index]; } /// Add another vector to this one. Vector& operator+=(const Vector &V) { assert(Length != 0 && Data && "Invalid vector"); assert(Length == V.Length && "Vector length mismatch."); std::transform(Data.get(), Data.get() + Length, V.Data.get(), Data.get(), std::plus()); return *this; } /// Returns the index of the minimum value in this vector unsigned minIndex() const { assert(Length != 0 && Data && "Invalid vector"); return std::min_element(Data.get(), Data.get() + Length) - Data.get(); } private: unsigned Length; std::unique_ptr Data; }; /// Return a hash_value for the given vector. inline hash_code hash_value(const Vector &V) { unsigned *VBegin = reinterpret_cast(V.Data.get()); unsigned *VEnd = reinterpret_cast(V.Data.get() + V.Length); return hash_combine(V.Length, hash_combine_range(VBegin, VEnd)); } /// Output a textual representation of the given vector on the given /// output stream. template 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; } /// PBQP Matrix class class Matrix { private: friend hash_code hash_value(const Matrix &); public: /// Construct a PBQP Matrix with the given dimensions. Matrix(unsigned Rows, unsigned Cols) : Rows(Rows), Cols(Cols), Data(std::make_unique(Rows * Cols)) { } /// Construct a PBQP Matrix with the given dimensions and initial /// value. Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal) : Rows(Rows), Cols(Cols), Data(std::make_unique(Rows * Cols)) { std::fill(Data.get(), Data.get() + (Rows * Cols), InitVal); } /// Copy construct a PBQP matrix. Matrix(const Matrix &M) : Rows(M.Rows), Cols(M.Cols), Data(std::make_unique(Rows * Cols)) { std::copy(M.Data.get(), M.Data.get() + (Rows * Cols), Data.get()); } /// Move construct a PBQP matrix. Matrix(Matrix &&M) : Rows(M.Rows), Cols(M.Cols), Data(std::move(M.Data)) { M.Rows = M.Cols = 0; } /// Comparison operator. bool operator==(const Matrix &M) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); if (Rows != M.Rows || Cols != M.Cols) return false; return std::equal(Data.get(), Data.get() + (Rows * Cols), M.Data.get()); } /// Return the number of rows in this matrix. unsigned getRows() const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); return Rows; } /// Return the number of cols in this matrix. unsigned getCols() const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); return Cols; } /// Matrix element access. PBQPNum* operator[](unsigned R) { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); assert(R < Rows && "Row out of bounds."); return Data.get() + (R * Cols); } /// Matrix element access. const PBQPNum* operator[](unsigned R) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); assert(R < Rows && "Row out of bounds."); return Data.get() + (R * Cols); } /// Returns the given row as a vector. Vector getRowAsVector(unsigned R) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); Vector V(Cols); for (unsigned C = 0; C < Cols; ++C) V[C] = (*this)[R][C]; return V; } /// Returns the given column as a vector. Vector getColAsVector(unsigned C) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); Vector V(Rows); for (unsigned R = 0; R < Rows; ++R) V[R] = (*this)[R][C]; return V; } /// Matrix transpose. Matrix transpose() const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); 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; } /// Add the given matrix to this one. Matrix& operator+=(const Matrix &M) { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); assert(Rows == M.Rows && Cols == M.Cols && "Matrix dimensions mismatch."); std::transform(Data.get(), Data.get() + (Rows * Cols), M.Data.get(), Data.get(), std::plus()); return *this; } Matrix operator+(const Matrix &M) { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); Matrix Tmp(*this); Tmp += M; return Tmp; } private: unsigned Rows, Cols; std::unique_ptr Data; }; /// Return a hash_code for the given matrix. inline hash_code hash_value(const Matrix &M) { unsigned *MBegin = reinterpret_cast(M.Data.get()); unsigned *MEnd = reinterpret_cast(M.Data.get() + (M.Rows * M.Cols)); return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd)); } /// Output a textual representation of the given matrix on the given /// output stream. template 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) << "\n"; return OS; } template class MDVector : public Vector { public: MDVector(const Vector &v) : Vector(v), md(*this) {} MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { } const Metadata& getMetadata() const { return md; } private: Metadata md; }; template inline hash_code hash_value(const MDVector &V) { return hash_value(static_cast(V)); } template class MDMatrix : public Matrix { public: MDMatrix(const Matrix &m) : Matrix(m), md(*this) {} MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { } const Metadata& getMetadata() const { return md; } private: Metadata md; }; template inline hash_code hash_value(const MDMatrix &M) { return hash_value(static_cast(M)); } } // end namespace PBQP } // end namespace llvm #endif // LLVM_CODEGEN_PBQP_MATH_H