1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-06 14:52:34 +02:00
audacity/src/Matrix.cpp
James Crook 657159d542 Fix C4189 and C4100 Warnings
C4189 is 'Local variable initialised but not used'
C4100 is 'Unreferenced parameter'

Fixed some other warnings, e.g. about empty if, too.
2018-10-10 19:46:24 +01:00

346 lines
7.9 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
Matrix.cpp
Dominic Mazzoni
**********************************************************************/
#include <stdlib.h>
#include <math.h>
#include <wx/defs.h>
#include "Matrix.h"
Vector::Vector()
{
}
Vector::Vector(unsigned len, double *data)
: mN{ len }
, mData(len)
{
if (data)
std::copy(data, data + len, mData.get());
else
std::fill(mData.get(), mData.get() + len, 0.0);
}
Vector::Vector(unsigned len, float *data)
: mN{ len }
, mData{ len }
{
if (data)
std::copy(data, data + len, mData.get());
else
std::fill(mData.get(), mData.get() + len, 0.0);
}
Vector& Vector::operator=(const Vector &other)
{
wxASSERT(Len() == other.Len());
std::copy(other.mData.get(), other.mData.get() + mN, mData.get());
return *this;
}
Vector::Vector(const Vector &other)
: mN{ other.Len() }
, mData{ mN }
{
std::copy(other.mData.get(), other.mData.get() + mN, mData.get());
}
Vector::~Vector()
{
}
void Vector::Reinit(unsigned len)
{
Vector temp(len);
Swap(temp);
}
void Vector::Swap(Vector &that)
{
std::swap(mN, that.mN);
mData.swap(that.mData);
}
double Vector::Sum() const
{
double sum = 0.0;
for(unsigned i = 0; i < Len(); i++)
sum += mData[i];
return sum;
}
Matrix::Matrix(unsigned rows, unsigned cols, double **data)
: mRows{ rows }
, mCols{ cols }
, mRowVec{ mRows }
{
for(unsigned i = 0; i < mRows; i++) {
mRowVec[i].Reinit( mCols );
for(unsigned j = 0; j < mCols; j++) {
if (data)
(*this)[i][j] = data[i][j];
else
(*this)[i][j] = 0.0;
}
}
}
Matrix& Matrix::operator=(const Matrix &other)
{
CopyFrom(other);
return *this;
}
Matrix::Matrix(const Matrix &other)
{
CopyFrom(other);
}
void Matrix::CopyFrom(const Matrix &other)
{
mRows = other.mRows;
mCols = other.mCols;
mRowVec.reinit(mRows);
for (unsigned i = 0; i < mRows; i++) {
mRowVec[i].Reinit( mCols );
mRowVec[i] = other.mRowVec[i];
}
}
Matrix::~Matrix()
{
}
void Matrix::SwapRows(unsigned i, unsigned j)
{
mRowVec[i].Swap(mRowVec[j]);
}
Matrix IdentityMatrix(unsigned N)
{
Matrix M(N, N);
for(unsigned i = 0; i < N; i++)
M[i][i] = 1.0;
return M;
}
Vector operator+(const Vector &left, const Vector &right)
{
wxASSERT(left.Len() == right.Len());
Vector v(left.Len());
for(unsigned i = 0; i < left.Len(); i++)
v[i] = left[i] + right[i];
return v;
}
Vector operator-(const Vector &left, const Vector &right)
{
wxASSERT(left.Len() == right.Len());
Vector v(left.Len());
for(unsigned i = 0; i < left.Len(); i++)
v[i] = left[i] - right[i];
return v;
}
Vector operator*(const Vector &left, const Vector &right)
{
wxASSERT(left.Len() == right.Len());
Vector v(left.Len());
for(unsigned i = 0; i < left.Len(); i++)
v[i] = left[i] * right[i];
return v;
}
Vector operator*(const Vector &left, double right)
{
Vector v(left.Len());
for(unsigned i = 0; i < left.Len(); i++)
v[i] = left[i] * right;
return v;
}
Vector VectorSubset(const Vector &other, unsigned start, unsigned len)
{
Vector v(len);
for(unsigned i = 0; i < len; i++)
v[i] = other[start+i];
return v;
}
Vector VectorConcatenate(const Vector& left, const Vector& right)
{
Vector v(left.Len() + right.Len());
for(unsigned i = 0; i < left.Len(); i++)
v[i] = left[i];
for(unsigned i = 0; i < right.Len(); i++)
v[i + left.Len()] = right[i];
return v;
}
Vector operator*(const Vector &left, const Matrix &right)
{
wxASSERT(left.Len() == right.Rows());
Vector v(right.Cols());
for(unsigned i = 0; i < right.Cols(); i++) {
v[i] = 0.0;
for(unsigned j = 0; j < right.Rows(); j++)
v[i] += left[j] * right[j][i];
}
return v;
}
Vector operator*(const Matrix &left, const Vector &right)
{
wxASSERT(left.Cols() == right.Len());
Vector v(left.Rows());
for(unsigned i = 0; i < left.Rows(); i++) {
v[i] = 0.0;
for(unsigned j = 0; j < left.Cols(); j++)
v[i] += left[i][j] * right[j];
}
return v;
}
Matrix operator+(const Matrix &left, const Matrix &right)
{
wxASSERT(left.Rows() == right.Rows());
wxASSERT(left.Cols() == right.Cols());
Matrix M(left.Rows(), left.Cols());
for(unsigned i = 0; i < left.Rows(); i++)
for(unsigned j = 0; j < left.Cols(); j++)
M[i][j] = left[i][j] + right[i][j];
return M;
}
Matrix operator*(const Matrix &left, const double right)
{
Matrix M(left.Rows(), left.Cols());
for(unsigned i = 0; i < left.Rows(); i++)
for(unsigned j = 0; j < left.Cols(); j++)
M[i][j] = left[i][j] * right;
return M;
}
Matrix ScalarMultiply(const Matrix &left, const Matrix &right)
{
wxASSERT(left.Rows() == right.Rows());
wxASSERT(left.Cols() == right.Cols());
Matrix M(left.Rows(), left.Cols());
for(unsigned i = 0; i < left.Rows(); i++)
for(unsigned j = 0; j < left.Cols(); j++)
M[i][j] = left[i][j] * right[i][j];
return M;
}
Matrix MatrixMultiply(const Matrix &left, const Matrix &right)
{
wxASSERT(left.Cols() == right.Rows());
Matrix M(left.Rows(), right.Cols());
for(unsigned i = 0; i < left.Rows(); i++)
for(unsigned j = 0; j < right.Cols(); j++) {
M[i][j] = 0.0;
for(unsigned k = 0; k < left.Cols(); k++)
M[i][j] += left[i][k] * right[k][j];
}
return M;
}
Matrix MatrixSubset(const Matrix &input,
unsigned startRow, unsigned numRows,
unsigned startCol, unsigned numCols)
{
Matrix M(numRows, numCols);
for(unsigned i = 0; i < numRows; i++)
for(unsigned j = 0; j < numCols; j++)
M[i][j] = input[startRow+i][startCol+j];
return M;
}
Matrix MatrixConcatenateCols(const Matrix& left, const Matrix& right)
{
wxASSERT(left.Rows() == right.Rows());
Matrix M(left.Rows(), left.Cols() + right.Cols());
for(unsigned i = 0; i < left.Rows(); i++) {
for(unsigned j = 0; j < left.Cols(); j++)
M[i][j] = left[i][j];
for(unsigned j = 0; j < right.Cols(); j++)
M[i][j+left.Cols()] = right[i][j];
}
return M;
}
Matrix TransposeMatrix(const Matrix& other)
{
Matrix M(other.Cols(), other.Rows());
for(unsigned i = 0; i < other.Rows(); i++)
for(unsigned j = 0; j < other.Cols(); j++)
M[j][i] = other[i][j];
return M;
}
bool InvertMatrix(const Matrix& input, Matrix& Minv)
{
// Very straightforward implementation of
// Gauss-Jordan elimination to invert a matrix.
// Returns true if successful
wxASSERT(input.Rows() == input.Cols());
auto N = input.Rows();
Matrix M = input;
Minv = IdentityMatrix(N);
// Do the elimination one column at a time
for(unsigned i = 0; i < N; i++) {
// Pivot the row with the largest absolute value in
// column i, into row i
double absmax = 0.0;
unsigned int argmax = 0;
for(unsigned j = i; j < N; j++)
if (fabs(M[j][i]) > absmax) {
absmax = fabs(M[j][i]);
argmax = j;
}
// If no row has a nonzero value in that column,
// the matrix is singular and we have to give up.
if (absmax == 0)
return false;
if (i != argmax) {
M.SwapRows(i, argmax);
Minv.SwapRows(i, argmax);
}
// Divide this row by the value of M[i][i]
double factor = 1.0 / M[i][i];
M[i] = M[i] * factor;
Minv[i] = Minv[i] * factor;
// Eliminate the rest of the column
for(unsigned j = 0; j < N; j++) {
if (j == i)
continue;
if (fabs(M[j][i]) > 0) {
// Subtract a multiple of row i from row j
factor = M[j][i];
for(unsigned k = 0; k < N; k++) {
M[j][k] -= (M[i][k] * factor);
Minv[j][k] -= (Minv[i][k] * factor);
}
}
}
}
return true;
}