Square root of all elements of Boost Ublas Matrix - c++

I am trying to compute square root of all elements of a Boost Ublas matrix. So far, I have this, and it works.
#include <iostream>
#include "boost\numeric\ublas\matrix.hpp"
#include <Windows.h>
#include <math.h>
#include <cmath>
#include <algorithm>
typedef boost::numeric::ublas::matrix<float> matrix;
const size_t X_SIZE = 10;
const size_t Y_SIZE = 10;
void UblasExpr();
int main()
{
UblasExpr();
return 0;
}
void UblasExpr()
{
matrix m1, m2, m3;
m1.resize(X_SIZE, Y_SIZE);
m2.resize(X_SIZE, Y_SIZE);
m3.resize(X_SIZE, Y_SIZE);
for (int i = 0; i < X_SIZE; i++)
{
for (int j = 0; j < Y_SIZE; j++)
{
m1(i, j) = 2;
m2(i, j) = 10;
}
}
m3 = element_prod(m1, m2);
std::transform(m1.data().begin(), m1.data().end(), m3.data().begin(), std::sqrtf);
for (int i = 0; i < X_SIZE; i++)
{
for (int j = 0; j < Y_SIZE; j++)
{
std::cout << m3(i, j) << " ";
}
std::cout << std::endl;
}
}
But, I would like to not use the std::transform, and instead do something like this :
m3 = sqrtf(m1);
Is there a way to make it work? My application is very performance sensitive, so the alternative is only acceptable if it results in no loss of efficiency.
P.S. I would like to do this for a whole lot of other operations like log10f, cos, acos, sin, asin, pow. I need these all in my code.

You can define your own sqrt function with an appropriate signature:
typedef boost::numeric::ublas::matrix<float> matrix;
matrix sqrt_element(const matrix& a)
{
matrix result(a.size1(), a.size2());
std::transform(a.data().begin(), a.data().end(), result.data().begin(), std::sqrtf);
return result;
}
You could also define a general 'apply_elementwise' to take a callable object as an argument (untested/not compiled):
typedef boost::numeric::ublas::matrix<float> matrix;
template <typename CALLABLE>
matrix apply_elementwise(const CALLABLE& f, const matrix& a)
{
matrix result(a.size1(), a.size2());
std::transform(a.data().begin(), a.data().end(), result.data().begin(), f);
return result;
}
Then you could call this as:
matrix y(apply_elementwise(std::sqrt, x));
matrix z;
z = apply_elementwise(std::cos, x);
In these functions, we're returning a matrix by value. Ideally, you want to make sure you that the matrix class you're using employs rvalue-reference constructors and assignment operators to minimize copying of data.

Related

Operator Overloading Matrix Multiplication

