В этот разделе описаны шаблоны классов предназначенные для представления математических матриц.
template <class Type> class IMatrix { Type * const * const data; // Запрет оператора присваивания и конструктора копии void operator = ( const IMatrix & ); IMatrix ( const IMatrix & ); public: const nat nRow; // к-во строк const nat nCol; // к-во столбцов IMatrix ( nat r, nat c, Type * const * const p ) : nRow(r), nCol(c), data(p) {} IMatrix & fill ( const Type & p ) { for ( nat i = 0; i < nRow; ++i ) { Type * t = data[i]; for ( nat j = 0; j < nCol; ++j ) t[j] = p; } return *this; } IMatrix & operator *= ( const Type & p ) { for ( nat i = 0; i < nRow; ++i ) { Type * t = data[i]; for ( nat j = 0; j < nCol; ++j ) t[j] *= p; } return *this; } operator Type * const * () { return data; } operator const Type * const * () const { return data; } };Имеются: 1) конструктор, 2) функция-член fill, которая заполняет матрицу указанным значением, 3) оператор *=, который умножает матрицу на число, и 4) два оператора пребразования типа. Шаблон SMatrix может создавать матрицу в стеке и применяется, когда размер матрицы известен на этапе компиляции: template <class Type, nat R, nat C> class SMatrix : public IMatrix<Type> { Type * p[R]; Type stor[R*C]; public: SMatrix () : IMatrix<Type> ( R, C, p ) { p[0] = stor; for ( nat i = 1; i < R; ++i ) p[i] = p[i-1] + C; } SMatrix ( const SMatrix & m ) : IMatrix<Type> ( R, C, p ) { nat i; p[0] = stor; for ( i = 1; i < R; ++i ) p[i] = p[i-1] + C; for ( i = 0; i < R*C; ++i ) stor[i] = m.stor[i]; } SMatrix & operator = ( const SMatrix & m ) { for ( nat i = 0; i < R*C; ++i ) stor[i] = m.stor[i]; return *this; } };Шаблон HMatrix располагает элементы матрицы в динамической памяти ( куче ): template <class Type, nat R, nat C> class HMatrix : public IMatrix<Type> { Type ** p; // Запрет оператора присваивания HMatrix & operator = ( const HMatrix & m ); public: HMatrix ( nat r, nat c ) : IMatrix<Type> ( r, c, p = r > 0 ? new Type*[r] : 0 ) { if ( ! nRow ) return; p[0] = new Type[nRow*nCol]; for ( nat i = 1; i < nRow; ++i ) p[i] = p[i-1] + nCol; } explicit HMatrix ( const IMatrix<Type> & m ) : IMatrix<Type> ( m.nRow, m.nCol, p = m.nRow > 0 ? new Type*[m.nRow] : 0 ) { if ( ! nRow ) return; const nat n = nRow * nCol; Type * t = p[0] = new Type[n]; for ( nat i = 1; i < nRow; ++i ) p[i] = p[i-1] + nCol; const Type * s = m[0]; for ( nat j = 0; j < n; ++j ) t[j] = s[j]; } explicit HMatrix ( const HMatrix<Type> & m ) : IMatrix<Type> ( m.nRow, m.nCol, p = m.nRow > 0 ? new Type*[m.nRow] : 0 ) { if ( ! nRow ) return; const nat n = nRow * nCol; Type * t = p[0] = new Type[n]; for ( nat i = 1; i < nRow; ++i ) p[i] = p[i-1] + nCol; const Type * s = m[0]; for ( nat j = 0; j < n; ++j ) t[j] = s[j]; } ~HMatrix() { if ( p != 0 ) { delete[] p[0]; delete[] p; } } };Шаблон CmbMatrix является комбинацией двух предыдущих: template <class Type, nat R, nat C> class CmbMatrix : public IMatrix<Type> { Type ** p; Type * pa[R]; Type stor[R*C]; // Запрет оператора присваивания CmbMatrix & operator = ( const CmbMatrix & m ); public: CmbMatrix ( nat r, nat c ) : IMatrix<Type> ( r, c, p = r > R ? new Type*[r] : pa ) { const nat n = nRow * nCol; p[0] = n > R*C ? new Type[n] : stor; for ( nat i = 1; i < nRow; ++i ) p[i] = p[i-1] + nCol; } explicit CmbMatrix ( const IMatrix<Type> & m ) : IMatrix<Type> ( m.nRow, m.nCol, p = m.nRow > R ? new Type*[m.nRow] : pa ) { const nat n = nRow * nCol; Type * t = p[0] = n > R*C ? new Type[n] : stor; for ( nat i = 1; i < nRow; ++i ) p[i] = p[i-1] + nCol; const Type * s = m[0]; for ( nat j = 0; j < n; ++j ) t[j] = s[j]; } explicit CmbMatrix ( const CmbMatrix<Type, R, C> & m ) : IMatrix<Type> ( m.nRow, m.nCol, p = m.nRow > R ? new Type*[m.nRow] : pa ) { const nat n = nRow * nCol; Type * t = p[0] = n > R*C ? new Type[n] : stor; for ( nat i = 1; i < nRow; ++i ) p[i] = p[i-1] + nCol; const Type * s = m[0]; for ( nat j = 0; j < n; ++j ) t[j] = s[j]; } ~CmbMatrix() { if ( p[0] != stor ) delete[] p[0]; if ( p != pa ) delete[] p; } };Следующая группа функций-шаблонов выполняет копирование, сложение, отнимание и умножение матриц, если размеры матриц согласованы: template <class Type> bool copy ( const IMatrix<Type> & a, IMatrix<Type> & b ) // b = a template <class Type> bool plus ( const IMatrix<Type> & a, const IMatrix<Type> & b, IMatrix<Type> & c ) // c = a + b template <class Type> bool minus ( const IMatrix<Type> & a, const IMatrix<Type> & b, IMatrix<Type> & c ) // c = a - b template <class Type> bool multi ( const IMatrix<Type> & a, const IMatrix<Type> & b, IMatrix<Type> & c ) // c = a * bСледующая группа функций определена для вещественных матриц ( исходники находятся в файле matrix.cpp ): bool determinant ( const IMatrix<double> & m, double & d ); bool trans ( const IMatrix<double> & a, IMatrix<double> & b ); // b = aT bool inverse( const IMatrix<double> & a, IMatrix<double> & b ); // a * b = 1 // Матричные нормы double norm1 ( const IMatrix<double> & ); // 1-норма double norm2 ( const IMatrix<double> & ); // 2-норма double normF ( const IMatrix<double> & ); // норма Фробениуса double normU ( const IMatrix<double> & ); // бесконечная норма // Cингулярное разложение: A = U * W * V bool svd ( const IMatrix<double> & A, IMatrix<double> & U, IMatrix<double> & W, IMatrix<double> & V );Следующая группа функций определена для комплексных матриц ( исходники находятся в файле cmatrix.cpp ): // Транспонирование bool trans ( const IMatrix<Complex> & a, IMatrix<Complex> & b ); // b = aT // Решение задачи наименьших квадратов при помощи преобразований Хаусхолдера bool lss_h ( IMatrix<Complex> & a, const Complex * b, Complex * x ); // b[a.nRow], x[a.nCol]Наверх
|