Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

112 строки
2.9 KiB

  1. //
  2. // LolRemez - Remez algorithm implementation
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #pragma once
  11. using namespace lol;
  12. /*
  13. * Arbitrarily-sized square matrices; for now this only supports
  14. * naive inversion and is used for the Remez inversion method.
  15. */
  16. template<typename T> struct Matrix
  17. {
  18. inline Matrix<T>(int cols, int rows)
  19. : m_cols(cols),
  20. m_rows(rows)
  21. {
  22. ASSERT(cols > 0);
  23. ASSERT(rows > 0);
  24. m_data.Resize(m_cols * m_rows);
  25. }
  26. inline Matrix<T>(Matrix<T> const &other)
  27. {
  28. m_cols = other.m_cols;
  29. m_rows = other.m_rows;
  30. m_data = other.m_data;
  31. }
  32. void Init(T const &x)
  33. {
  34. for (int j = 0; j < m_rows; j++)
  35. for (int i = 0; i < m_cols; i++)
  36. m(i, j) = (i == j) ? x : (T)0;
  37. }
  38. /* Naive matrix inversion */
  39. Matrix<T> inv() const
  40. {
  41. ASSERT(m_cols == m_rows);
  42. Matrix a(*this), b(m_cols, m_rows);
  43. b.Init((T)1);
  44. /* Inversion method: iterate through all columns and make sure
  45. * all the terms are 1 on the diagonal and 0 everywhere else */
  46. for (int i = 0; i < m_cols; i++)
  47. {
  48. /* If the expected coefficient is zero, add one of
  49. * the other lines. The first we meet will do. */
  50. if (!a.m(i, i))
  51. {
  52. for (int j = i + 1; j < m_cols; j++)
  53. {
  54. if (!a.m(i, j))
  55. continue;
  56. /* Add row j to row i */
  57. for (int n = 0; n < m_cols; n++)
  58. {
  59. a.m(n, i) += a.m(n, j);
  60. b.m(n, i) += b.m(n, j);
  61. }
  62. break;
  63. }
  64. }
  65. /* Now we know the diagonal term is non-zero. Get its inverse
  66. * and use that to nullify all other terms in the column */
  67. T x = (T)1 / a.m(i, i);
  68. for (int j = 0; j < m_cols; j++)
  69. {
  70. if (j == i)
  71. continue;
  72. T mul = x * a.m(i, j);
  73. for (int n = 0; n < m_cols; n++)
  74. {
  75. a.m(n, j) -= mul * a.m(n, i);
  76. b.m(n, j) -= mul * b.m(n, i);
  77. }
  78. }
  79. /* Finally, ensure the diagonal term is 1 */
  80. for (int n = 0; n < m_cols; n++)
  81. {
  82. a.m(n, i) *= x;
  83. b.m(n, i) *= x;
  84. }
  85. }
  86. return b;
  87. }
  88. inline T & m(int i, int j) { return m_data[m_rows * j + i]; }
  89. inline T const & m(int i, int j) const { return m_data[m_rows * j + i]; }
  90. int m_cols, m_rows;
  91. private:
  92. array<T> m_data;
  93. };