The issue I am having is how to get the correct number columns to go through for the inner most loop of K.
An example is a 2x3 matrix and a 3x2 matrix being multiplied.
The result should be a 2x2 matrix, but currently I dont know how to send the value of 2 to the operator overloaded function.
It should be
int k = 0; k < columns of first matrix;k++
Matrix::Matrix(int row, int col)
{
rows = row;
cols = col;
cx = (float**)malloc(rows * sizeof(float*)); //initialize pointer to pointer matrix
for (int i = 0; i < rows; i++)
*(cx + i) = (float*)malloc(cols * sizeof(float));
}
Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < ?;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;
//calling
Matrix mult(rowA, colB);
mult = mat1 * mat2;
}
Linear algebra rules say the result should have dimensions rows x dx.cols
Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, dx.cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < cols;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;
A few random hints:
Your code is basically C; it doesn’t use (e.g.) important memory-safety features from C++. (Operator overloading is the only C++-like feature in use.) I suggest that you take advantage of C++ a bit more.
Strictly avoid malloc() in C++. Use std::make_unique(...) or, if there is no other way, a raw new operator. (BTW, there is always another way.) In the latter case, make sure there is a destructor with a delete or delete[]. The use of malloc() in your snippet smells like a memory leak.
What can be const should be const. Initialize as many class members as possible in the constructor’s initializer list and make them const if appropriate. (For example, Matrix dimensions don’t change and should be const.)
When writing a container-like class (which a Matrix may be, in a sense), don’t restrict it to a single data type; your future self will thank you. (What if you need a double instead of a float? Is it going to be a one-liner edit or an all-nighter spent searching where a forgotten float eats away your precision?)
Here’s a quick and dirty runnable example showing matrix multiplication:
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <memory>
namespace matrix {
using std::size_t;
template<typename Element>
class Matrix {
class Accessor {
public:
Accessor(const Matrix& mat, size_t m) : data_(&mat.data_[m * mat.n_]) {}
Element& operator [](size_t n) { return data_[n]; }
const Element& operator [](size_t n) const { return data_[n]; }
private:
Element *const data_;
};
public:
Matrix(size_t m, size_t n) : m_(m), n_(n),
data_(std::make_unique<Element[]>(m * n)) {}
Matrix(Matrix &&rv) : m_(rv.m_), n_(rv.n_), data_(std::move(rv.data_)) {}
Matrix operator *(const Matrix& right) {
Matrix result(m_, right.n_);
for (size_t i = 0; i < m_; ++i)
for (size_t j = 0; j < right.n_; ++j) {
result[i][j] = Element{};
for (size_t k = 0; k < n_; ++k) result[i][j] +=
(*this)[i][k] * right[k][j];
}
return result;
}
Accessor operator [](size_t m) { return Accessor(*this, m); }
const Accessor operator [](size_t m) const { return Accessor(*this, m); }
size_t m() const { return m_; }
size_t n() const { return n_; }
private:
const size_t m_;
const size_t n_;
std::unique_ptr<Element[]> data_;
};
template<typename Element>
std::ostream& operator <<(std::ostream &out, const Matrix<Element> &mat) {
for (size_t i = 0; i < mat.m(); ++i) {
for (size_t j = 0; j < mat.n(); ++j) out << std::setw(4) << mat[i][j];
out << std::endl;
}
return out;
}
} // namespace matrix
int main() {
matrix::Matrix<int> m22{2, 2};
m22[0][0] = 0; // TODO: std::initializer_list
m22[0][1] = 1;
m22[1][0] = 2;
m22[1][1] = 3;
matrix::Matrix<int> m23{2, 3};
m23[0][0] = 0; // TODO: std::initializer_list
m23[0][1] = 1;
m23[0][2] = 2;
m23[1][0] = 3;
m23[1][1] = 4;
m23[1][2] = 5;
matrix::Matrix<int> m32{3, 2};
m32[0][0] = 5; // TODO: std::initializer_list
m32[0][1] = 4;
m32[1][0] = 3;
m32[1][1] = 2;
m32[2][0] = 1;
m32[2][1] = 0;
std::cout << "Original:\n\n";
std::cout << m22 << std::endl << m23 << std::endl << m32 << std::endl;
std::cout << "Multiplied:\n\n";
std::cout << m22 * m22 << std::endl
<< m22 * m23 << std::endl
<< m32 * m22 << std::endl
<< m23 * m32 << std::endl
<< m32 * m23 << std::endl;
}
Possible improvements and other recommendations:
Add consistency checks. throw, for example, a std::invalid_argument when dimensions don’t match on multiplication, i.e. when m_ != right.n_, and a std::range_error when the operator [] gets an out-of-bounds argument. (The checks may be optional, activated (e.g.) for debugging using an if constexpr.)
Use a std::initializer_list or the like for initialization, so that you can have (e.g.) a const Matrix initialized in-line.
Always check your code using valgrind. (Tip: Buliding with -g lets valgrind print also the line numbers where something wrong happened (or where a relevant preceding (de)allocation had happened).)
The code could me made shorter and more elegant (not necessarily more efficient; compiler optimizations are magic nowadays) by not using operator [] everywhere and having some fun with pointer arithmetics instead.
Make the type system better, so that (e.g.) Matrix instances with different types can play well with each other. Perhaps a Matrix<int> multiplied by a Matrix<double> could yield a Matrix<double> etc. One could also support multiplication between a scalar value and a Matrix. Or between a Matrix and a std::array, std::vector etc.

Matrix multiplication (with different dimensions)

