1 //===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_CODEGEN_PBQP_MATH_H
11 #define LLVM_CODEGEN_PBQP_MATH_H
20 typedef float PBQPNum;
22 /// \brief PBQP Vector class.
24 friend class VectorComparator;
27 /// \brief Construct a PBQP vector of the given size.
28 explicit Vector(unsigned Length)
29 : Length(Length), Data(new PBQPNum[Length]) {
30 // llvm::dbgs() << "Constructing PBQP::Vector "
31 // << this << " (length " << Length << ")\n";
34 /// \brief Construct a PBQP vector with initializer.
35 Vector(unsigned Length, PBQPNum InitVal)
36 : Length(Length), Data(new PBQPNum[Length]) {
37 // llvm::dbgs() << "Constructing PBQP::Vector "
38 // << this << " (length " << Length << ", fill "
39 // << InitVal << ")\n";
40 std::fill(Data, Data + Length, InitVal);
43 /// \brief Copy construct a PBQP vector.
44 Vector(const Vector &V)
45 : Length(V.Length), Data(new PBQPNum[Length]) {
46 // llvm::dbgs() << "Copy-constructing PBQP::Vector " << this
47 // << " from PBQP::Vector " << &V << "\n";
48 std::copy(V.Data, V.Data + Length, Data);
51 /// \brief Move construct a PBQP vector.
53 : Length(V.Length), Data(V.Data) {
58 /// \brief Destroy this vector, return its memory.
60 // llvm::dbgs() << "Deleting PBQP::Vector " << this << "\n";
64 /// \brief Copy-assignment operator.
65 Vector& operator=(const Vector &V) {
66 // llvm::dbgs() << "Assigning to PBQP::Vector " << this
67 // << " from PBQP::Vector " << &V << "\n";
70 Data = new PBQPNum[Length];
71 std::copy(V.Data, V.Data + Length, Data);
75 /// \brief Move-assignment operator.
76 Vector& operator=(Vector &&V) {
85 /// \brief Comparison operator.
86 bool operator==(const Vector &V) const {
87 assert(Length != 0 && Data != nullptr && "Invalid vector");
88 if (Length != V.Length)
90 return std::equal(Data, Data + Length, V.Data);
93 /// \brief Return the length of the vector
94 unsigned getLength() const {
95 assert(Length != 0 && Data != nullptr && "Invalid vector");
99 /// \brief Element access.
100 PBQPNum& operator[](unsigned Index) {
101 assert(Length != 0 && Data != nullptr && "Invalid vector");
102 assert(Index < Length && "Vector element access out of bounds.");
106 /// \brief Const element access.
107 const PBQPNum& operator[](unsigned Index) const {
108 assert(Length != 0 && Data != nullptr && "Invalid vector");
109 assert(Index < Length && "Vector element access out of bounds.");
113 /// \brief Add another vector to this one.
114 Vector& operator+=(const Vector &V) {
115 assert(Length != 0 && Data != nullptr && "Invalid vector");
116 assert(Length == V.Length && "Vector length mismatch.");
117 std::transform(Data, Data + Length, V.Data, Data, std::plus<PBQPNum>());
121 /// \brief Subtract another vector from this one.
122 Vector& operator-=(const Vector &V) {
123 assert(Length != 0 && Data != nullptr && "Invalid vector");
124 assert(Length == V.Length && "Vector length mismatch.");
125 std::transform(Data, Data + Length, V.Data, Data, std::minus<PBQPNum>());
129 /// \brief Returns the index of the minimum value in this vector
130 unsigned minIndex() const {
131 assert(Length != 0 && Data != nullptr && "Invalid vector");
132 return std::min_element(Data, Data + Length) - Data;
140 class VectorComparator {
142 bool operator()(const Vector &A, const Vector &B) {
143 if (A.Length < B.Length)
145 if (B.Length < A.Length)
147 char *AData = reinterpret_cast<char*>(A.Data);
148 char *BData = reinterpret_cast<char*>(B.Data);
149 return std::lexicographical_compare(AData,
150 AData + A.Length * sizeof(PBQPNum),
152 BData + A.Length * sizeof(PBQPNum));
156 /// \brief Output a textual representation of the given vector on the given
158 template <typename OStream>
159 OStream& operator<<(OStream &OS, const Vector &V) {
160 assert((V.getLength() != 0) && "Zero-length vector badness.");
163 for (unsigned i = 1; i < V.getLength(); ++i)
171 /// \brief PBQP Matrix class
174 friend class MatrixComparator;
177 /// \brief Construct a PBQP Matrix with the given dimensions.
178 Matrix(unsigned Rows, unsigned Cols) :
179 Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) {
182 /// \brief Construct a PBQP Matrix with the given dimensions and initial
184 Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal)
185 : Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) {
186 std::fill(Data, Data + (Rows * Cols), InitVal);
189 /// \brief Copy construct a PBQP matrix.
190 Matrix(const Matrix &M)
191 : Rows(M.Rows), Cols(M.Cols), Data(new PBQPNum[Rows * Cols]) {
192 std::copy(M.Data, M.Data + (Rows * Cols), Data);
195 /// \brief Move construct a PBQP matrix.
197 : Rows(M.Rows), Cols(M.Cols), Data(M.Data) {
202 /// \brief Destroy this matrix, return its memory.
203 ~Matrix() { delete[] Data; }
205 /// \brief Copy-assignment operator.
206 Matrix& operator=(const Matrix &M) {
208 Rows = M.Rows; Cols = M.Cols;
209 Data = new PBQPNum[Rows * Cols];
210 std::copy(M.Data, M.Data + (Rows * Cols), Data);
214 /// \brief Move-assignment operator.
215 Matrix& operator=(Matrix &&M) {
225 /// \brief Comparison operator.
226 bool operator==(const Matrix &M) const {
227 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
228 if (Rows != M.Rows || Cols != M.Cols)
230 return std::equal(Data, Data + (Rows * Cols), M.Data);
233 /// \brief Return the number of rows in this matrix.
234 unsigned getRows() const {
235 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
239 /// \brief Return the number of cols in this matrix.
240 unsigned getCols() const {
241 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
245 /// \brief Matrix element access.
246 PBQPNum* operator[](unsigned R) {
247 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
248 assert(R < Rows && "Row out of bounds.");
249 return Data + (R * Cols);
252 /// \brief Matrix element access.
253 const PBQPNum* operator[](unsigned R) const {
254 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
255 assert(R < Rows && "Row out of bounds.");
256 return Data + (R * Cols);
259 /// \brief Returns the given row as a vector.
260 Vector getRowAsVector(unsigned R) const {
261 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
263 for (unsigned C = 0; C < Cols; ++C)
264 V[C] = (*this)[R][C];
268 /// \brief Returns the given column as a vector.
269 Vector getColAsVector(unsigned C) const {
270 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
272 for (unsigned R = 0; R < Rows; ++R)
273 V[R] = (*this)[R][C];
277 /// \brief Reset the matrix to the given value.
278 Matrix& reset(PBQPNum Val = 0) {
279 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
280 std::fill(Data, Data + (Rows * Cols), Val);
284 /// \brief Set a single row of this matrix to the given value.
285 Matrix& setRow(unsigned R, PBQPNum Val) {
286 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
287 assert(R < Rows && "Row out of bounds.");
288 std::fill(Data + (R * Cols), Data + ((R + 1) * Cols), Val);
292 /// \brief Set a single column of this matrix to the given value.
293 Matrix& setCol(unsigned C, PBQPNum Val) {
294 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
295 assert(C < Cols && "Column out of bounds.");
296 for (unsigned R = 0; R < Rows; ++R)
301 /// \brief Matrix transpose.
302 Matrix transpose() const {
303 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
304 Matrix M(Cols, Rows);
305 for (unsigned r = 0; r < Rows; ++r)
306 for (unsigned c = 0; c < Cols; ++c)
307 M[c][r] = (*this)[r][c];
311 /// \brief Returns the diagonal of the matrix as a vector.
313 /// Matrix must be square.
314 Vector diagonalize() const {
315 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
316 assert(Rows == Cols && "Attempt to diagonalize non-square matrix.");
318 for (unsigned r = 0; r < Rows; ++r)
319 V[r] = (*this)[r][r];
323 /// \brief Add the given matrix to this one.
324 Matrix& operator+=(const Matrix &M) {
325 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
326 assert(Rows == M.Rows && Cols == M.Cols &&
327 "Matrix dimensions mismatch.");
328 std::transform(Data, Data + (Rows * Cols), M.Data, Data,
329 std::plus<PBQPNum>());
333 Matrix operator+(const Matrix &M) {
334 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
340 /// \brief Returns the minimum of the given row
341 PBQPNum getRowMin(unsigned R) const {
342 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
343 assert(R < Rows && "Row out of bounds");
344 return *std::min_element(Data + (R * Cols), Data + ((R + 1) * Cols));
347 /// \brief Returns the minimum of the given column
348 PBQPNum getColMin(unsigned C) const {
349 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
350 PBQPNum MinElem = (*this)[0][C];
351 for (unsigned R = 1; R < Rows; ++R)
352 if ((*this)[R][C] < MinElem)
353 MinElem = (*this)[R][C];
357 /// \brief Subtracts the given scalar from the elements of the given row.
358 Matrix& subFromRow(unsigned R, PBQPNum Val) {
359 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
360 assert(R < Rows && "Row out of bounds");
361 std::transform(Data + (R * Cols), Data + ((R + 1) * Cols),
363 std::bind2nd(std::minus<PBQPNum>(), Val));
367 /// \brief Subtracts the given scalar from the elements of the given column.
368 Matrix& subFromCol(unsigned C, PBQPNum Val) {
369 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
370 for (unsigned R = 0; R < Rows; ++R)
371 (*this)[R][C] -= Val;
375 /// \brief Returns true if this is a zero matrix.
376 bool isZero() const {
377 assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
378 return find_if(Data, Data + (Rows * Cols),
379 std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
380 Data + (Rows * Cols);
388 class MatrixComparator {
390 bool operator()(const Matrix &A, const Matrix &B) {
399 char *AData = reinterpret_cast<char*>(A.Data);
400 char *BData = reinterpret_cast<char*>(B.Data);
401 return std::lexicographical_compare(
402 AData, AData + (A.Rows * A.Cols * sizeof(PBQPNum)),
403 BData, BData + (A.Rows * A.Cols * sizeof(PBQPNum)));
407 /// \brief Output a textual representation of the given matrix on the given
409 template <typename OStream>
410 OStream& operator<<(OStream &OS, const Matrix &M) {
411 assert((M.getRows() != 0) && "Zero-row matrix badness.");
412 for (unsigned i = 0; i < M.getRows(); ++i)
413 OS << M.getRowAsVector(i);
417 template <typename Metadata>
418 class MDVector : public Vector {
420 MDVector(const Vector &v) : Vector(v), md(*this) { }
421 MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { }
422 const Metadata& getMetadata() const { return md; }
427 template <typename Metadata>
428 class MDMatrix : public Matrix {
430 MDMatrix(const Matrix &m) : Matrix(m), md(*this) { }
431 MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { }
432 const Metadata& getMetadata() const { return md; }
440 #endif // LLVM_CODEGEN_PBQP_MATH_H