stlmat.h

来自「矩阵、向量以及四元数的封装类」· C头文件 代码 · 共 2,636 行 · 第 1/4 页

H
2,636
字号
          m.mat[k][i] = m.mat[is[k]][i];
          m.mat[is[k]][i] = swap;
        }
      }
      if (js[k] != k)
      {
        f = -f;
        for (i = 0; i < N; ++i)
        {
          swap = m.mat[i][k];
          m.mat[i][k] = m.mat[i][js[k]];
          m.mat[i][js[k]] = swap;
        }
      }

      fDet *= m.mat[k][k];
      m.mat[k][k] = 1.0 / m.mat[k][k];
      for (j = 0; j < N; j++)
      {
        if (j != k)
          m.mat[k][j] *= m.mat[k][k];
      }
      for (i = 0; i < N; i++)
      {
        if (i != k)
        {
          for (j = 0; j < N; j++)
          {
            if (j != k)
              m.mat[i][j] = m.mat[i][j] - m.mat[i][k] * m.mat[k][j];
          }
        }
      }
      for (i = 0; i < N; i++)
      {
        if (i != k)
          m.mat[i][k] *= -m.mat[k][k];
      }
    }
    return fDet * f;
  }

  /**
   * Divide a matrix by another one.
   */
  friend inline Matrix operator /(const Matrix &mL, const Matrix &mR) throw(int)
  {
  	if (R != C)
  		throw NoSquareMatrix;
    return mL * mR.getInverse();
  }
#endif
};

template <size_t R, size_t C>
const size_t Matrix<R, C>::count = R * C;
template <size_t R, size_t C>
const size_t Matrix<R, C>::size = sizeof(double) * R * C;

#if !defined(STL_COMPILER_MSVC) || STL_COMPILER_VER > 1200
/** \class Matrix<N, N>
 * A N x N matrix template class.
 */
template <size_t N>
struct Matrix<N, N>
{
private:
  /// Array components.
  union
  {
    /// 2D array.
    double      mat[N][N];
    /// 1D array.
    double      vec[N * N];
  };
  /// Count of the components
  static const unsigned int count;
  /// Size in bytes of the components.
  static const unsigned int size;

public:
  /** \name Construct
   * @{ */
  /**
   * Default constructor.
   * @remarks The matrix is not initialized in this case.
   */
  Matrix()
  {}

  /**
   * Construct a matrix with given values array.
   * @param m Pointer of the values array used to set the matrix.
   */
  Matrix(const double *m)
  {
    memcpy(vec, m, size);
  }

  /**
   * Construct a matrix with given type compatible values array.
   * @param m Pointer of the values array used to set the matrix.
   */
  template <typename T>
  Matrix(const T *m)
  {
    for (unsigned int i = 0; i < count; i ++)
      vec[i] = m[i];
  }

  /**
   * Construct a matrix with given 2D values array.
   * @param m A 2D values array.
   */
  Matrix(const double m[N][N])
  {
    memcpy(vec, m[0], size);
  }

  /**
   * Construct a matrix with given type compatible 2D values array.
   * @param m A 2D type compatible values array.
   */
  template <typename T>
  Matrix(const T m[N][N])
  {
    for (unsigned int i = 0; i < N; i ++)
      for (unsigned int j = 0; j < N; j ++)
        mat[i][j] = m[i][j];
  }

  /**
   * Copy constructor, construct a matrix with another one.
   * @param m Another matrix used to set the new one.
   */
  Matrix(const Matrix &m)
  {
    memcpy(vec, m.vec, size);
  }
  /** @} */

  /** \name Assignment
   * @{ */
  /**
   * Assignment operator, set the matrix with a values array.
   * @param m Pointer of the values array used to set the matrix.
   * @return Reference of this matrix.
   */
  inline Matrix &operator =(const double *m)
  {
    memcpy(vec, m, size);
    return *this;
  }

