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

📄 matlibstdtoolbox.cpp

📁 Dream.exe soft source (Visual C++)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************\
 * Copyright (c) 2001
 *
 * Author(s):
 *	Volker Fischer
 *
 * Description:
 *	c++ Mathematic Library (Matlib)
 *
 ******************************************************************************
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
\******************************************************************************/

#include "MatlibStdToolbox.h"


/* Implementation *************************************************************/
CReal Min(const CMatlibVector<CReal>& rvI)
{
	const int iSize = rvI.GetSize();
	CReal rMinRet = rvI[0];
	for (int i = 1; i < iSize; i++)
	{
		if (rvI[i] < rMinRet)
			rMinRet = rvI[i];
	}

	return rMinRet;
}

void Min(CReal& rMinVal, int& iMinInd, const CMatlibVector<CReal>& rvI)
{
	const int iSize = rvI.GetSize();
	rMinVal = rvI[0]; /* Init actual minimum value */
	iMinInd = 0; /* Init index of minimum */
	for (int i = 1; i < iSize; i++)
	{
		if (rvI[i] < rMinVal)
		{
			rMinVal = rvI[i];
			iMinInd = i;
		}
	}
}

CReal Max(const CMatlibVector<CReal>& rvI)
{
	CReal rMaxRet;
	int iMaxInd; /* Not used by this function */
	Max(rMaxRet, iMaxInd, rvI);

	return rMaxRet;
}

void Max(CReal& rMaxVal, int& iMaxInd, const CMatlibVector<CReal>& rvI)
{
	const int iSize = rvI.GetSize();
	rMaxVal = rvI[0]; /* Init actual maximum value */
	iMaxInd = 0; /* Init index of maximum */
	for (int i = 1; i < iSize; i++)
	{
		if (rvI[i] > rMaxVal)
		{
			rMaxVal = rvI[i];
			iMaxInd = i;
		}
	}
}

CMatlibVector<CReal> Sort(const CMatlibVector<CReal>& rvI)
{
	const int iSize = rvI.GetSize();
	const int iEnd = iSize - 1;
	CMatlibVector<CReal> fvRet(iSize, VTY_TEMP);

	/* Copy input vector in output vector */
	fvRet = rvI;

	/* Loop through the array one less than its total cell count */
	for (int i = 0; i < iEnd; i++)
	{
		/* Loop through every cell (value) in array */
		for (int j = 0; j < iEnd; j++)
		{
			/* Compare the values and switch if necessary */
			if (fvRet[j] > fvRet[j + 1])
			{
				const CReal rSwap = fvRet[j];
				fvRet[j] = fvRet[j + 1];
				fvRet[j + 1] = rSwap;
			}
		}
	}

	return fvRet;
}

CMatlibMatrix<CReal> Eye(const int iLen)
{
	CMatlibMatrix<CReal> matrRet(iLen, iLen, VTY_TEMP);

	/* Set all values except of the diagonal to zero, diagonal entries = 1 */
	for (int i = 0; i < iLen; i++)
	{
		for (int j = 0; j < iLen; j++)
		{
			if (i == j)
				matrRet[i][j] = (CReal) 1.0;
			else
				matrRet[i][j] = (CReal) 0.0;
		}
	}

	return matrRet;
}

CMatlibMatrix<CComplex> Diag(const CMatlibVector<CComplex>& cvI)
{
	const int iSize = cvI.GetSize();
	CMatlibMatrix<CComplex> matcRet(iSize, iSize, VTY_TEMP);

	/* Set the diagonal to the values of the input vector */
	for (int i = 0; i < iSize; i++)
	{
		for (int j = 0; j < iSize; j++)
		{
			if (i == j)
				matcRet[i][j] = cvI[i];
			else
				matcRet[i][j] = (CReal) 0.0;
		}
	}

	return matcRet;
}

CReal Trace(const CMatlibMatrix<CReal>& rmI)
{
	const int iSize = rmI.GetRowSize(); /* matrix must be square */
	CReal rReturn = (CReal) 0.0;

	for (int i = 0; i < iSize; i++)
		rReturn += rmI[i][i];

	return rReturn;
}

CMatlibMatrix<CComplex> Transp(const CMatlibMatrix<CComplex>& cmI)
{
	const int iRowSize = cmI.GetRowSize();
	const int iColSize = cmI.GetColSize();

	/* Swaped row and column size due to transpose operation */
	CMatlibMatrix<CComplex> matcRet(iColSize, iRowSize, VTY_TEMP);

	/* Transpose matrix */
	for (int i = 0; i < iRowSize; i++)
	{
		for (int j = 0; j < iColSize; j++)
			matcRet[j][i] = cmI[i][j];
	}

	return matcRet;
}