For Math class in school I need to create an application that does something (just anything) with matrices. I decided to create a matrix calculator. I have a Matrix class which contains a 2D array, an row integer and a column integer. I created the following function to multiply two matrices:
public: Matrix* multiply(Matrix* other)
{
Matrix* temp = new Matrix(other->r, other->c);
for(int i = 0; i < this->r; i++)
{
for(int j = 0; j < this->c; j++)
{
for(int k = 0; k < other->c; k++)
temp->mat[i][j] += this->mat[i][k] * other->mat[k][j];
}
}
return temp;
}
This works perfectly, but only if I multiply matrices with the same dimensions (e.g. Mat4x4*Mat4x4 or Mat2x4*Mat2x4). I understand I can't just multiply an Mat4x4 with an Mat9X2 or anything, but I do know the second matrix's columns should be equal to the first matrix's rows (so a Mat2x2 should be able to multiply with a Mat2x1) and that the answer will have the dimensions of the second matrix. How could (or should) I make the function so it will multiply the matrices with the same and with different dimensions?
Thanks in advance
A solution for your program would be to make the temp dimensions not the others dimension but this->r, other->c in order to make the dimensions valid with the outputs from the matrix multiplication.
Hope this helps.
The following code contains a Matrix class implementation meant to show a few features of C++ (like unique pointers, random numbers, and stream formatting). I often use it when I want to explain a little bit about the language. Maybe it can help you.
#include <cassert>
#include <iostream>
#include <iomanip>
#include <memory>
#include <random>
// Pedagogical implementation of matrix type.
class Matrix {
public:
// Create a rows-by-cols matrix filled with random numbers in (-1, 1).
static Matrix Random(std::size_t rows, std::size_t cols) {
Matrix m(rows, cols);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(-1, 1);
for (std::size_t row = 0; row < rows; ++row) {
for (std::size_t col = 0; col < cols; ++col) {
m(row, col) = dis(gen);
}
}
return m;
}
// Build an uninitialized rows-by-cols matrix.
Matrix(std::size_t rows, std::size_t cols)
: m_data { std::make_unique<double[]>(rows * cols) },
m_rows { rows },
m_cols { cols }
{
assert(m_rows > 0);
assert(m_cols > 0);
}
// Return number of rows
std::size_t rows() const { return m_rows; }
// Return number of columns
std::size_t cols() const { return m_cols; }
// Value at (row, col)
double operator()(std::size_t row, std::size_t col) const {
assert(row < rows());
assert(col < cols());
return m_data[row * cols() + col];
}
// Reference to value at (row, col)
double& operator()(std::size_t row, std::size_t col) {
assert(row < rows());
assert(col < cols());
return m_data[row * cols() + col];
}
// Matrix multiply
Matrix operator*(const Matrix& other) const {
assert(cols() == other.rows());
Matrix out(rows(), other.cols());
for (std::size_t i = 0; i < rows(); ++i) {
for (std::size_t j = 0; j < other.cols(); ++j) {
double sum { 0 };
for (std::size_t k = 0; k < cols(); ++k) {
sum += (*this)(i, k) * other(k, j);
}
out(i, j) = sum;
}
}
return out;
}
private:
std::unique_ptr<double[]> m_data; // will cleanup after itself
const std::size_t m_rows;
const std::size_t m_cols;
};
// Pretty-print a matrix
std::ostream& operator<<(std::ostream& os, const Matrix& m) {
os << std::scientific << std::setprecision(16);
for (std::size_t row = 0; row < m.rows(); ++row) {
for (std::size_t col = 0; col < m.cols(); ++col) {
os << std::setw(23) << m(row, col) << " ";
}
os << "\n";
}
return os;
}
int main() {
Matrix A = Matrix::Random(3, 4);
Matrix B = Matrix::Random(4, 2);
std::cout << "A\n" << A
<< "B\n" << B
<< "A * B\n" << (A * B);
}
Possible output:
$ clang++ matmul.cpp -std=c++17 -Ofast -march=native -Wall -Wextra
$ ./a.out
A
1.0367049464391398e-01 7.4917987082978588e-03 -2.7966084757805687e-01 -7.2325095373639048e-01
2.2478938813996119e-01 8.4194832286446353e-01 5.3602376615184033e-01 7.1132727553003439e-01
1.9608747339865196e-01 -6.4829263198209253e-01 -2.7477471919710350e-01 1.2721104074473044e-01
B
-8.5938605801284385e-01 -6.2981285198013204e-01
-6.0333085647033191e-01 -6.8234173530317577e-01
-1.2614486249714407e-01 -3.3875904433100934e-01
-6.9618174970366520e-01 6.6785401241316045e-01
A * B
4.4517888255515814e-01 -4.5869338680118737e-01
-1.2639839804611623e+00 -4.2259184895688506e-01
1.6871952235091500e-01 4.9689953389829533e-01
It turnes out the order of the rows and columns got me heckin' bamboozled. The formula was correct. Sorry for unnecessary post.

Compiler optimization when chaining operators

