您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

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