The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. /**
  20. General matrix and vectors class, meant for classic math manipulation such as
  21. additions, multiplications, and linear systems of equations solving.
  22. @see LinearAlgebra
  23. */
  24. template<typename ElementType>
  25. class Matrix
  26. {
  27. public:
  28. //==============================================================================
  29. /** Creates a new matrix with a given number of rows and columns. */
  30. Matrix (size_t numRows, size_t numColumns)
  31. : rows (numRows), columns (numColumns)
  32. {
  33. resize();
  34. clear();
  35. }
  36. /** Creates a new matrix with a given number of rows and columns, with initial
  37. data coming from an array, stored in row-major order.
  38. */
  39. Matrix (size_t numRows, size_t numColumns, const ElementType* dataPointer)
  40. : rows (numRows), columns (numColumns)
  41. {
  42. resize();
  43. memcpy (data.getRawDataPointer(), dataPointer, rows * columns * sizeof (ElementType));
  44. }
  45. /** Creates a copy of another matrix. */
  46. Matrix (const Matrix&) = default;
  47. /** Moves a copy of another matrix. */
  48. Matrix (Matrix&&) noexcept = default;
  49. /** Creates a copy of another matrix. */
  50. Matrix& operator= (const Matrix&) = default;
  51. /** Moves another matrix into this one */
  52. Matrix& operator= (Matrix&&) noexcept = default;
  53. //==============================================================================
  54. /** Creates the identity matrix */
  55. static Matrix identity (size_t size);
  56. /** Creates a Toeplitz Matrix from a vector with a given squared size */
  57. static Matrix toeplitz (const Matrix& vector, size_t size);
  58. /** Creates a squared size x size Hankel Matrix from a vector with an optional offset.
  59. @param vector The vector from which the Hankel matrix should be generated.
  60. Its number of rows should be at least 2 * (size - 1) + 1
  61. @param size The size of resulting square matrix.
  62. @param offset An optional offset into the given vector.
  63. */
  64. static Matrix hankel (const Matrix& vector, size_t size, size_t offset = 0);
  65. //==============================================================================
  66. /** Returns the number of rows in the matrix. */
  67. size_t getNumRows() const noexcept { return rows; }
  68. /** Returns the number of columns in the matrix. */
  69. size_t getNumColumns() const noexcept { return columns; }
  70. /** Returns an Array of 2 integers with the number of rows and columns in the
  71. matrix.
  72. */
  73. Array<size_t> getSize() const noexcept { return {{ rows, columns }}; }
  74. /** Fills the contents of the matrix with zeroes. */
  75. void clear() noexcept { zeromem (data.begin(), sizeof (ElementType) * (size_t) data.size()); }
  76. //==============================================================================
  77. /** Swaps the contents of two rows in the matrix and returns a reference to itself. */
  78. Matrix& swapRows (size_t rowOne, size_t rowTwo) noexcept;
  79. /** Swaps the contents of two columns in the matrix and returns a reference to itself. */
  80. Matrix& swapColumns (size_t columnOne, size_t columnTwo) noexcept;
  81. //==============================================================================
  82. /** Returns the value of the matrix at a given row and column (for reading). */
  83. inline ElementType operator() (size_t row, size_t column) const noexcept
  84. {
  85. jassert (row < rows && column < columns);
  86. return data.getReference (static_cast<int> (dataAcceleration.getReference (static_cast<int> (row))) + static_cast<int> (column));
  87. }
  88. /** Returns the value of the matrix at a given row and column (for modifying). */
  89. inline ElementType& operator() (size_t row, size_t column) noexcept
  90. {
  91. jassert (row < rows && column < columns);
  92. return data.getReference (static_cast<int> (dataAcceleration.getReference (static_cast<int> (row))) + static_cast<int> (column));
  93. }
  94. /** Returns a pointer to the raw data of the matrix object, ordered in row-major
  95. order (for modifying).
  96. */
  97. inline ElementType* getRawDataPointer() noexcept { return data.getRawDataPointer(); }
  98. /** Returns a pointer to the raw data of the matrix object, ordered in row-major
  99. order (for reading).
  100. */
  101. inline const ElementType* getRawDataPointer() const noexcept { return data.begin(); }
  102. //==============================================================================
  103. /** Addition of two matrices */
  104. inline Matrix& operator+= (const Matrix& other) noexcept { return apply (other, std::plus<ElementType>()); }
  105. /** Subtraction of two matrices */
  106. inline Matrix& operator-= (const Matrix& other) noexcept { return apply (other, std::minus<ElementType>()); }
  107. /** Scalar multiplication */
  108. inline Matrix& operator*= (ElementType scalar) noexcept
  109. {
  110. std::for_each (begin(), end(), [scalar] (ElementType& x) { x*= scalar; });
  111. return *this;
  112. }
  113. /** Addition of two matrices */
  114. inline Matrix operator+ (const Matrix& other) const { Matrix result (*this); result += other; return result; }
  115. /** Addition of two matrices */
  116. inline Matrix operator- (const Matrix& other) const { Matrix result (*this); result -= other; return result; }
  117. /** Scalar multiplication */
  118. inline Matrix operator* (ElementType scalar) const { Matrix result (*this); result *= scalar; return result; }
  119. /** Matrix multiplication */
  120. Matrix operator* (const Matrix& other) const;
  121. /** Does a hadarmard product with the receiver and other and stores the result in the receiver */
  122. inline Matrix& hadarmard (const Matrix& other) noexcept { return apply (other, std::multiplies<ElementType>()); }
  123. /** Does a hadarmard product with a and b returns the result. */
  124. static inline Matrix hadarmard (const Matrix& a, const Matrix& b) { Matrix result (a); result.hadarmard (b); return result; }
  125. //==============================================================================
  126. /** Compare to matrices with a given tolerance */
  127. static bool compare (const Matrix& a, const Matrix& b, ElementType tolerance = 0) noexcept;
  128. /* Comparison operator */
  129. inline bool operator== (const Matrix& other) const noexcept { return compare (*this, other); }
  130. //==============================================================================
  131. /** Tells if the matrix is a square matrix */
  132. bool isSquare() const noexcept { return rows == columns; }
  133. /** Tells if the matrix is a vector */
  134. bool isVector() const noexcept { return isOneColumnVector() || isOneRowVector(); }
  135. /** Tells if the matrix is a one column vector */
  136. bool isOneColumnVector() const noexcept { return columns == 1; }
  137. /** Tells if the matrix is a one row vector */
  138. bool isOneRowVector() const noexcept { return rows == 1; }
  139. /** Tells if the matrix is a null matrix */
  140. bool isNullMatrix() const noexcept { return rows == 0 || columns == 0; }
  141. //==============================================================================
  142. /** Solves a linear system of equations represented by this object and the argument b,
  143. using various algorithms depending on the size of the arguments.
  144. The matrix must be a square matrix N times N, and b must be a vector N times 1,
  145. with the coefficients of b. After the execution of the algorithm,
  146. the vector b will contain the solution.
  147. Returns true if the linear system of euqations was successfully solved.
  148. */
  149. bool solve (Matrix& b) const noexcept;
  150. //==============================================================================
  151. /** Returns a String displaying in a convenient way the matrix contents. */
  152. String toString() const;
  153. //==============================================================================
  154. ElementType* begin() noexcept { return data.begin(); }
  155. ElementType* end() noexcept { return data.end(); }
  156. const ElementType* begin() const noexcept { return &data.getReference (0); }
  157. const ElementType* end() const noexcept { return begin() + data.size(); }
  158. private:
  159. //==============================================================================
  160. /** Resizes the matrix. */
  161. void resize()
  162. {
  163. data.resize (static_cast<int> (columns * rows));
  164. dataAcceleration.resize (static_cast<int> (rows));
  165. for (size_t i = 0; i < rows; ++i)
  166. dataAcceleration.setUnchecked (static_cast<int> (i), i * columns);
  167. }
  168. template <typename BinaryOperation>
  169. Matrix& apply (const Matrix& other, BinaryOperation binaryOp)
  170. {
  171. jassert (rows == other.rows && columns == other.columns);
  172. auto* dst = getRawDataPointer();
  173. for (auto src : other)
  174. {
  175. *dst = binaryOp (*dst, src);
  176. ++dst;
  177. }
  178. return *this;
  179. }
  180. //==============================================================================
  181. Array<ElementType> data;
  182. Array<size_t> dataAcceleration;
  183. size_t rows, columns;
  184. //==============================================================================
  185. JUCE_LEAK_DETECTOR (Matrix)
  186. };