  /**
   * Assignment operator, set the matrix with a type compatible values array.
   * @param m Pointer of the values array used to set the matrix.
   * @return Reference of this matrix.
   */
  template <typename T>
  inline Matrix &operator =(const T *m)
  {
    for (unsigned int i = 0; i < count; i ++)
      vec[i] = m[i];
    return *this;
  }

  /**
   * Assignment operator, set the matrix with a 2D values array.
   * @param m A 2D values array.
   * @return Reference of this matrix.
   */
  inline Matrix &operator =(const double m[N][N])
  {
    memcpy(vec, m[0], size);
    return *this;
  }

  /**
   * Assignment operator, set the matrix with a 2D type compatible values array.
   * @param m A 2D values array.
   * @return Reference of this matrix.
   */
  template <typename T>
  inline Matrix &operator =(const T m[N][N])
  {
    for (unsigned int i = 0; i < N; i ++)
      for (unsigned int j = 0; j < N; j ++)
        mat[i][j] = m[i][j];
    return *this;
  }

  /**
   * Assignment operator, set the matrix with another one.
   * @param m Reference of another matrix used to set this one.
   * @return Reference of this matrix.
   */
  inline Matrix &operator =(const Matrix &m)
  {
    memcpy(vec, m.vec, size);
    return *this;
  }


  /**
   * Set the matrix with another one.
   * @param m Reference of another matrix used to set this one.
   * @return Reference of this matrix.
   */
  inline Matrix &set(const Matrix &m)
  {
    memcpy(vec, m.vec, size);
    return *this;
  }

  /**
   * Set the matrix with given values array.
   * @param m Pointer of the values array used to set this matrix.
   * @return Reference of this matrix.
   */
  inline Matrix &set(const double *m)
  {
    memcpy(vec, m, size);
    return *this;
  }

  /**
   * Set the matrix with given type compatible value array.
   * @param m Pointer of the values array used to set the matrix.
   * @return Reference of this matrix.
   */
  template <typename T>
  inline Matrix &set(const T *m)
  {
    for (unsigned int i = 0; i < count; i ++)
      vec[i] = m[i];
    return *this;
  }

  /**
   * Set the matrix with given two dimension array.
   * @param m A 2D values array.
   * @return Reference of this matrix.
   */
  inline Matrix &set(const double m[N][N])
  {
    memcpy(vec, m[0], size);
    return *this;
  }

  /**
   * Set the matrix with given type compatible two dimension values array.
   * @param m A 2D values array.
   * @return Reference of this matrix.
   */
  template <typename T>
  inline Matrix &set(const T m[N][N])
  {
    for (unsigned int i = 0; i < N; i ++)
      for (unsigned int j = 0; j < N; j ++)
        mat[i][j] = m[i][j];
    return *this;
  }

  /**
   * Make this matrix identity.
   * @return Reference of this matrix.
   */
  inline Matrix &identity()
  {
    memset(vec, 0, size);
    for (unsigned int i = 0; i < N; i ++)
      mat[i][i] = 1.0;
    return *this;
  }
  /** @} */

public:
	/** \name Visit
	 * @{ */
  /**
   * Query the n'th row of the Matrix.
   * @param n Zero based index of the row wanted.
   * @return Address of the first component in the given row.
   */
	inline double *operator [](int n)
  {
    return mat[n];
  }

  /**
   * Query the n'th row of the Matrix.
   * @param n Zero based index of the row wanted.
   * @return Address of the first component in the given row.
   */
	inline const double *operator[](int n) const
  {
    return mat[n];
  }

  /**
   * Get the specified row as a vector.
   * @param n Zero based index of the row wanted.
   * @return A vector holding on the queried row.
   */
	inline Vector<N> getRow(int n) const
  {
    return Vector<N>(mat[n]);
  }

  /**
   * Get the specified column as a vector.
   * @param n Zero based index of the column wanted.
   * @return A vector holding on the queried column.
   */
	inline Vector<N> getColumn(int n) const
  {
    Vector<N> v;
    for (unsigned int i = 0; i < N; i ++)
      v[i] = mat[i][n];
    return v;
  }
  /** @} */

