blob: 099ba788e9a2d8c2bbfbecc2d4049b56288fd515 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- Math.h - PBQP Vector and Matrix classes ------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CODEGEN_PBQP_MATH_H
10#define LLVM_CODEGEN_PBQP_MATH_H
11
12#include "llvm/ADT/Hashing.h"
13#include "llvm/ADT/STLExtras.h"
14#include <algorithm>
15#include <cassert>
16#include <functional>
17#include <memory>
18
19namespace llvm {
20namespace PBQP {
21
22using PBQPNum = float;
23
Andrew Scullcdfcccc2018-10-05 20:58:37 +010024/// PBQP Vector class.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010025class Vector {
26 friend hash_code hash_value(const Vector &);
27
28public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010029 /// Construct a PBQP vector of the given size.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010030 explicit Vector(unsigned Length)
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020031 : Length(Length), Data(std::make_unique<PBQPNum []>(Length)) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010032
Andrew Scullcdfcccc2018-10-05 20:58:37 +010033 /// Construct a PBQP vector with initializer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010034 Vector(unsigned Length, PBQPNum InitVal)
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020035 : Length(Length), Data(std::make_unique<PBQPNum []>(Length)) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010036 std::fill(Data.get(), Data.get() + Length, InitVal);
37 }
38
Andrew Scullcdfcccc2018-10-05 20:58:37 +010039 /// Copy construct a PBQP vector.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010040 Vector(const Vector &V)
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020041 : Length(V.Length), Data(std::make_unique<PBQPNum []>(Length)) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010042 std::copy(V.Data.get(), V.Data.get() + Length, Data.get());
43 }
44
Andrew Scullcdfcccc2018-10-05 20:58:37 +010045 /// Move construct a PBQP vector.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010046 Vector(Vector &&V)
47 : Length(V.Length), Data(std::move(V.Data)) {
48 V.Length = 0;
49 }
50
Andrew Scullcdfcccc2018-10-05 20:58:37 +010051 /// Comparison operator.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010052 bool operator==(const Vector &V) const {
53 assert(Length != 0 && Data && "Invalid vector");
54 if (Length != V.Length)
55 return false;
56 return std::equal(Data.get(), Data.get() + Length, V.Data.get());
57 }
58
Andrew Scullcdfcccc2018-10-05 20:58:37 +010059 /// Return the length of the vector
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010060 unsigned getLength() const {
61 assert(Length != 0 && Data && "Invalid vector");
62 return Length;
63 }
64
Andrew Scullcdfcccc2018-10-05 20:58:37 +010065 /// Element access.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010066 PBQPNum& operator[](unsigned Index) {
67 assert(Length != 0 && Data && "Invalid vector");
68 assert(Index < Length && "Vector element access out of bounds.");
69 return Data[Index];
70 }
71
Andrew Scullcdfcccc2018-10-05 20:58:37 +010072 /// Const element access.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010073 const PBQPNum& operator[](unsigned Index) const {
74 assert(Length != 0 && Data && "Invalid vector");
75 assert(Index < Length && "Vector element access out of bounds.");
76 return Data[Index];
77 }
78
Andrew Scullcdfcccc2018-10-05 20:58:37 +010079 /// Add another vector to this one.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010080 Vector& operator+=(const Vector &V) {
81 assert(Length != 0 && Data && "Invalid vector");
82 assert(Length == V.Length && "Vector length mismatch.");
83 std::transform(Data.get(), Data.get() + Length, V.Data.get(), Data.get(),
84 std::plus<PBQPNum>());
85 return *this;
86 }
87
Andrew Scullcdfcccc2018-10-05 20:58:37 +010088 /// Returns the index of the minimum value in this vector
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010089 unsigned minIndex() const {
90 assert(Length != 0 && Data && "Invalid vector");
91 return std::min_element(Data.get(), Data.get() + Length) - Data.get();
92 }
93
94private:
95 unsigned Length;
96 std::unique_ptr<PBQPNum []> Data;
97};
98
Andrew Scullcdfcccc2018-10-05 20:58:37 +010099/// Return a hash_value for the given vector.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100100inline hash_code hash_value(const Vector &V) {
101 unsigned *VBegin = reinterpret_cast<unsigned*>(V.Data.get());
102 unsigned *VEnd = reinterpret_cast<unsigned*>(V.Data.get() + V.Length);
103 return hash_combine(V.Length, hash_combine_range(VBegin, VEnd));
104}
105
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100106/// Output a textual representation of the given vector on the given
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100107/// output stream.
108template <typename OStream>
109OStream& operator<<(OStream &OS, const Vector &V) {
110 assert((V.getLength() != 0) && "Zero-length vector badness.");
111
112 OS << "[ " << V[0];
113 for (unsigned i = 1; i < V.getLength(); ++i)
114 OS << ", " << V[i];
115 OS << " ]";
116
117 return OS;
118}
119
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100120/// PBQP Matrix class
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100121class Matrix {
122private:
123 friend hash_code hash_value(const Matrix &);
124
125public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100126 /// Construct a PBQP Matrix with the given dimensions.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100127 Matrix(unsigned Rows, unsigned Cols) :
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200128 Rows(Rows), Cols(Cols), Data(std::make_unique<PBQPNum []>(Rows * Cols)) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100129 }
130
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100131 /// Construct a PBQP Matrix with the given dimensions and initial
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100132 /// value.
133 Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal)
134 : Rows(Rows), Cols(Cols),
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200135 Data(std::make_unique<PBQPNum []>(Rows * Cols)) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100136 std::fill(Data.get(), Data.get() + (Rows * Cols), InitVal);
137 }
138
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100139 /// Copy construct a PBQP matrix.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100140 Matrix(const Matrix &M)
141 : Rows(M.Rows), Cols(M.Cols),
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200142 Data(std::make_unique<PBQPNum []>(Rows * Cols)) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100143 std::copy(M.Data.get(), M.Data.get() + (Rows * Cols), Data.get());
144 }
145
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100146 /// Move construct a PBQP matrix.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100147 Matrix(Matrix &&M)
148 : Rows(M.Rows), Cols(M.Cols), Data(std::move(M.Data)) {
149 M.Rows = M.Cols = 0;
150 }
151
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100152 /// Comparison operator.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100153 bool operator==(const Matrix &M) const {
154 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
155 if (Rows != M.Rows || Cols != M.Cols)
156 return false;
157 return std::equal(Data.get(), Data.get() + (Rows * Cols), M.Data.get());
158 }
159
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100160 /// Return the number of rows in this matrix.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100161 unsigned getRows() const {
162 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
163 return Rows;
164 }
165
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100166 /// Return the number of cols in this matrix.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100167 unsigned getCols() const {
168 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
169 return Cols;
170 }
171
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100172 /// Matrix element access.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100173 PBQPNum* operator[](unsigned R) {
174 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
175 assert(R < Rows && "Row out of bounds.");
176 return Data.get() + (R * Cols);
177 }
178
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100179 /// Matrix element access.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100180 const PBQPNum* operator[](unsigned R) const {
181 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
182 assert(R < Rows && "Row out of bounds.");
183 return Data.get() + (R * Cols);
184 }
185
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100186 /// Returns the given row as a vector.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100187 Vector getRowAsVector(unsigned R) const {
188 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
189 Vector V(Cols);
190 for (unsigned C = 0; C < Cols; ++C)
191 V[C] = (*this)[R][C];
192 return V;
193 }
194
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100195 /// Returns the given column as a vector.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100196 Vector getColAsVector(unsigned C) const {
197 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
198 Vector V(Rows);
199 for (unsigned R = 0; R < Rows; ++R)
200 V[R] = (*this)[R][C];
201 return V;
202 }
203
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100204 /// Matrix transpose.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100205 Matrix transpose() const {
206 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
207 Matrix M(Cols, Rows);
208 for (unsigned r = 0; r < Rows; ++r)
209 for (unsigned c = 0; c < Cols; ++c)
210 M[c][r] = (*this)[r][c];
211 return M;
212 }
213
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100214 /// Add the given matrix to this one.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100215 Matrix& operator+=(const Matrix &M) {
216 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
217 assert(Rows == M.Rows && Cols == M.Cols &&
218 "Matrix dimensions mismatch.");
219 std::transform(Data.get(), Data.get() + (Rows * Cols), M.Data.get(),
220 Data.get(), std::plus<PBQPNum>());
221 return *this;
222 }
223
224 Matrix operator+(const Matrix &M) {
225 assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix");
226 Matrix Tmp(*this);
227 Tmp += M;
228 return Tmp;
229 }
230
231private:
232 unsigned Rows, Cols;
233 std::unique_ptr<PBQPNum []> Data;
234};
235
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100236/// Return a hash_code for the given matrix.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100237inline hash_code hash_value(const Matrix &M) {
238 unsigned *MBegin = reinterpret_cast<unsigned*>(M.Data.get());
239 unsigned *MEnd =
240 reinterpret_cast<unsigned*>(M.Data.get() + (M.Rows * M.Cols));
241 return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd));
242}
243
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100244/// Output a textual representation of the given matrix on the given
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100245/// output stream.
246template <typename OStream>
247OStream& operator<<(OStream &OS, const Matrix &M) {
248 assert((M.getRows() != 0) && "Zero-row matrix badness.");
249 for (unsigned i = 0; i < M.getRows(); ++i)
250 OS << M.getRowAsVector(i) << "\n";
251 return OS;
252}
253
254template <typename Metadata>
255class MDVector : public Vector {
256public:
257 MDVector(const Vector &v) : Vector(v), md(*this) {}
258 MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { }
259
260 const Metadata& getMetadata() const { return md; }
261
262private:
263 Metadata md;
264};
265
266template <typename Metadata>
267inline hash_code hash_value(const MDVector<Metadata> &V) {
268 return hash_value(static_cast<const Vector&>(V));
269}
270
271template <typename Metadata>
272class MDMatrix : public Matrix {
273public:
274 MDMatrix(const Matrix &m) : Matrix(m), md(*this) {}
275 MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { }
276
277 const Metadata& getMetadata() const { return md; }
278
279private:
280 Metadata md;
281};
282
283template <typename Metadata>
284inline hash_code hash_value(const MDMatrix<Metadata> &M) {
285 return hash_value(static_cast<const Matrix&>(M));
286}
287
288} // end namespace PBQP
289} // end namespace llvm
290
291#endif // LLVM_CODEGEN_PBQP_MATH_H