CMatlibMatrix<CComplex> Inv(const CMatlibMatrix<CComplex>& matrI)
{
/*
	Parts of the following code are taken from Ptolemy
	(http://ptolemy.eecs.berkeley.edu/)

	The input matrix must be square, this is NOT checked here!
*/
	_COMPLEX	temp;
	int			row, col, i;

	const int iSize = matrI.GetColSize();
	CMatlibMatrix<CComplex> matrRet(iSize, iSize, VTY_TEMP);

	/* Make a working copy of input matrix */
	CMatlibMatrix<CComplex> work(matrI);

	/* Set result to be the identity matrix */
	matrRet = Eye(iSize);

	for (i = 0; i < iSize; i++) 
	{
		/* Check that the element in (i,i) is not zero */
		if ((Real(work[i][i]) == 0) && (Imag(work[i][i]) == 0))
		{
			/* Swap with a row below this one that has a non-zero element
			   in the same column */
			for (row = i + 1; row < iSize; row++)
			{
				if ((Real(work[i][i]) != 0) || (Imag(work[i][i]) != 0))
					break;
			}

// TEST
if (row == iSize)
{
printf("couldn't invert matrix, possibly singular.\n");
	matrRet = Eye(iSize);
	return matrRet;
}

			/* Swap rows */
			for (col = 0; col < iSize; col++)
			{
				temp = work[i][col];
				work[i][col] = work[row][col];
				work[row][col] = temp;
				temp = matrRet[i][col];
				matrRet[i][col] = matrRet[row][col];
				matrRet[row][col] = temp;
			}
		}

		/* Divide every element in the row by element (i,i) */
		temp = work[i][i];
		for (col = 0; col < iSize; col++)
		{
			work[i][col] /= temp;
			matrRet[i][col] /= temp;
		}

		/* Zero out the rest of column i */
		for (row = 0; row < iSize; row++)
		{
			if (row != i)
			{
				temp = work[row][i];
				for (col = iSize - 1; col >= 0; col--)
				{
					work[row][col] -= (temp * work[i][col]);
					matrRet[row][col] -= (temp * matrRet[i][col]);
				}
			}
		}
	}

	return matrRet;
}

/* This function is not listed in the header file. It shall be used only for
   Matlib internal calculations */
CComplex _integral(MATLIB_CALLBACK_QAUD f, const CReal a, const CReal b,
				   const CReal errorBound, CReal& integralBound,
				   _BOOLEAN& integralError, const CReal ru)
{
/*
	The following code (inclusive the actual Quad() function) is based on a
	JavaScript Example written by Lucio Tavernini. The code is hosted at
	http://tavernini.com/integral.shtml.

	Description: Adaptive Simpson's Quadrature

	_integral(f, a, b, errorBound) attempts to integrate f from
	a to b while keeping the asymptotic error estimate below
	errorBound using an adaptive implementation of Simpson's rule.

	Notes: Instead of NaN we use _MAXREAL. Infinite bounds are not allowed! The
	lower bound must always be smaller than the higher bound!
*/

	CReal		left, right, h, h6, bound;
	CComplex	fa, fb, v1, v2, error, value;
	int			m1, jend, mstart, j;

	if (integralError)
		return _MAXREAL; /* NaN */

	/* Integrate over [a,b]. Initialize */
	const int max = 1024;
	CRealVector x(max);
	CComplexVector f1(max);
	CComplexVector f2(max);
	CComplexVector f3(max);
	CComplexVector v(max);

	int step = 1;
	int m = 1;
	bound = errorBound;
	value = 0;
	h = b - a;
	x[0] = a;
	f1[0] = f(a);
	f2[0] = f((CReal) 0.5 * (a + b));
	f3[0] = f(b);
	v[0] = h * (f1[0] + (CReal) 4.0 * f2[0] + f3[0]) / (CReal) 6.0;

	do
	{
		/* Are we going to go forward or backward? */
		if (step == -1)
		{
			/* Forward: j = m,...,max */
			step = 1;
			j = m + 1;
			jend = max;
			m = 0;
			mstart = 0;
		}
		else
		{
			/* Backward: j = m,...,1 */
			step = -1;
			j = m - 1;
			jend = -1;
			m = max - 1;
			mstart = max - 1;
		}
		
		h = (CReal) 0.5 * h;
		h6 = h / 6;
		bound = (CReal) 0.5 * bound;
		
		do
		{
			left = x[j];
			right = x[j] + (CReal) 0.5 * h;

			/* Complete loss of significance? */
			if (left >= right)
			{
				printf("integral: Error 1");
				return value;
			}

			fa = f(x[j] + (CReal) 0.5 * h);
			fb = f(x[j] + (CReal) 1.5 * h);
			v1 = h6 * (f1[j] + (CReal) 4.0 * fa + f2[j]);
			v2 = h6 * (f2[j] + (CReal) 4.0 * fb + f3[j]);
			error = (v[j] - v1 - v2) / (CReal) 15.0;

			if ((Abs(error) <= bound) || (Abs(v1 + v2) < Abs(value) * ru))
				value = ((v1 + v2) + value) - error;
			else
			{
				if (integralError)
					return _MAXREAL; /* NaN */
				
				/* Are we out of memory? */
				if (m == j)
				{
					left = x[j];
					right = x[j] + (CReal) 0.5 * h;

					/* Complete loss of significance? */
					if (left >= right)
					{
						printf("integral: Error 2");
						return value;
					}

					value += _integral(f, left, x[j] + 2 * h, bound,
						integralBound, integralError, ru);
				}
				else 
				{
					/* No, we are not */
					left = x[j];
					right = x[j] + (CReal) 0.125 * h;

⌨️ 快捷键说明

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