  /**
   * Get the transpose Matrix of this one.
   * @return A matrix as the transpose of this one.
   */
	inline Matrix<N, N> getTranspose() const
  {
    Matrix<N, N> m;
    for (unsigned int i = 0; i < N; i ++)
      for (unsigned int j = 0; j < N; j ++)
        m[j][i] = mat[i][j];
    return m;
  }

  /**
   * Transpose this matrix.
   * @return Reference of this matrix.
   */
  inline Matrix &transpose()
  {
    double swap;
    for (int i = 0; i < N; i ++)
      for (int j = 0; j < i; j ++)
      {
        swap = mat[i][j];
        mat[i][j] = mat[j][i];
        mat[j][i] = swap;
      }
    return *this;
  }

  /**
   * Query the inverse matrix.
   * @return A matrix as the inverse matrix of this one.
   */
  inline Matrix getInverse() const throw(MatrixErrorCode)
  {
    Matrix m(mat);
    m.invert();
    return m;
  }

  /**
   * Invert this matrix.
   * @return Reference of this one.
   */
  inline void invert() throw(MatrixErrorCode)
  {
    int is[N];
    int js[N];
    int i, j, k;
    double swap;
    for (k = 0; k < N; ++k)
    {
      double fMax = 0.0;
      is[k] = js[k] = k;
      for (i = k; i < N; ++i)
      {
        for (j = k; j < N; ++j)
        {
          if (fabs(mat[i][j]) > fMax)
          {
            fMax = fabs(mat[i][j]);
            is[k] = i;
            js[k] = j;
          }
        }
      }
      if (fMax < 1e-12)
        throw ZeroMatrix;
      if (is[k] != k)
      {
        for (i = 0; i < N; ++i)
        {
          swap = mat[k][i];
          mat[k][i] = mat[is[k]][i];
          mat[is[k]][i] = swap;
        }
      }
      if (js[k] != k)
      {
        for (i = 0; i < N; ++i)
        {
          swap = mat[i][k];
          mat[i][k] = mat[i][js[k]];
          mat[i][js[k]] = swap;
        }
      }
      mat[k][k] = 1.0 / mat[k][k];
      for (j = 0; j < N; ++j)
      {
        if (j != k)
          mat[k][j] *= mat[k][k];
      }
      for (i = 0; i < N; ++i)
      {
        if (i != k)
        {
          for (j = 0; j < N; ++j)
          {
            if (j != k)
              mat[i][j] = mat[i][j] - mat[i][k] * mat[k][j];
          }
        }
      }
      for (i = 0; i < N; ++i)
      {
        if (i != k)
          mat[i][k] *= -mat[k][k];
      }
    }
    for (k = N - 1; (int)k >= 0; k--)
    {
      if (js[k] != k)
      {
        for (i = 0; i < N; ++i)
        {
          swap = mat[k][i];
          mat[k][i] = mat[js[k]][i];
          mat[js[k]][i] = swap;
        }
      }
      if (is[k] != k)
      {
        for (i = 0; i < N; ++i)
        {
          swap = mat[i][k];
          mat[i][k] = mat[i][is[k]];
          mat[i][is[k]] = swap;
        }
      }
    }

    return *this;
  }

