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.

311 lines
8.5KB

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