Math.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. //===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef LLVM_CODEGEN_PBQP_MATH_H
  10. #define LLVM_CODEGEN_PBQP_MATH_H
  11. #include "llvm/ADT/Hashing.h"
  12. #include <algorithm>
  13. #include <cassert>
  14. #include <functional>
  15. namespace llvm {
  16. namespace PBQP {
  17. typedef float PBQPNum;
  18. /// \brief PBQP Vector class.
  19. class Vector {
  20. friend hash_code hash_value(const Vector &);
  21. public:
  22. /// \brief Construct a PBQP vector of the given size.
  23. explicit Vector(unsigned Length)
  24. : Length(Length), Data(new PBQPNum[Length]) {
  25. // llvm::dbgs() << "Constructing PBQP::Vector "
  26. // << this << " (length " << Length << ")\n";
  27. }
  28. /// \brief Construct a PBQP vector with initializer.
  29. Vector(unsigned Length, PBQPNum InitVal)
  30. : Length(Length), Data(new PBQPNum[Length]) {
  31. // llvm::dbgs() << "Constructing PBQP::Vector "
  32. // << this << " (length " << Length << ", fill "
  33. // << InitVal << ")\n";
  34. std::fill(Data, Data + Length, InitVal);
  35. }
  36. /// \brief Copy construct a PBQP vector.
  37. Vector(const Vector &V)
  38. : Length(V.Length), Data(new PBQPNum[Length]) {
  39. // llvm::dbgs() << "Copy-constructing PBQP::Vector " << this
  40. // << " from PBQP::Vector " << &V << "\n";
  41. std::copy(V.Data, V.Data + Length, Data);
  42. }
  43. /// \brief Move construct a PBQP vector.
  44. Vector(Vector &&V)
  45. : Length(V.Length), Data(V.Data) {
  46. V.Length = 0;
  47. V.Data = nullptr;
  48. }
  49. /// \brief Destroy this vector, return its memory.
  50. ~Vector() {
  51. // llvm::dbgs() << "Deleting PBQP::Vector " << this << "\n";
  52. delete[] Data;
  53. }
  54. /// \brief Copy-assignment operator.
  55. Vector& operator=(const Vector &V) {
  56. // llvm::dbgs() << "Assigning to PBQP::Vector " << this
  57. // << " from PBQP::Vector " << &V << "\n";
  58. delete[] Data;
  59. Length = V.Length;
  60. Data = new PBQPNum[Length];
  61. std::copy(V.Data, V.Data + Length, Data);
  62. return *this;
  63. }
  64. /// \brief Move-assignment operator.
  65. Vector& operator=(Vector &&V) {
  66. delete[] Data;
  67. Length = V.Length;
  68. Data = V.Data;
  69. V.Length = 0;
  70. V.Data = nullptr;
  71. return *this;
  72. }
  73. /// \brief Comparison operator.
  74. bool operator==(const Vector &V) const {
  75. assert(Length != 0 && Data != nullptr && "Invalid vector");
  76. if (Length != V.Length)
  77. return false;
  78. return std::equal(Data, Data + Length, V.Data);
  79. }
  80. /// \brief Return the length of the vector
  81. unsigned getLength() const {
  82. assert(Length != 0 && Data != nullptr && "Invalid vector");
  83. return Length;
  84. }
  85. /// \brief Element access.
  86. PBQPNum& operator[](unsigned Index) {
  87. assert(Length != 0 && Data != nullptr && "Invalid vector");
  88. assert(Index < Length && "Vector element access out of bounds.");
  89. return Data[Index];
  90. }
  91. /// \brief Const element access.
  92. const PBQPNum& operator[](unsigned Index) const {
  93. assert(Length != 0 && Data != nullptr && "Invalid vector");
  94. assert(Index < Length && "Vector element access out of bounds.");
  95. return Data[Index];
  96. }
  97. /// \brief Add another vector to this one.
  98. Vector& operator+=(const Vector &V) {
  99. assert(Length != 0 && Data != nullptr && "Invalid vector");
  100. assert(Length == V.Length && "Vector length mismatch.");
  101. std::transform(Data, Data + Length, V.Data, Data, std::plus<PBQPNum>());
  102. return *this;
  103. }
  104. /// \brief Subtract another vector from this one.
  105. Vector& operator-=(const Vector &V) {
  106. assert(Length != 0 && Data != nullptr && "Invalid vector");
  107. assert(Length == V.Length && "Vector length mismatch.");
  108. std::transform(Data, Data + Length, V.Data, Data, std::minus<PBQPNum>());
  109. return *this;
  110. }
  111. /// \brief Returns the index of the minimum value in this vector
  112. unsigned minIndex() const {
  113. assert(Length != 0 && Data != nullptr && "Invalid vector");
  114. return std::min_element(Data, Data + Length) - Data;
  115. }
  116. private:
  117. unsigned Length;
  118. PBQPNum *Data;
  119. };
  120. /// \brief Return a hash_value for the given vector.
  121. inline hash_code hash_value(const Vector &V) {
  122. unsigned *VBegin = reinterpret_cast<unsigned*>(V.Data);
  123. unsigned *VEnd = reinterpret_cast<unsigned*>(V.Data + V.Length);
  124. return hash_combine(V.Length, hash_combine_range(VBegin, VEnd));
  125. }
  126. /// \brief Output a textual representation of the given vector on the given
  127. /// output stream.
  128. template <typename OStream>
  129. OStream& operator<<(OStream &OS, const Vector &V) {
  130. assert((V.getLength() != 0) && "Zero-length vector badness.");
  131. OS << "[ " << V[0];
  132. for (unsigned i = 1; i < V.getLength(); ++i)
  133. OS << ", " << V[i];
  134. OS << " ]";
  135. return OS;
  136. }
  137. /// \brief PBQP Matrix class
  138. class Matrix {
  139. private:
  140. friend hash_code hash_value(const Matrix &);
  141. public:
  142. /// \brief Construct a PBQP Matrix with the given dimensions.
  143. Matrix(unsigned Rows, unsigned Cols) :
  144. Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) {
  145. }
  146. /// \brief Construct a PBQP Matrix with the given dimensions and initial
  147. /// value.
  148. Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal)
  149. : Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) {
  150. std::fill(Data, Data + (Rows * Cols), InitVal);
  151. }
  152. /// \brief Copy construct a PBQP matrix.
  153. Matrix(const Matrix &M)
  154. : Rows(M.Rows), Cols(M.Cols), Data(new PBQPNum[Rows * Cols]) {
  155. std::copy(M.Data, M.Data + (Rows * Cols), Data);
  156. }
  157. /// \brief Move construct a PBQP matrix.
  158. Matrix(Matrix &&M)
  159. : Rows(M.Rows), Cols(M.Cols), Data(M.Data) {
  160. M.Rows = M.Cols = 0;
  161. M.Data = nullptr;
  162. }
  163. /// \brief Destroy this matrix, return its memory.
  164. ~Matrix() { delete[] Data; }
  165. /// \brief Copy-assignment operator.
  166. Matrix& operator=(const Matrix &M) {
  167. delete[] Data;
  168. Rows = M.Rows; Cols = M.Cols;
  169. Data = new PBQPNum[Rows * Cols];
  170. std::copy(M.Data, M.Data + (Rows * Cols), Data);
  171. return *this;
  172. }
  173. /// \brief Move-assignment operator.
  174. Matrix& operator=(Matrix &&M) {
  175. delete[] Data;
  176. Rows = M.Rows;
  177. Cols = M.Cols;
  178. Data = M.Data;
  179. M.Rows = M.Cols = 0;
  180. M.Data = nullptr;
  181. return *this;
  182. }
  183. /// \brief Comparison operator.
  184. bool operator==(const Matrix &M) const {
  185. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  186. if (Rows != M.Rows || Cols != M.Cols)
  187. return false;
  188. return std::equal(Data, Data + (Rows * Cols), M.Data);
  189. }
  190. /// \brief Return the number of rows in this matrix.
  191. unsigned getRows() const {
  192. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  193. return Rows;
  194. }
  195. /// \brief Return the number of cols in this matrix.
  196. unsigned getCols() const {
  197. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  198. return Cols;
  199. }
  200. /// \brief Matrix element access.
  201. PBQPNum* operator[](unsigned R) {
  202. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  203. assert(R < Rows && "Row out of bounds.");
  204. return Data + (R * Cols);
  205. }
  206. /// \brief Matrix element access.
  207. const PBQPNum* operator[](unsigned R) const {
  208. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  209. assert(R < Rows && "Row out of bounds.");
  210. return Data + (R * Cols);
  211. }
  212. /// \brief Returns the given row as a vector.
  213. Vector getRowAsVector(unsigned R) const {
  214. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  215. Vector V(Cols);
  216. for (unsigned C = 0; C < Cols; ++C)
  217. V[C] = (*this)[R][C];
  218. return V;
  219. }
  220. /// \brief Returns the given column as a vector.
  221. Vector getColAsVector(unsigned C) const {
  222. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  223. Vector V(Rows);
  224. for (unsigned R = 0; R < Rows; ++R)
  225. V[R] = (*this)[R][C];
  226. return V;
  227. }
  228. /// \brief Reset the matrix to the given value.
  229. Matrix& reset(PBQPNum Val = 0) {
  230. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  231. std::fill(Data, Data + (Rows * Cols), Val);
  232. return *this;
  233. }
  234. /// \brief Set a single row of this matrix to the given value.
  235. Matrix& setRow(unsigned R, PBQPNum Val) {
  236. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  237. assert(R < Rows && "Row out of bounds.");
  238. std::fill(Data + (R * Cols), Data + ((R + 1) * Cols), Val);
  239. return *this;
  240. }
  241. /// \brief Set a single column of this matrix to the given value.
  242. Matrix& setCol(unsigned C, PBQPNum Val) {
  243. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  244. assert(C < Cols && "Column out of bounds.");
  245. for (unsigned R = 0; R < Rows; ++R)
  246. (*this)[R][C] = Val;
  247. return *this;
  248. }
  249. /// \brief Matrix transpose.
  250. Matrix transpose() const {
  251. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  252. Matrix M(Cols, Rows);
  253. for (unsigned r = 0; r < Rows; ++r)
  254. for (unsigned c = 0; c < Cols; ++c)
  255. M[c][r] = (*this)[r][c];
  256. return M;
  257. }
  258. /// \brief Returns the diagonal of the matrix as a vector.
  259. ///
  260. /// Matrix must be square.
  261. Vector diagonalize() const {
  262. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  263. assert(Rows == Cols && "Attempt to diagonalize non-square matrix.");
  264. Vector V(Rows);
  265. for (unsigned r = 0; r < Rows; ++r)
  266. V[r] = (*this)[r][r];
  267. return V;
  268. }
  269. /// \brief Add the given matrix to this one.
  270. Matrix& operator+=(const Matrix &M) {
  271. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  272. assert(Rows == M.Rows && Cols == M.Cols &&
  273. "Matrix dimensions mismatch.");
  274. std::transform(Data, Data + (Rows * Cols), M.Data, Data,
  275. std::plus<PBQPNum>());
  276. return *this;
  277. }
  278. Matrix operator+(const Matrix &M) {
  279. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  280. Matrix Tmp(*this);
  281. Tmp += M;
  282. return Tmp;
  283. }
  284. /// \brief Returns the minimum of the given row
  285. PBQPNum getRowMin(unsigned R) const {
  286. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  287. assert(R < Rows && "Row out of bounds");
  288. return *std::min_element(Data + (R * Cols), Data + ((R + 1) * Cols));
  289. }
  290. /// \brief Returns the minimum of the given column
  291. PBQPNum getColMin(unsigned C) const {
  292. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  293. PBQPNum MinElem = (*this)[0][C];
  294. for (unsigned R = 1; R < Rows; ++R)
  295. if ((*this)[R][C] < MinElem)
  296. MinElem = (*this)[R][C];
  297. return MinElem;
  298. }
  299. /// \brief Subtracts the given scalar from the elements of the given row.
  300. Matrix& subFromRow(unsigned R, PBQPNum Val) {
  301. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  302. assert(R < Rows && "Row out of bounds");
  303. std::transform(Data + (R * Cols), Data + ((R + 1) * Cols),
  304. Data + (R * Cols),
  305. std::bind2nd(std::minus<PBQPNum>(), Val));
  306. return *this;
  307. }
  308. /// \brief Subtracts the given scalar from the elements of the given column.
  309. Matrix& subFromCol(unsigned C, PBQPNum Val) {
  310. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  311. for (unsigned R = 0; R < Rows; ++R)
  312. (*this)[R][C] -= Val;
  313. return *this;
  314. }
  315. /// \brief Returns true if this is a zero matrix.
  316. bool isZero() const {
  317. assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix");
  318. return find_if(Data, Data + (Rows * Cols),
  319. std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
  320. Data + (Rows * Cols);
  321. }
  322. private:
  323. unsigned Rows, Cols;
  324. PBQPNum *Data;
  325. };
  326. /// \brief Return a hash_code for the given matrix.
  327. inline hash_code hash_value(const Matrix &M) {
  328. unsigned *MBegin = reinterpret_cast<unsigned*>(M.Data);
  329. unsigned *MEnd = reinterpret_cast<unsigned*>(M.Data + (M.Rows * M.Cols));
  330. return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd));
  331. }
  332. /// \brief Output a textual representation of the given matrix on the given
  333. /// output stream.
  334. template <typename OStream>
  335. OStream& operator<<(OStream &OS, const Matrix &M) {
  336. assert((M.getRows() != 0) && "Zero-row matrix badness.");
  337. for (unsigned i = 0; i < M.getRows(); ++i)
  338. OS << M.getRowAsVector(i) << "\n";
  339. return OS;
  340. }
  341. template <typename Metadata>
  342. class MDVector : public Vector {
  343. public:
  344. MDVector(const Vector &v) : Vector(v), md(*this) { }
  345. MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { }
  346. const Metadata& getMetadata() const { return md; }
  347. private:
  348. Metadata md;
  349. };
  350. template <typename Metadata>
  351. inline hash_code hash_value(const MDVector<Metadata> &V) {
  352. return hash_value(static_cast<const Vector&>(V));
  353. }
  354. template <typename Metadata>
  355. class MDMatrix : public Matrix {
  356. public:
  357. MDMatrix(const Matrix &m) : Matrix(m), md(*this) { }
  358. MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { }
  359. const Metadata& getMetadata() const { return md; }
  360. private:
  361. Metadata md;
  362. };
  363. template <typename Metadata>
  364. inline hash_code hash_value(const MDMatrix<Metadata> &M) {
  365. return hash_value(static_cast<const Matrix&>(M));
  366. }
  367. } // namespace PBQP
  368. } // namespace llvm
  369. #endif // LLVM_CODEGEN_PBQP_MATH_H