I overloaded the arithmetic/assignment operators on std::vector in order to be able to do some basic linear algebra operations. However, I'm having some performance trouble when chaining those operations.
Here's the content of my main.h:
#include <vector>
#include <stdlib.h>
using namespace std;
typedef vector<float> vec;
inline vec& operator+=(vec& lhs, const vec& rhs) {
for (size_t i = 0; i < lhs.size(); ++i) {
lhs[i] += rhs[i];
}
return lhs;
}
inline vec operator*(float lhs, vec rhs) {
for (size_t i = 0; i < rhs.size(); ++i) {
rhs[i] *= lhs;
}
return rhs;
}
Content of main1.cpp:
#include "main.h"
// gcc 4.9.2 (-O3): 0m5.965s
int main(int, char**) {
float x = rand();
vec v1(1000);
vec v2(1000);
for (size_t i = 0; i < v1.size(); ++i) {
v1[i] = rand();
v2[i] = rand();
}
for (int i = 0; i < 10000000; ++i) {
v1 += x * v2;
// same as:
//vec y = x * v2;
//v1 += y;
}
return 0;
}
Content of main2.cpp:
#include "main.h"
// gcc 4.9.2 (-O3): 0m2.400s
int main(int, char**) {
// same stuff
for (int i = 0; i < 10000000; ++i) {
for (size_t j = 0; j < v1.size(); ++j) {
v1[j] += x * v2[j];
}
}
return 0;
}
The second program runs much faster than the first. I do understand why this is the case: instead of just one loop, the first program does two loops, and it allocates a temporary vector.
But this is the kind of thing I'd expect the compiler to see and optimize. Or am I doing something wrong?
I don't recall having this problem with linear algebra libraries (e.g. Armadillo). How do they tackle this problem? Does this involve some complicated template programming, or is there some simple way to help the compiler optimize this?
There were some super ugly template meta-programming solutions to that problem. But then the standards committee invented the combination of rvalue references and move semantics. Look those up and find many examples of the solution without the absurd levels of meta programming.

Class inheritance, copy constructor and set/get functions

I got the following class:
class Matrix{
private:
int rows;
int columns;
double* matrix;
public:
Matrix();
explicit Matrix(int N);
Matrix(int M, int N);
void setValue(int M, int N, double value);
double getValue(int M, int N);
bool isValid() const;
int getRows();
int getColumns();
~Matrix();
friend ostream& operator<<(ostream &out, Matrix&matrix1);
Matrix &operator=(const Matrix &m) {
if (rows * columns != m.rows * m.columns){
delete [] this->matrix;
this->matrix = new double[m.rows * m.columns];
}
rows = m.rows;
columns = m.columns;
for(int i = 0; i < rows; i++){
for(int j = 0; j < columns; j++){
this->matrix[i * columns + j] = m.matrix[i * columns + j];
}
}
return *this;
}
Matrix(const Matrix &rhs);
};
with these functions
#include <iostream>
#include "Matrix.h"
using namespace std;
//OPPGAVE 2
Matrix::Matrix(){
matrix = NULL;
}
Matrix::Matrix(int N){
matrix = new double[N * N];
rows = N;
columns = N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
if(i==j)
matrix[i * N + j] = 1;
else
matrix[i * N + j] = 0;
}
}
}
Matrix::Matrix(int M, int N){
matrix = new double[M * N];
rows = M;
columns = N;
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++)
matrix[i * N + j] = 0;
}
}
Matrix::~Matrix(){
delete [] matrix;
}
void Matrix::setValue(int M, int N, double value){
matrix[M * columns + N] = value;
}
double Matrix::getValue(int M, int N){
return matrix[M * columns + N];
}
bool Matrix::isValid() const{
if(matrix==NULL)
return false;
else
return true;
}
int Matrix::getRows(){
return rows;
}
int Matrix::getColumns(){
return columns;
}
ostream& operator<<(ostream &out, Matrix&matrix1){
if(matrix1.isValid())
for(int i = 0; i < matrix1.getRows(); i++){
for(int j = 0; j < matrix1.getColumns(); j++)
out << matrix1.getValue(i,j) << "\t";
out << endl;
}
else
out << "Matrisen er ikke gyldig." << endl;
return out;
}
Matrix::Matrix(const Matrix &rhs) : rows(rhs.rows),
columns(rhs.columns),
matrix(new double[rows * columns]) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
this->matrix[i * columns + j] = rhs.matrix[i * columns + j];
}
}
}
The exercise says:
a) Create a class Vector that inherits the MxN Matrix.
We want to use the Vector class as an interface to an Mx1 dimensional matrix with some
extra functionality.
b) Implement the following constructors for the Vector class.
• Vector()
Default constructor, should initialize the underlying matrix into the invalid state.
• explicit Vector(unsigned int N)
Should construct the underlying Mx1 Matrix, initialized as a zero-matrix. (The explicit keyword is not in the syllabus, but it should be used here.)
• Vector(const Matrix & other);
Copy-constructor from Matrix. Should assign a matrix to *this if and only if the matrix has dimensions Nx1, otherwise the resulting *this should be set to invalid. Hint: Reuse operator= from the Matrix-class.
This is what I've got so far:
#include "Matrix.h"
class Vector : public Matrix{
public:
Vector();
explicit Vector(int N);
Vector(const Matrix & other);
};
and
using namespace std;
#include <iostream>
#include "Vector.h"
Vector::Vector()
:Matrix(){ }
Vector::Vector(int N)
:Matrix(N,1){ }
How am I supposed to reuse the operator= from Matrix? If I try to copy it from the Matrix class into the Vector class, it says that rows, columns etc is inaccessible. How do I access these?
Is it possible to write a copy constructor for the Vector class more or less the same as the copy constructor for the Matrix class? They are both arrays, so I guess it should work?
Will the operators I overloaded for Matrix (not included here) automaticly be used if I multiply a Matrix with a Vector, or do I also need to include these somehow in the Vector class? (They were written outside the Matrix class in the Matrix.cpp-file.)
Next Im going to write set and get functions for the Vector class.
Is it possible to write these functions on this form?:
void Vector::setValue(int i, double value) {
Matrix::setValue(i, 1, value);
}
Help and tips are greatly appreciated!
What follows is hideous kludgery to satisfy an incompetent professor. Don't do this in the real world.
First, the misnamed "copy" constructor. If we weren't worried about the dimensions, we could do this (shudder):
Vector(const Matrix & other)
{
*this = other;
}
But we must check the dimensions first. We could do it this way:
Vector(const Matrix & other)
{
if(other.getColumns()==1)
*this = other;
}
But some chucklehead neglected to make getColumns() const, so this results in a compiler error. We could do something truly drastic, const cast:
Vector(const Matrix & other)
{
Matrix *p = const_cast<Matrix *>(&other);
if(p->getColumns()==1)
*this = other;
}
Or just something facepalmingly awful:
Vector(const Matrix & other)
{
Matrix M(other); // notice that this is not const
if(M.getColumns()==1)
*this = other;
}
Do you need help with the isValid stuff?
You are on the right track for the sets and gets. You can call operators with member function like syntax Class::operator*(args). Implementing the vector assignment would look something like this:
Vector & Vector::operator=(const Vector &v){
Matrix::operator=(v);
return *this;
}
You will want your Vector constructors to be declared public. I am thinking because you are using inheritance the compiler will generate correct copy constructors and assignment operators for the Vector class. You should write tests to verify this assumption.

