⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 matrix_sub.cc

📁 basic linear algebra classes and applications (SVD,interpolation, multivariate optimization)
💻 CC
字号:
// This may look like C code, but it is really -*- C++ -*-/* ************************************************************************ * *			Linear Algebra Package * *		Basic linear algebra operations, levels 1 & 2 *	    Operations on a single row, column, or the diagonal *			   	of a matrix * * $Id: matrix_sub.cc,v 4.2 1998/12/01 17:25:41 oleg Exp oleg $ * ************************************************************************ */#include "LAStreams.h"#include <math.h>#include <iostream.h>/* *------------------------------------------------------------------------ *		Messing with a single row/column/diag of a matrix */			// Constructing the MatrixColumn objectConstMatrixColumn::ConstMatrixColumn(const Matrix& m, const int col)  	: Matrix::ConstReference(m),  	  DimSpec(m.q_row_lwb(),m.q_row_upb(),col,col),  	  col_ptr(m.elements+(col-m.q_col_lwb())*m.q_nrows()){  if( col > m.q_col_upb() || col < m.q_col_lwb() )    m.info(),    _error("Column #%d is not within the above matrix",col);}			// Constructing the MatrixRow objectConstMatrixRow::ConstMatrixRow(const Matrix& m, const int row)  	: Matrix::ConstReference(m),  	  DimSpec(row,row,m.q_col_lwb(),m.q_col_upb()),  	  row_ptr(m.elements+(row-m.q_row_lwb())),  	  stride(m.q_nrows()),  	  end_ptr(m.elements+m.nelems){  if( row > m.q_row_upb() || row < m.q_row_lwb() )    m.info(),    _error("Row #%d is not within the above matrix",row);  assert( stride > 0 );}			// Constructing the MatrixDiag objectConstMatrixDiag::ConstMatrixDiag(const Matrix& m)  	: Matrix::ConstReference(m),  	  DimSpec(1,::min(m.q_nrows(),m.q_ncols()),  	          1,::min(m.q_nrows(),m.q_ncols())),  	  start_ptr(m.elements),  	  stride(m.q_nrows()+1),  	  end_ptr(m.elements+m.nelems){  assert( stride > 1 );}/* *------------------------------------------------------------------------ * 	Collection-scalar arithmetics: walking with a stride */				// For every element, do `elem OP value`#define COMPUTED_VAL_ASSIGNMENT(OP,VALTYPE)				\									\void ElementWiseStride::operator OP (const VALTYPE val)			\{									\  for(register REAL * ep = start_ptr; ep < end_ptr; ep += stride)	\    *ep OP val;								\}									\COMPUTED_VAL_ASSIGNMENT(=,REAL)COMPUTED_VAL_ASSIGNMENT(+=,double)COMPUTED_VAL_ASSIGNMENT(-=,double)COMPUTED_VAL_ASSIGNMENT(*=,double)#undef COMPUTED_VAL_ASSIGNMENT				// is "element OP val" true for all				// elements in the collection?#define COMPARISON_WITH_SCALAR(OP)					\									\bool ElementWiseStrideConst::operator OP (const REAL val) const		\{									\  for(register const REAL * ep = start_ptr; ep < end_ptr; ep += stride)	\    if( !(*ep OP val) )							\      return false;							\									\  return true;								\}									\COMPARISON_WITH_SCALAR(==)COMPARISON_WITH_SCALAR(!=)COMPARISON_WITH_SCALAR(<)COMPARISON_WITH_SCALAR(<=)COMPARISON_WITH_SCALAR(>)COMPARISON_WITH_SCALAR(>=)#undef COMPARISON_WITH_SCALAR/* *------------------------------------------------------------------------ *	Apply algebraic functions to all elements of a collection */				// Take an absolute value of a matrixvoid ElementWiseStride::abs(void){  for(register REAL * ep = start_ptr; ep < end_ptr; ep += stride)    *ep = ::abs(*ep);}				// Square each elementvoid ElementWiseStride::sqr(void){  for(register REAL * ep = start_ptr; ep < end_ptr; ep += stride )    *ep = *ep * *ep;}				// Take the square root of all the elementsvoid ElementWiseStride::sqrt(void){  for(register REAL * ep = start_ptr; ep < end_ptr; ep += stride )    if( *ep >= 0 )      *ep = ::sqrt(*ep);    else      _error("%d-th element, %g, is negative. Can't take the square root",	     (ep-start_ptr), *ep );}/* *------------------------------------------------------------------------ * 		Element-wise operations on two groups of elements */				// For every element, do `elem OP another.elem`#define TWO_GROUP_COMP(OP)					\									\bool ElementWiseStrideConst::operator OP (const ElementWiseStrideConst& another) const \{									\  register const REAL * sp = another.start_ptr;				\  register const REAL * tp = start_ptr;					\  for(; tp < end_ptr && sp < another.end_ptr;				\      tp += stride, sp += another.stride)				\    if( !(*tp OP *sp) )							\      return false;							\									\  assure( tp >= end_ptr && sp >= another.end_ptr,			\    "stride collections have different number of elements" );		\  return true;								\}									\TWO_GROUP_COMP(==)TWO_GROUP_COMP(!=)TWO_GROUP_COMP(<)TWO_GROUP_COMP(<=)TWO_GROUP_COMP(>)TWO_GROUP_COMP(>=)#undef TWO_GROUP_COMP				// For every element, do `elem OP another.elem`#define TWO_GROUP_OP(OP)					\									\void ElementWiseStride::operator OP (const ElementWiseStrideConst& another) \{									\  register const REAL * sp = another.start_ptr;				\  register REAL * tp = start_ptr; 					\  for(; tp < end_ptr && sp < another.end_ptr;				\      tp += stride, sp += another.stride)				\    *tp OP *sp;								\  assure( tp >= end_ptr && sp >= another.end_ptr,			\    "stride collections have different number of elements" );		\}									\TWO_GROUP_OP(=)TWO_GROUP_OP(+=)TWO_GROUP_OP(-=)TWO_GROUP_OP(*=)TWO_GROUP_OP(/=)#undef TWO_GROUP_OP/* *------------------------------------------------------------------------ *	Reduce a collection or a difference between two collections *		to a single number: a "norm" */#define REDUCE_SUM(X,VAL) X += (VAL)#define REDUCE_SUMSQ(X,VAL) X += sqr(VAL)#define REDUCE_SUMABS(X,VAL) X += ::abs(VAL)#define REDUCE_MAXABS(X,VAL) X = ::max((REAL)X,::abs(VAL))#define REDUCE_ONE(NAME,OP)							\									\double ElementWiseStrideConst::NAME (void) const			\{									\  register double norm = 0;						\  for(register const REAL * ep = start_ptr; ep < end_ptr; ep += stride)	\    OP(norm,*ep);							\  return norm;								\}									\REDUCE_ONE(sum,REDUCE_SUM)REDUCE_ONE(sum_squares,REDUCE_SUMSQ)REDUCE_ONE(sum_abs,REDUCE_SUMABS)REDUCE_ONE(max_abs,REDUCE_MAXABS)#undef REDUCE_ONE#define REDUCE_DIFF_OF_TWO(NAME,OP)					\									\double ElementWiseStrideConst::NAME (const ElementWiseStrideConst& another) const	\{									\  register double norm = 0;						\  register const REAL * sp = another.start_ptr;				\  register const REAL * tp = start_ptr; 				\  for(; tp < end_ptr && sp < another.end_ptr;				\      tp += stride, sp += another.stride)				\    OP(norm,*tp - *sp);							\									\  assure( tp >= end_ptr && sp >= another.end_ptr,			\    "stride collections have different number of elements" );		\  return norm;								\}									\REDUCE_DIFF_OF_TWO(sum_squares,REDUCE_SUMSQ)REDUCE_DIFF_OF_TWO(sum_abs,REDUCE_SUMABS)REDUCE_DIFF_OF_TWO(max_abs,REDUCE_MAXABS)#undef REDUCE_DIFF_OF_TWO#undef REDUCE_SUM#undef REDUCE_SUMSQ#undef REDUCE_SUMABS#undef REDUCE_MAXABS/* *------------------------------------------------------------------------ *		   Multiplications with the diagonal matrix */				// Multiply a matrix by the diagonal				// of another matrix				// matrix(i,j) *= diag(j)Matrix& operator *= (Matrix& m, const ConstMatrixDiag& diag){  LAStreamOut m_str(m);  LAStrideStreamIn diag_str(diag);  if( m.q_ncols() != diag.q_nrows() )    m.info(), cerr << "\n and the diagonal " << diag << endl,   _error("cannot be multiplied");  			// Each column of m gets multiplied by the corresponding  			// diag(i). Note that m is traversed column-wise  while( !diag_str.eof() )  {    const REAL diag_el = diag_str.get();    for(register int i=0; i<m.q_nrows(); i++)      m_str.get() *= diag_el;  }  assert( m_str.eof() );  return m;}

⌨️ 快捷键说明

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