LLVM API Documentation

Math.h
Go to the documentation of this file.
00001 //===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #ifndef LLVM_CODEGEN_PBQP_MATH_H
00011 #define LLVM_CODEGEN_PBQP_MATH_H
00012 
00013 #include <algorithm>
00014 #include <cassert>
00015 #include <functional>
00016 
00017 namespace PBQP {
00018 
00019 typedef float PBQPNum;
00020 
00021 /// \brief PBQP Vector class.
00022 class Vector {
00023   friend class VectorComparator;
00024 public:
00025 
00026   /// \brief Construct a PBQP vector of the given size.
00027   explicit Vector(unsigned Length)
00028     : Length(Length), Data(new PBQPNum[Length]) {
00029     // llvm::dbgs() << "Constructing PBQP::Vector "
00030     //              << this << " (length " << Length << ")\n";
00031   }
00032 
00033   /// \brief Construct a PBQP vector with initializer.
00034   Vector(unsigned Length, PBQPNum InitVal)
00035     : Length(Length), Data(new PBQPNum[Length]) {
00036     // llvm::dbgs() << "Constructing PBQP::Vector "
00037     //              << this << " (length " << Length << ", fill "
00038     //              << InitVal << ")\n";
00039     std::fill(Data, Data + Length, InitVal);
00040   }
00041 
00042   /// \brief Copy construct a PBQP vector.
00043   Vector(const Vector &V)
00044     : Length(V.Length), Data(new PBQPNum[Length]) {
00045     // llvm::dbgs() << "Copy-constructing PBQP::Vector " << this
00046     //              << " from PBQP::Vector " << &V << "\n";
00047     std::copy(V.Data, V.Data + Length, Data);
00048   }
00049 
00050   /// \brief Move construct a PBQP vector.
00051   Vector(Vector &&V)
00052     : Length(V.Length), Data(V.Data) {
00053     V.Length = 0;
00054     V.Data = nullptr;
00055   }
00056 
00057   /// \brief Destroy this vector, return its memory.
00058   ~Vector() {
00059     // llvm::dbgs() << "Deleting PBQP::Vector " << this << "\n";
00060     delete[] Data;
00061   }
00062 
00063   /// \brief Copy-assignment operator.
00064   Vector& operator=(const Vector &V) {
00065     // llvm::dbgs() << "Assigning to PBQP::Vector " << this
00066     //              << " from PBQP::Vector " << &V << "\n";
00067     delete[] Data;
00068     Length = V.Length;
00069     Data = new PBQPNum[Length];
00070     std::copy(V.Data, V.Data + Length, Data);
00071     return *this;
00072   }
00073 
00074   /// \brief Move-assignment operator.
00075   Vector& operator=(Vector &&V) {
00076     delete[] Data;
00077     Length = V.Length;
00078     Data = V.Data;
00079     V.Length = 0;
00080     V.Data = nullptr;
00081     return *this;
00082   }
00083 
00084   /// \brief Comparison operator.
00085   bool operator==(const Vector &V) const {
00086     assert(Length != 0 && Data != nullptr && "Invalid vector");
00087     if (Length != V.Length)
00088       return false;
00089     return std::equal(Data, Data + Length, V.Data);
00090   }
00091 
00092   /// \brief Return the length of the vector
00093   unsigned getLength() const {
00094     assert(Length != 0 && Data != nullptr && "Invalid vector");
00095     return Length;
00096   }
00097 
00098   /// \brief Element access.
00099   PBQPNum& operator[](unsigned Index) {
00100     assert(Length != 0 && Data != nullptr && "Invalid vector");
00101     assert(Index < Length && "Vector element access out of bounds.");
00102     return Data[Index];
00103   }
00104 
00105   /// \brief Const element access.
00106   const PBQPNum& operator[](unsigned Index) const {
00107     assert(Length != 0 && Data != nullptr && "Invalid vector");
00108     assert(Index < Length && "Vector element access out of bounds.");
00109     return Data[Index];
00110   }
00111 
00112   /// \brief Add another vector to this one.
00113   Vector& operator+=(const Vector &V) {
00114     assert(Length != 0 && Data != nullptr && "Invalid vector");
00115     assert(Length == V.Length && "Vector length mismatch.");
00116     std::transform(Data, Data + Length, V.Data, Data, std::plus<PBQPNum>());
00117     return *this;
00118   }
00119 
00120   /// \brief Subtract another vector from this one.
00121   Vector& operator-=(const Vector &V) {
00122     assert(Length != 0 && Data != nullptr && "Invalid vector");
00123     assert(Length == V.Length && "Vector length mismatch.");
00124     std::transform(Data, Data + Length, V.Data, Data, std::minus<PBQPNum>());
00125     return *this;
00126   }
00127 
00128   /// \brief Returns the index of the minimum value in this vector
00129   unsigned minIndex() const {
00130     assert(Length != 0 && Data != nullptr && "Invalid vector");
00131     return std::min_element(Data, Data + Length) - Data;
00132   }
00133 
00134 private:
00135   unsigned Length;
00136   PBQPNum *Data;
00137 };
00138 
00139 class VectorComparator {
00140 public:
00141   bool operator()(const Vector &A, const Vector &B) {
00142     if (A.Length < B.Length)
00143       return true;
00144     if (B.Length < A.Length)
00145       return false;
00146     char *AData = reinterpret_cast<char*>(A.Data);
00147     char *BData = reinterpret_cast<char*>(B.Data);
00148     return std::lexicographical_compare(AData,
00149                                         AData + A.Length * sizeof(PBQPNum),
00150                                         BData,
00151                                         BData + A.Length * sizeof(PBQPNum));
00152   }
00153 };
00154 
00155 /// \brief Output a textual representation of the given vector on the given
00156 ///        output stream.
00157 template <typename OStream>
00158 OStream& operator<<(OStream &OS, const Vector &V) {
00159   assert((V.getLength() != 0) && "Zero-length vector badness.");
00160 
00161   OS << "[ " << V[0];
00162   for (unsigned i = 1; i < V.getLength(); ++i)
00163     OS << ", " << V[i];
00164   OS << " ]";
00165 
00166   return OS;
00167 }
00168 
00169 
00170 /// \brief PBQP Matrix class
00171 class Matrix {
00172 private:
00173   friend class MatrixComparator;
00174 public:
00175 
00176   /// \brief Construct a PBQP Matrix with the given dimensions.
00177   Matrix(unsigned Rows, unsigned Cols) :
00178     Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) {
00179   }
00180 
00181   /// \brief Construct a PBQP Matrix with the given dimensions and initial
00182   /// value.
00183   Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal)
00184     : Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) {
00185     std::fill(Data, Data + (Rows * Cols), InitVal);
00186   }
00187 
00188   /// \brief Copy construct a PBQP matrix.
00189   Matrix(const Matrix &M)
00190     : Rows(M.Rows), Cols(M.Cols), Data(new PBQPNum[Rows * Cols]) {
00191     std::copy(M.Data, M.Data + (Rows * Cols), Data);
00192   }
00193 
00194   /// \brief Move construct a PBQP matrix.
00195   Matrix(Matrix &&M)
00196     : Rows(M.Rows), Cols(M.Cols), Data(M.Data) {
00197     M.Rows = M.Cols = 0;
00198     M.Data = nullptr;
00199   }
00200 
00201   /// \brief Destroy this matrix, return its memory.
00202   ~Matrix() { delete[] Data; }
00203 
00204   /// \brief Copy-assignment operator.
00205   Matrix& operator=(const Matrix &M) {
00206     delete[] Data;
00207     Rows = M.Rows; Cols = M.Cols;
00208     Data = new PBQPNum[Rows * Cols];
00209     std::copy(M.Data, M.Data + (Rows * Cols), Data);
00210     return *this;
00211   }
00212 
00213   /// \brief Move-assignment operator.
00214   Matrix& operator=(Matrix &&M) {
00215     delete[] Data;
00216     Rows = M.Rows;
00217     Cols = M.Cols;
00218     Data = M.Data;
00219     M.Rows = M.Cols = 0;
00220     M.Data = nullptr;
00221     return *this;
00222   }
00223 
00224   /// \brief Comparison operator.
00225   bool operator==(const Matrix &M) const {
00226     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00227     if (Rows != M.Rows || Cols != M.Cols)
00228       return false;
00229     return std::equal(Data, Data + (Rows * Cols), M.Data);
00230   }
00231 
00232   /// \brief Return the number of rows in this matrix.
00233   unsigned getRows() const {
00234     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00235     return Rows;
00236   }
00237 
00238   /// \brief Return the number of cols in this matrix.
00239   unsigned getCols() const {
00240     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00241     return Cols;
00242   }
00243 
00244   /// \brief Matrix element access.
00245   PBQPNum* operator[](unsigned R) {
00246     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00247     assert(R < Rows && "Row out of bounds.");
00248     return Data + (R * Cols);
00249   }
00250 
00251   /// \brief Matrix element access.
00252   const PBQPNum* operator[](unsigned R) const {
00253     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00254     assert(R < Rows && "Row out of bounds.");
00255     return Data + (R * Cols);
00256   }
00257 
00258   /// \brief Returns the given row as a vector.
00259   Vector getRowAsVector(unsigned R) const {
00260     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00261     Vector V(Cols);
00262     for (unsigned C = 0; C < Cols; ++C)
00263       V[C] = (*this)[R][C];
00264     return V;
00265   }
00266 
00267   /// \brief Returns the given column as a vector.
00268   Vector getColAsVector(unsigned C) const {
00269     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00270     Vector V(Rows);
00271     for (unsigned R = 0; R < Rows; ++R)
00272       V[R] = (*this)[R][C];
00273     return V;
00274   }
00275 
00276   /// \brief Reset the matrix to the given value.
00277   Matrix& reset(PBQPNum Val = 0) {
00278     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00279     std::fill(Data, Data + (Rows * Cols), Val);
00280     return *this;
00281   }
00282 
00283   /// \brief Set a single row of this matrix to the given value.
00284   Matrix& setRow(unsigned R, PBQPNum Val) {
00285     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00286     assert(R < Rows && "Row out of bounds.");
00287     std::fill(Data + (R * Cols), Data + ((R + 1) * Cols), Val);
00288     return *this;
00289   }
00290 
00291   /// \brief Set a single column of this matrix to the given value.
00292   Matrix& setCol(unsigned C, PBQPNum Val) {
00293     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00294     assert(C < Cols && "Column out of bounds.");
00295     for (unsigned R = 0; R < Rows; ++R)
00296       (*this)[R][C] = Val;
00297     return *this;
00298   }
00299 
00300   /// \brief Matrix transpose.
00301   Matrix transpose() const {
00302     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00303     Matrix M(Cols, Rows);
00304     for (unsigned r = 0; r < Rows; ++r)
00305       for (unsigned c = 0; c < Cols; ++c)
00306         M[c][r] = (*this)[r][c];
00307     return M;
00308   }
00309 
00310   /// \brief Returns the diagonal of the matrix as a vector.
00311   ///
00312   /// Matrix must be square.
00313   Vector diagonalize() const {
00314     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00315     assert(Rows == Cols && "Attempt to diagonalize non-square matrix.");
00316     Vector V(Rows);
00317     for (unsigned r = 0; r < Rows; ++r)
00318       V[r] = (*this)[r][r];
00319     return V;
00320   }
00321 
00322   /// \brief Add the given matrix to this one.
00323   Matrix& operator+=(const Matrix &M) {
00324     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00325     assert(Rows == M.Rows && Cols == M.Cols &&
00326            "Matrix dimensions mismatch.");
00327     std::transform(Data, Data + (Rows * Cols), M.Data, Data,
00328                    std::plus<PBQPNum>());
00329     return *this;
00330   }
00331 
00332   Matrix operator+(const Matrix &M) {
00333     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00334     Matrix Tmp(*this);
00335     Tmp += M;
00336     return Tmp;
00337   }
00338 
00339   /// \brief Returns the minimum of the given row
00340   PBQPNum getRowMin(unsigned R) const {
00341     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00342     assert(R < Rows && "Row out of bounds");
00343     return *std::min_element(Data + (R * Cols), Data + ((R + 1) * Cols));
00344   }
00345 
00346   /// \brief Returns the minimum of the given column
00347   PBQPNum getColMin(unsigned C) const {
00348     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00349     PBQPNum MinElem = (*this)[0][C];
00350     for (unsigned R = 1; R < Rows; ++R)
00351       if ((*this)[R][C] < MinElem)
00352         MinElem = (*this)[R][C];
00353     return MinElem;
00354   }
00355 
00356   /// \brief Subtracts the given scalar from the elements of the given row.
00357   Matrix& subFromRow(unsigned R, PBQPNum Val) {
00358     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00359     assert(R < Rows && "Row out of bounds");
00360     std::transform(Data + (R * Cols), Data + ((R + 1) * Cols),
00361                    Data + (R * Cols),
00362                    std::bind2nd(std::minus<PBQPNum>(), Val));
00363     return *this;
00364   }
00365 
00366   /// \brief Subtracts the given scalar from the elements of the given column.
00367   Matrix& subFromCol(unsigned C, PBQPNum Val) {
00368     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00369     for (unsigned R = 0; R < Rows; ++R)
00370       (*this)[R][C] -= Val;
00371     return *this;
00372   }
00373 
00374   /// \brief Returns true if this is a zero matrix.
00375   bool isZero() const {
00376     assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
00377     return find_if(Data, Data + (Rows * Cols),
00378                    std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
00379       Data + (Rows * Cols);
00380   }
00381 
00382 private:
00383   unsigned Rows, Cols;
00384   PBQPNum *Data;
00385 };
00386 
00387 class MatrixComparator {
00388 public:
00389   bool operator()(const Matrix &A, const Matrix &B) {
00390     if (A.Rows < B.Rows)
00391       return true;
00392     if (B.Rows < A.Rows)
00393       return false;
00394     if (A.Cols < B.Cols)
00395       return true;
00396     if (B.Cols < A.Cols)
00397       return false;
00398     char *AData = reinterpret_cast<char*>(A.Data);
00399     char *BData = reinterpret_cast<char*>(B.Data);
00400     return std::lexicographical_compare(
00401              AData, AData + (A.Rows * A.Cols * sizeof(PBQPNum)),
00402              BData, BData + (A.Rows * A.Cols * sizeof(PBQPNum)));
00403   }
00404 };
00405 
00406 /// \brief Output a textual representation of the given matrix on the given
00407 ///        output stream.
00408 template <typename OStream>
00409 OStream& operator<<(OStream &OS, const Matrix &M) {
00410   assert((M.getRows() != 0) && "Zero-row matrix badness.");
00411   for (unsigned i = 0; i < M.getRows(); ++i)
00412     OS << M.getRowAsVector(i);
00413   return OS;
00414 }
00415 
00416 template <typename Metadata>
00417 class MDVector : public Vector {
00418 public:
00419   MDVector(const Vector &v) : Vector(v), md(*this) { }
00420   MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { }
00421   const Metadata& getMetadata() const { return md; }
00422 private:
00423   Metadata md;
00424 };
00425 
00426 template <typename Metadata>
00427 class MDMatrix : public Matrix {
00428 public:
00429   MDMatrix(const Matrix &m) : Matrix(m), md(*this) { }
00430   MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { }
00431   const Metadata& getMetadata() const { return md; }
00432 private:
00433   Metadata md;
00434 };
00435 
00436 }
00437 
00438 #endif // LLVM_CODEGEN_PBQP_MATH_H