Compare matrices multiplication

I must multiply a matrix by itself until the matrix in some degree would not be equal to one of the preceding matrices. Then I need to get the values of degrees in which the matrices are equal. The number of rows and columns are equal. The matrix is stored in a two-dimensional array. Values are 0 or 1. What is the best way to check for equality with the previous matrices? I tried to use vector to store matrices:
vector<int[5][5]> m;
but I got an error cannot convert from 'const int [5][5]' to 'int [5][5]'.
Waiting for an advice.
If you can use boost, look at the boost Matrix class:
It seems to be missing an == operator, but it's easy to add:
#include <iostream>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
using namespace boost::numeric::ublas;
template<typename T>
bool operator==(const matrix<T>& m, const matrix<T>& n)
{
bool returnValue =
(m.size1() == n.size1()) &&
(m.size2() == n.size2());
if (returnValue)
{
for (unsigned int i = 0; returnValue && i < m.size1(); ++i)
{
for (unsigned int j = 0; returnValue && j < m.size2(); ++j)
{
returnValue &= m(i,j) == n(i,j);
}
}
}
return returnValue;
}
And used like so:
int main ()
{
matrix<double> m (3, 3);
for (unsigned int i = 0; i < m.size1(); ++ i)
{
for (unsigned int j = 0; j < m.size2(); ++ j)
{
m (i, j) = 3 * i + j;
}
}
std::cout << m << std::endl;
matrix<double> n (3, 3);
std::cout << (m == n) << std::endl;
std::cout << (m == m) << std::endl;
}
[Code]
If you want to do it with vector, you probably want vector < vector < int > >, i.e. a vector of vectors of ints (i.e. kind of 2-dimensional vector).
vector<int[5][5]> would (if it worked) declare a vector of 2-dimensional 5x5-int-arrays.