|
- //
- // LolRemez - Remez algorithm implementation
- //
- // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the Do What The Fuck You Want To
- // Public License, Version 2, as published by Sam Hocevar. See
- // http://www.wtfpl.net/ for more details.
- //
-
- #pragma once
-
- using namespace lol;
-
- /*
- * Arbitrarily-sized square matrices; for now this only supports
- * naive inversion and is used for the Remez inversion method.
- */
-
- template<typename T> struct Matrix
- {
- inline Matrix<T>(int cols, int rows)
- : m_cols(cols),
- m_rows(rows)
- {
- ASSERT(cols > 0);
- ASSERT(rows > 0);
-
- m_data.Resize(m_cols * m_rows);
- }
-
- inline Matrix<T>(Matrix<T> const &other)
- {
- m_cols = other.m_cols;
- m_rows = other.m_rows;
- m_data = other.m_data;
- }
-
- void Init(T const &x)
- {
- for (int j = 0; j < m_rows; j++)
- for (int i = 0; i < m_cols; i++)
- m(i, j) = (i == j) ? x : (T)0;
- }
-
- /* Naive matrix inversion */
- Matrix<T> inv() const
- {
- ASSERT(m_cols == m_rows);
-
- Matrix a(*this), b(m_cols, m_rows);
-
- b.Init((T)1);
-
- /* Inversion method: iterate through all columns and make sure
- * all the terms are 1 on the diagonal and 0 everywhere else */
- for (int i = 0; i < m_cols; i++)
- {
- /* If the expected coefficient is zero, add one of
- * the other lines. The first we meet will do. */
- if (!a.m(i, i))
- {
- for (int j = i + 1; j < m_cols; j++)
- {
- if (!a.m(i, j))
- continue;
- /* Add row j to row i */
- for (int n = 0; n < m_cols; n++)
- {
- a.m(n, i) += a.m(n, j);
- b.m(n, i) += b.m(n, j);
- }
- break;
- }
- }
-
- /* Now we know the diagonal term is non-zero. Get its inverse
- * and use that to nullify all other terms in the column */
- T x = (T)1 / a.m(i, i);
- for (int j = 0; j < m_cols; j++)
- {
- if (j == i)
- continue;
- T mul = x * a.m(i, j);
- for (int n = 0; n < m_cols; n++)
- {
- a.m(n, j) -= mul * a.m(n, i);
- b.m(n, j) -= mul * b.m(n, i);
- }
- }
-
- /* Finally, ensure the diagonal term is 1 */
- for (int n = 0; n < m_cols; n++)
- {
- a.m(n, i) *= x;
- b.m(n, i) *= x;
- }
- }
-
- return b;
- }
-
- inline T & m(int i, int j) { return m_data[m_rows * j + i]; }
- inline T const & m(int i, int j) const { return m_data[m_rows * j + i]; }
-
- int m_cols, m_rows;
-
- private:
- Array<T> m_data;
- };
|