10c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org/*
20c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
30c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org *
40c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org *  Use of this source code is governed by a BSD-style license
50c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org *  that can be found in the LICENSE file in the root of the source
60c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org *  tree. An additional intellectual property rights grant can be found
70c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org *  in the file PATENTS.  All contributing project authors may
80c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
90c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org */
100c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
110c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_MATRIX_H_
120c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#define WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_MATRIX_H_
130c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
140c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#include <algorithm>
15dfa36058c945cf2ef9932a566987f648c24fa632Michael Graczyk#include <cstring>
160c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#include <string>
170c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#include <vector>
180c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
190c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#include "webrtc/base/checks.h"
200c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#include "webrtc/base/constructormagic.h"
2100b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h"
220c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
230c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgnamespace {
240c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
250c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// Wrappers to get around the compiler warning resulting from the fact that
260c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// there's no std::sqrt overload for ints. We cast all non-complex types to
270c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// a double for the sqrt method.
280c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgtemplate <typename T>
290c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgT sqrt_wrapper(T x) {
300c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  return sqrt(static_cast<double>(x));
310c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org}
320c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
330c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgtemplate <typename S>
340c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgstd::complex<S> sqrt_wrapper(std::complex<S> x) {
350c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  return sqrt(x);
360c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org}
370c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org} // namespace
380c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
390c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgnamespace webrtc {
400c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
410c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// Matrix is a class for doing standard matrix operations on 2 dimensional
420c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// matrices of any size. Results of matrix operations are stored in the
430c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// calling object. Function overloads exist for both in-place (the calling
440c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// object is used as both an operand and the result) and out-of-place (all
450c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// operands are passed in as parameters) operations. If operand dimensions
460c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// mismatch, the program crashes. Out-of-place operations change the size of
470c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// the calling object, if necessary, before operating.
480c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org//
490c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// 'In-place' operations that inherently change the size of the matrix (eg.
500c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// Transpose, Multiply on different-sized matrices) must make temporary copies
510c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// (|scratch_elements_| and |scratch_data_|) of existing data to complete the
520c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// operations.
530c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org//
540c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// The data is stored contiguously. Data can be accessed internally as a flat
550c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// array, |data_|, or as an array of row pointers, |elements_|, but is
560c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// available to users only as an array of row pointers through |elements()|.
570c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// Memory for storage is allocated when a matrix is resized only if the new
580c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// size overflows capacity. Memory needed temporarily for any operations is
590c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// similarly resized only if the new size overflows capacity.
600c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org//
610c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// If you pass in storage through the ctor, that storage is copied into the
620c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// matrix. TODO(claguna): albeit tricky, allow for data to be referenced
630c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org// instead of copied, and owned by the user.
640c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgtemplate <typename T>
650c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.orgclass Matrix {
660c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org public:
670c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix() : num_rows_(0), num_columns_(0) {}
680c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
690c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Allocates space for the elements and initializes all values to zero.
706955870806624479723addfae6dcf5d13968796cPeter Kasting  Matrix(size_t num_rows, size_t num_columns)
710c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      : num_rows_(num_rows), num_columns_(num_columns) {
720c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    Resize();
730c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    scratch_data_.resize(num_rows_ * num_columns_);
740c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    scratch_elements_.resize(num_rows_);
750c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
760c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
770c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Copies |data| into the new Matrix.
786955870806624479723addfae6dcf5d13968796cPeter Kasting  Matrix(const T* data, size_t num_rows, size_t num_columns)
79661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org      : num_rows_(0), num_columns_(0) {
800c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(data, num_rows, num_columns);
810c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    scratch_data_.resize(num_rows_ * num_columns_);
820c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    scratch_elements_.resize(num_rows_);
830c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
840c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
850c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  virtual ~Matrix() {}
860c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
870c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Deep copy an existing matrix.
880c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  void CopyFrom(const Matrix& other) {
890c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(&other.data_[0], other.num_rows_, other.num_columns_);
900c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
910c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
920c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Copy |data| into the Matrix. The current data is lost.
936955870806624479723addfae6dcf5d13968796cPeter Kasting  void CopyFrom(const T* const data, size_t num_rows, size_t num_columns) {
94661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org    Resize(num_rows, num_columns);
95661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org    memcpy(&data_[0], data, num_rows_ * num_columns_ * sizeof(data_[0]));
960c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
970c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
98dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  Matrix& CopyFromColumn(const T* const* src,
99dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                         size_t column_index,
1006955870806624479723addfae6dcf5d13968796cPeter Kasting                         size_t num_rows) {
1010c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    Resize(1, num_rows);
1026955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < num_columns_; ++i) {
1030c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] = src[i][column_index];
1040c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
1050c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1060c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
1070c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1080c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1096955870806624479723addfae6dcf5d13968796cPeter Kasting  void Resize(size_t num_rows, size_t num_columns) {
110661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org    if (num_rows != num_rows_ || num_columns != num_columns_) {
111661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org      num_rows_ = num_rows;
112661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org      num_columns_ = num_columns;
113661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org      Resize();
114661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org    }
1150c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1160c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1170c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Accessors and mutators.
1186955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t num_rows() const { return num_rows_; }
1196955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t num_columns() const { return num_columns_; }
1200c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  T* const* elements() { return &elements_[0]; }
1210c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  const T* const* elements() const { return &elements_[0]; }
1220c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1230c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  T Trace() {
12491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_rows_, num_columns_);
1250c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1260c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    T trace = 0;
1276955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < num_rows_; ++i) {
1280c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      trace += elements_[i][i];
1290c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
1300c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return trace;
1310c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1320c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1330c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Matrix Operations. Returns *this to support method chaining.
1340c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Transpose() {
1350c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyDataToScratch();
136661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org    Resize(num_columns_, num_rows_);
1370c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return Transpose(scratch_elements());
1380c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1390c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1400c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Transpose(const Matrix& operand) {
14191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(operand.num_rows_, num_columns_);
14291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(operand.num_columns_, num_rows_);
1430c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1440c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return Transpose(operand.elements());
1450c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1460c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1470c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  template <typename S>
1480c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Scale(const S& scalar) {
1490c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
1500c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] *= scalar;
1510c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
1520c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1530c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
1540c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1550c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1560c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  template <typename S>
1570c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Scale(const Matrix& operand, const S& scalar) {
1580c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(operand);
1590c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return Scale(scalar);
1600c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1610c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1620c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Add(const Matrix& operand) {
16391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_rows_, operand.num_rows_);
16491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_columns_, operand.num_columns_);
1650c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1660c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
1670c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] += operand.data_[i];
1680c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
1690c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1700c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
1710c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1720c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1730c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Add(const Matrix& lhs, const Matrix& rhs) {
1740c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(lhs);
1750c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return Add(rhs);
1760c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1770c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1780c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Subtract(const Matrix& operand) {
17991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_rows_, operand.num_rows_);
18091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_columns_, operand.num_columns_);
1810c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1820c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
1830c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] -= operand.data_[i];
1840c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
1850c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1860c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
1870c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1880c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1890c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Subtract(const Matrix& lhs, const Matrix& rhs) {
1900c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(lhs);
1910c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return Subtract(rhs);
1920c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
1930c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1940c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseMultiply(const Matrix& operand) {
19591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_rows_, operand.num_rows_);
19691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_columns_, operand.num_columns_);
1970c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
1980c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
1990c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] *= operand.data_[i];
2000c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
2010c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2020c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
2030c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2040c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2050c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseMultiply(const Matrix& lhs, const Matrix& rhs) {
2060c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(lhs);
2070c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return PointwiseMultiply(rhs);
2080c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2090c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2100c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseDivide(const Matrix& operand) {
21191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_rows_, operand.num_rows_);
21291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_columns_, operand.num_columns_);
2130c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2140c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
2150c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] /= operand.data_[i];
2160c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
2170c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2180c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
2190c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2200c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2210c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseDivide(const Matrix& lhs, const Matrix& rhs) {
2220c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(lhs);
2230c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return PointwiseDivide(rhs);
2240c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2250c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2260c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseSquareRoot() {
2270c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
2280c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] = sqrt_wrapper(data_[i]);
2290c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
2300c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2310c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
2320c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2330c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2340c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseSquareRoot(const Matrix& operand) {
2350c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(operand);
2360c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return PointwiseSquareRoot();
2370c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2380c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2390c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseAbsoluteValue() {
2400c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
2410c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] = abs(data_[i]);
2420c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
2430c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2440c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
2450c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2460c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2470c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseAbsoluteValue(const Matrix& operand) {
2480c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(operand);
2490c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return PointwiseAbsoluteValue();
2500c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2510c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2520c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseSquare() {
2530c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    for (size_t i = 0; i < data_.size(); ++i) {
2540c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      data_[i] *= data_[i];
2550c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
2560c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2570c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
2580c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2590c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2600c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& PointwiseSquare(const Matrix& operand) {
2610c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyFrom(operand);
2620c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return PointwiseSquare();
2630c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2640c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2650c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Multiply(const Matrix& lhs, const Matrix& rhs) {
26691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(lhs.num_columns_, rhs.num_rows_);
26791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_rows_, lhs.num_rows_);
26891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_columns_, rhs.num_columns_);
2690c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2700c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return Multiply(lhs.elements(), rhs.num_rows_, rhs.elements());
2710c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2720c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2730c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Multiply(const Matrix& rhs) {
27491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_EQ(num_columns_, rhs.num_rows_);
2750c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2760c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    CopyDataToScratch();
277661af50dd55a2beb488d4995ed21c5ffd53f8eddaluebs@webrtc.org    Resize(num_rows_, rhs.num_columns_);
2780c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return Multiply(scratch_elements(), rhs.num_rows_, rhs.elements());
2790c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2800c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2810c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  std::string ToString() const {
2820c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    std::ostringstream ss;
2830c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    ss << std::endl << "Matrix" << std::endl;
2840c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2856955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < num_rows_; ++i) {
2866955870806624479723addfae6dcf5d13968796cPeter Kasting      for (size_t j = 0; j < num_columns_; ++j) {
2870c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org        ss << elements_[i][j] << " ";
2880c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      }
2890c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      ss << std::endl;
2900c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
2910c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    ss << std::endl;
2920c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2930c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return ss.str();
2940c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
2950c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
2960c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org protected:
2976955870806624479723addfae6dcf5d13968796cPeter Kasting  void SetNumRows(const size_t num_rows) { num_rows_ = num_rows; }
2986955870806624479723addfae6dcf5d13968796cPeter Kasting  void SetNumColumns(const size_t num_columns) { num_columns_ = num_columns; }
2990c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  T* data() { return &data_[0]; }
3000c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  const T* data() const { return &data_[0]; }
3010c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  const T* const* scratch_elements() const { return &scratch_elements_[0]; }
3020c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3030c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Resize the matrix. If an increase in capacity is required, the current
3040c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // data is lost.
3050c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  void Resize() {
3060c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    size_t size = num_rows_ * num_columns_;
3070c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    data_.resize(size);
3080c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    elements_.resize(num_rows_);
3090c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3106955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < num_rows_; ++i) {
3110c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      elements_[i] = &data_[i * num_columns_];
3120c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
3130c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
3140c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3150c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Copies data_ into scratch_data_ and updates scratch_elements_ accordingly.
3160c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  void CopyDataToScratch() {
3170c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    scratch_data_ = data_;
3180c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    scratch_elements_.resize(num_rows_);
3190c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3206955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < num_rows_; ++i) {
3210c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      scratch_elements_[i] = &scratch_data_[i * num_columns_];
3220c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
3230c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
3240c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3250c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org private:
3266955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t num_rows_;
3276955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t num_columns_;
3280c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  std::vector<T> data_;
3290c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  std::vector<T*> elements_;
3300c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3310c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Stores temporary copies of |data_| and |elements_| for in-place operations
3320c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // where referring to original data is necessary.
3330c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  std::vector<T> scratch_data_;
3340c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  std::vector<T*> scratch_elements_;
3350c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3360c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // Helpers for Transpose and Multiply operations that unify in-place and
3370c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  // out-of-place solutions.
3380c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  Matrix& Transpose(const T* const* src) {
3396955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t i = 0; i < num_rows_; ++i) {
3406955870806624479723addfae6dcf5d13968796cPeter Kasting      for (size_t j = 0; j < num_columns_; ++j) {
3410c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org        elements_[i][j] = src[j][i];
3420c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      }
3430c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
3440c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3450c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
3460c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
3470c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3486955870806624479723addfae6dcf5d13968796cPeter Kasting  Matrix& Multiply(const T* const* lhs,
3496955870806624479723addfae6dcf5d13968796cPeter Kasting                   size_t num_rows_rhs,
3506955870806624479723addfae6dcf5d13968796cPeter Kasting                   const T* const* rhs) {
3516955870806624479723addfae6dcf5d13968796cPeter Kasting    for (size_t row = 0; row < num_rows_; ++row) {
3526955870806624479723addfae6dcf5d13968796cPeter Kasting      for (size_t col = 0; col < num_columns_; ++col) {
3530c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org        T cur_element = 0;
3546955870806624479723addfae6dcf5d13968796cPeter Kasting        for (size_t i = 0; i < num_rows_rhs; ++i) {
3550c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org          cur_element += lhs[row][i] * rhs[i][col];
3560c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org        }
3570c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3580c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org        elements_[row][col] = cur_element;
3590c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org      }
3600c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    }
3610c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3620c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org    return *this;
3630c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org  }
3640c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3653c089d751ede283e21e186885eaf705c3257ccd2henrikg  RTC_DISALLOW_COPY_AND_ASSIGN(Matrix);
3660c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org};
3670c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3680c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org}  // namespace webrtc
3690c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org
3700c39e91cc827f222ab227bad09cf9199163d28f8aluebs@webrtc.org#endif  // WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_MATRIX_H_
371