Audio plugin host https://kx.studio/carla
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.

juce_Matrix.h 11KB

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