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.

matrix.h 2.6 KiB

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