Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

107 rader
2.8 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 LinearSystem
  17. {
  18. inline LinearSystem<T>(int cols)
  19. : m_cols(cols)
  20. {
  21. ASSERT(cols > 0);
  22. m_data.Resize(m_cols * m_cols);
  23. }
  24. inline LinearSystem<T>(LinearSystem<T> const &other)
  25. {
  26. m_cols = other.m_cols;
  27. m_data = other.m_data;
  28. }
  29. void Init(T const &x)
  30. {
  31. for (int j = 0; j < m_cols; j++)
  32. for (int i = 0; i < m_cols; i++)
  33. m(i, j) = (i == j) ? x : (T)0;
  34. }
  35. /* Naive matrix inversion */
  36. LinearSystem<T> inv() const
  37. {
  38. LinearSystem a(*this), b(m_cols);
  39. b.Init((T)1);
  40. /* Inversion method: iterate through all columns and make sure
  41. * all the terms are 1 on the diagonal and 0 everywhere else */
  42. for (int i = 0; i < m_cols; i++)
  43. {
  44. /* If the expected coefficient is zero, add one of
  45. * the other lines. The first we meet will do. */
  46. if (!a.m(i, i))
  47. {
  48. for (int j = i + 1; j < m_cols; j++)
  49. {
  50. if (!a.m(i, j))
  51. continue;
  52. /* Add row j to row i */
  53. for (int n = 0; n < m_cols; n++)
  54. {
  55. a.m(n, i) += a.m(n, j);
  56. b.m(n, i) += b.m(n, j);
  57. }
  58. break;
  59. }
  60. }
  61. /* Now we know the diagonal term is non-zero. Get its inverse
  62. * and use that to nullify all other terms in the column */
  63. T x = (T)1 / a.m(i, i);
  64. for (int j = 0; j < m_cols; j++)
  65. {
  66. if (j == i)
  67. continue;
  68. T mul = x * a.m(i, j);
  69. for (int n = 0; n < m_cols; n++)
  70. {
  71. a.m(n, j) -= mul * a.m(n, i);
  72. b.m(n, j) -= mul * b.m(n, i);
  73. }
  74. }
  75. /* Finally, ensure the diagonal term is 1 */
  76. for (int n = 0; n < m_cols; n++)
  77. {
  78. a.m(n, i) *= x;
  79. b.m(n, i) *= x;
  80. }
  81. }
  82. return b;
  83. }
  84. inline T & m(int i, int j) { return m_data[m_cols * j + i]; }
  85. inline T const & m(int i, int j) const { return m_data[m_cols * j + i]; }
  86. int m_cols;
  87. private:
  88. array<T> m_data;
  89. };