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.

315 lines
8.9KB

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