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.

248 lines
10KB

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