  /**
   * Query the determinant of this matrix.
   * @return Determinant of this matrix.
   */
  inline double getDeterminant() const
  {
    Matrix m(mat);
    int is[N], js[N];
    int i, j, k;
    double fDet = 1.0, swap;
    int f = 1;
    for (k = 0; k < N; ++k)
    {
      double fMax = 0.0;
      for (i = k; i < N; i++)
      {
        for (j = k; j < N; j++)
        {
          if (fabs(m.mat[i][j]) > fMax)
          {
            fMax = fabs(m.mat[i][j]);
            is[k] = i;
            js[k] = j;
          }
        }
      }
      if (fabs(fMax) < 1e-12)
        return 0;
      if (is[k] != k)
      {
        f = -f;
        for (i = 0; i < N; ++i)
        {
          swap = m.mat[k][i];
          m.mat[k][i] = m.mat[is[k]][i];
          m.mat[is[k]][i] = swap;
        }
      }
      if (js[k] != k)
      {
        f = -f;
        for (i = 0; i < N; ++i)
        {
          swap = m.mat[i][k];
          m.mat[i][k] = m.mat[i][js[k]];
          m.mat[i][js[k]] = swap;
        }
      }

      fDet *= m.mat[k][k];
      m.mat[k][k] = 1.0 / m.mat[k][k];
      for (j = 0; j < N; j++)
      {
        if (j != k)
          m.mat[k][j] *= m.mat[k][k];
      }
      for (i = 0; i < N; i++)
      {
        if (i != k)
        {
          for (j = 0; j < N; j++)
          {
            if (j != k)
              m.mat[i][j] = m.mat[i][j] - m.mat[i][k] * m.mat[k][j];
          }
        }
      }
      for (i = 0; i < N; i++)
      {
        if (i != k)
          m.mat[i][k] *= -m.mat[k][k];
      }
    }
    return fDet * f;
  }

  /** \name Operators
   * @{ */
  /**
   * Add another matrix onto this one.
   */
  inline Matrix &operator +=(const Matrix &m)
  {
    for (unsigned int i = 0; i < count; i ++)
      vec[i] += m.vec[i];
    return *this;
  }

  /**
   * Subtract another matrix from this one.
   */
  inline Matrix &operator -=(const Matrix &m)
  {
    for (unsigned int i = 0; i < count; i ++)
      vec[i] -= m.vec[i];
    return *this;
  }

  /**
   * Multiply this matrix with a scalar.
   */
  inline Matrix &operator *=(double s)
  {
    for (unsigned int i = 0; i < count; i ++)
      vec[i] *= s;
    return *this;
  }

  /**
   * Devide this matrix by a scalar.
   */
  inline Matrix &operator /=(double s)
  {
    s = 1.0 / s;
    for (unsigned int i = 0; i < count; i ++)
      vec[i] *= s;
    return *this;
  }

  /**
   * Multiply this matrix with another one.
   */
  inline Matrix &operator *=(const Matrix &m)
  {
    set((*this) * m);
    return *this;
  }

  /**
   * Divide by another matrix.
   */
  inline Matrix &operator /=(const Matrix &m) throw(MatrixErrorCode)
  {
    return operator *=(m.getInverse());
  }

  /**
   * Unary + operator.
   */
  inline Matrix operator +() const
  {
    return *this;
  }

  /**
   * Unary - operator.
   */
  inline Matrix operator -() const
  {
    Matrix m;
    for (unsigned int i = 0; i < count; i ++)
      m.vec[i] = -vec[i];
    return m;
  }

  /**
   * Add two matrices.
   */
  friend inline Matrix operator +(const Matrix &m1, const Matrix &m2)
  {
    Matrix m;
    for (unsigned int i = 0; i < count; i ++)
      m.vec[i] = m1.vec[i] + m2.vec[i];
    return m;
  }

  /**
   * Subtract two matrices.
   */
  friend inline Matrix operator -(const Matrix &m1, const Matrix &m2)
  {
    Matrix m;
    for (unsigned int i = 0; i < count; i ++)
      m.vec[i] = m1.vec[i] - m2.vec[i];
    return m;
  }

  /**
   * Multiply a matrix with a scalar.
   */
  friend inline Matrix operator *(const Matrix &m1, double s)
  {
    Matrix m;
    for (unsigned int i = 0; i < count; i ++)
      m.vec[i] = m1.vec[i] * s;
    return m;
  }

  /**
   * Multiply a scalar with a matrix.
   */
  friend inline Matrix operator *(double s, const Matrix &m1)
  {
    Matrix m;
    for (unsigned int i = 0; i < count; i ++)
      m.vec[i] = s * m1.vec[i];
    return m;
  }

  /**

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?