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.cpp 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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. template <typename ElementType>
  23. Matrix<ElementType> Matrix<ElementType>::identity (size_t size)
  24. {
  25. Matrix result (size, size);
  26. for (size_t i = 0; i < size; ++i)
  27. result(i, i) = 1;
  28. return result;
  29. }
  30. template <typename ElementType>
  31. Matrix<ElementType> Matrix<ElementType>::toeplitz (const Matrix& vector, size_t size)
  32. {
  33. jassert (vector.isOneColumnVector());
  34. jassert (size <= vector.rows);
  35. Matrix result (size, size);
  36. for (size_t i = 0; i < size; ++i)
  37. result (i, i) = vector (0, 0);
  38. for (size_t i = 1; i < size; ++i)
  39. for (size_t j = i; j < size; ++j)
  40. result (j, j - i) = result (j - i, j) = vector (i, 0);
  41. return result;
  42. }
  43. template <typename ElementType>
  44. Matrix<ElementType> Matrix<ElementType>::hankel (const Matrix& vector, size_t size, size_t offset)
  45. {
  46. jassert(vector.isOneColumnVector());
  47. jassert(vector.rows >= (2 * (size - 1) + 1));
  48. Matrix result (size, size);
  49. for (size_t i = 0; i < size; ++i)
  50. result (i, i) = vector ((2 * i) + offset, 0);
  51. for (size_t i = 1; i < size; ++i)
  52. for (size_t j = i; j < size; ++j)
  53. result (j, j - i) = result (j - i, j) = vector (i + 2 * (j - i) + offset, 0);
  54. return result;
  55. }
  56. //==============================================================================
  57. template <typename ElementType>
  58. Matrix<ElementType>& Matrix<ElementType>::swapColumns (size_t columnOne, size_t columnTwo) noexcept
  59. {
  60. jassert (columnOne < columns && columnTwo < columns);
  61. auto* p = data.getRawDataPointer();
  62. for (size_t i = 0; i < rows; ++i)
  63. {
  64. auto offset = dataAcceleration.getUnchecked (static_cast<int> (i));
  65. std::swap (p[offset + columnOne], p[offset + columnTwo]);
  66. }
  67. return *this;
  68. }
  69. template <typename ElementType>
  70. Matrix<ElementType>& Matrix<ElementType>::swapRows (size_t rowOne, size_t rowTwo) noexcept
  71. {
  72. jassert (rowOne < rows && rowTwo < rows);
  73. auto offset1 = rowOne * columns;
  74. auto offset2 = rowTwo * columns;
  75. auto* p = data.getRawDataPointer();
  76. for (size_t i = 0; i < columns; ++i)
  77. std::swap (p[offset1 + i], p[offset2 + i]);
  78. return *this;
  79. }
  80. //==============================================================================
  81. template <typename ElementType>
  82. Matrix<ElementType> Matrix<ElementType>::operator* (const Matrix<ElementType>& other) const
  83. {
  84. auto n = getNumRows(), m = other.getNumColumns(), p = getNumColumns();
  85. Matrix result (n, m);
  86. jassert (p == other.getNumRows());
  87. size_t offsetMat = 0, offsetlhs = 0;
  88. auto* dst = result.getRawDataPointer();
  89. auto* a = getRawDataPointer();
  90. auto* b = other.getRawDataPointer();
  91. for (size_t i = 0; i < n; ++i)
  92. {
  93. size_t offsetrhs = 0;
  94. for (size_t k = 0; k < p; ++k)
  95. {
  96. auto ak = a[offsetlhs++];
  97. for (size_t j = 0; j < m; ++j)
  98. dst[offsetMat + j] += ak * b[offsetrhs + j];
  99. offsetrhs += m;
  100. }
  101. offsetMat += m;
  102. }
  103. return result;
  104. }
  105. //==============================================================================
  106. template <typename ElementType>
  107. bool Matrix<ElementType>::compare (const Matrix& a, const Matrix& b, ElementType tolerance) noexcept
  108. {
  109. if (a.rows != b.rows || a.columns != b.columns)
  110. return false;
  111. tolerance = std::abs (tolerance);
  112. auto* bPtr = b.begin();
  113. for (auto aValue : a)
  114. if (std::abs (aValue - *bPtr++) > tolerance)
  115. return false;
  116. return true;
  117. }
  118. //==============================================================================
  119. template <typename ElementType>
  120. bool Matrix<ElementType>::solve (Matrix& b) const noexcept
  121. {
  122. auto n = columns;
  123. jassert (n == n && n == b.rows && b.isOneColumnVector());
  124. auto* x = b.getRawDataPointer();
  125. const auto& A = *this;
  126. switch (n)
  127. {
  128. case 1:
  129. {
  130. auto denominator = A (0,0);
  131. if (denominator == 0)
  132. return false;
  133. b (0, 0) /= denominator;
  134. }
  135. break;
  136. case 2:
  137. {
  138. auto denominator = A (0, 0) * A (1, 1) - A (0, 1) * A (1, 0);
  139. if (denominator == 0)
  140. return false;
  141. auto factor = (1 / denominator);
  142. auto b0 = x[0], b1 = x[1];
  143. x[0] = factor * (A (1, 1) * b0 - A (0, 1) * b1);
  144. x[1] = factor * (A (0, 0) * b1 - A (1, 0) * b0);
  145. }
  146. break;
  147. case 3:
  148. {
  149. auto denominator = A (0, 0) * (A (1, 1) * A (2, 2) - A (1, 2) * A (2, 1))
  150. + A (0, 1) * (A (1, 2) * A (2, 0) - A (1, 0) * A (2, 2))
  151. + A (0, 2) * (A (1, 0) * A (2, 1) - A (1, 1) * A (2, 0));
  152. if (denominator == 0)
  153. return false;
  154. auto factor = 1 / denominator;
  155. auto b0 = x[0], b1 = x[1], b2 = x[2];
  156. x[0] = ( ( A (0, 1) * A (1, 2) - A (0, 2) * A (1, 1)) * b2
  157. + (-A (0, 1) * A (2, 2) + A (0, 2) * A (2, 1)) * b1
  158. + ( A (1, 1) * A (2, 2) - A (1, 2) * A (2, 1)) * b0) * factor;
  159. x[1] = -( ( A (0, 0) * A (1, 2) - A (0, 2) * A (1, 0)) * b2
  160. + (-A (0, 0) * A (2, 2) + A (0, 2) * A (2, 0)) * b1
  161. + ( A (1, 0) * A (2, 2) - A (1, 2) * A (2, 0)) * b0) * factor;
  162. x[2] = ( ( A (0, 0) * A (1, 1) - A (0, 1) * A (1, 0)) * b2
  163. + (-A (0, 0) * A (2, 1) + A (0, 1) * A (2, 0)) * b1
  164. + ( A (1, 0) * A (2, 1) - A (1, 1) * A (2, 0)) * b0) * factor;
  165. }
  166. break;
  167. default:
  168. {
  169. Matrix<ElementType> M (A);
  170. for (size_t j = 0; j < n; ++j)
  171. {
  172. if (M (j, j) == 0)
  173. {
  174. auto i = j;
  175. while (i < n && M (i, j) == 0)
  176. ++i;
  177. if (i == n)
  178. return false;
  179. for (size_t k = 0; k < n; ++k)
  180. M (j, k) += M (i, k);
  181. x[j] += x[i];
  182. }
  183. auto t = 1 / M (j, j);
  184. for (size_t k = 0; k < n; ++k)
  185. M (j, k) *= t;
  186. x[j] *= t;
  187. for (size_t k = j + 1; k < n; ++k)
  188. {
  189. auto u = -M (k, j);
  190. for (size_t l = 0; l < n; ++l)
  191. M (k, l) += u * M (j, l);
  192. x[k] += u * x[j];
  193. }
  194. }
  195. for (int k = static_cast<int> (n) - 2; k >= 0; --k)
  196. for (size_t i = static_cast<size_t> (k) + 1; i < n; ++i)
  197. x[k] -= M (static_cast<size_t> (k), i) * x[i];
  198. }
  199. }
  200. return true;
  201. }
  202. //==============================================================================
  203. template <typename ElementType>
  204. String Matrix<ElementType>::toString() const
  205. {
  206. StringArray entries;
  207. int sizeMax = 0;
  208. auto* p = data.begin();
  209. for (size_t i = 0; i < rows; ++i)
  210. {
  211. for (size_t j = 0; j < columns; ++j)
  212. {
  213. String entry (*p++, 4);
  214. sizeMax = jmax (sizeMax, entry.length());
  215. entries.add (entry);
  216. }
  217. }
  218. sizeMax = ((sizeMax + 1) / 4 + 1) * 4;
  219. MemoryOutputStream result;
  220. auto n = static_cast<size_t> (entries.size());
  221. for (size_t i = 0; i < n; ++i)
  222. {
  223. result << entries[(int) i].paddedRight (' ', sizeMax);
  224. if (i % columns == (columns - 1))
  225. result << newLine;
  226. }
  227. return result.toString();
  228. }
  229. template class Matrix<float>;
  230. template class Matrix<double>;
  231. } // namespace dsp
  232. } // namespace juce