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.

319 lines
8.8KB

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