protot/src/SimpleMath/SimpleMathBlock.h

195 lines
5.1 KiB
C++

/**
* This is a highly inefficient math library. It was conceived by Martin
* Felis <martin.felis@iwr.uni-heidelberg.de> while he was compiling code
* that uses a highly efficient math library.
*
* It is intended to be used as a fast compiling substitute for the
* blazingly fast Eigen3 library and tries to mimic its API to a certain
* extend.
*
* Feel free to use it wherever you like. However, no guarantees are given
* that this code does what it says it would.
*/
#ifndef SIMPLEMATHBLOCK_H
#define SIMPLEMATHBLOCK_H
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <assert.h>
#include "compileassert.h"
// #include "SimpleMathQR.h"
/** \brief Namespace for a highly inefficient math library
*
*/
namespace SimpleMath {
/** \brief Namespace for fixed size elements
*/
// forward declaration
template <typename val_type, unsigned int nrows, unsigned int ncols>
class Matrix;
template <typename matrix_type, typename val_type>
class Block {
public:
typedef val_type value_type;
Block() :
mParentRows(0),
mParentCols(0),
mParentRowStart(0),
mParentColStart(0)
{ }
Block (const matrix_type &matrix, const unsigned int row_start, const unsigned int col_start, const unsigned int row_count, const unsigned int col_count) :
mParentRows (matrix.rows()),
mParentCols (matrix.cols()),
mParentRowStart (row_start),
mParentColStart (col_start),
mRowCount (row_count),
mColCount (col_count),
mTransposed (false) {
assert (mParentRows >= mParentRowStart + mRowCount);
assert (mParentCols >= mParentColStart + mColCount);
// without the following line we could not create blocks from const
// matrices
mParentMatrix = const_cast<matrix_type*>(&matrix);
}
// copy data from the other block into this
Block& operator=(const Block &other) {
if (this != &other) {
if (mRowCount != other.rows() || mColCount != other.cols()) {
std::cerr << "Error: cannot assign blocks of different size (left is " << mRowCount << "x" << mColCount << " right is " << other.rows() << "x" << other.cols() << ")!" << std::endl;
abort();
}
value_type* temp_values = new value_type [mRowCount * mColCount];
for (unsigned int i = 0; i < mRowCount; i++) {
for (unsigned int j = 0; j < mColCount; j++) {
temp_values[i * mColCount + j] = static_cast<value_type>(other(i,j));
}
}
for (unsigned int i = 0; i < mRowCount; i++) {
for (unsigned int j = 0; j < mColCount; j++) {
(*this)(i,j) = temp_values[i * mColCount + j];
}
}
delete[] temp_values;
}
return *this;
}
template <typename other_matrix_type>
// copy data from the other block into this
Block& operator=(const other_matrix_type &other) {
if (mRowCount != other.rows() || mColCount != other.cols()) {
std::cerr << "Error: cannot assign blocks of different size (left is " << mRowCount << "x" << mColCount << " right is " << other.rows() << "x" << other.cols() << ")!" << std::endl;
abort();
}
value_type *temp_values = new value_type[mRowCount * mColCount];
for (unsigned int i = 0; i < mRowCount; i++) {
for (unsigned int j = 0; j < mColCount; j++) {
temp_values[i * mColCount + j] = static_cast<value_type>(other(i,j));
}
}
for (unsigned int i = 0; i < mRowCount; i++) {
for (unsigned int j = 0; j < mColCount; j++) {
(*this)(i,j) = temp_values[i * mColCount + j];
}
}
delete[] temp_values;
return *this;
}
unsigned int rows() const {
if (!mTransposed)
return mRowCount;
return mColCount;
}
unsigned int cols() const {
if (!mTransposed)
return mColCount;
return mRowCount;
}
const val_type& operator() (const unsigned int i, const unsigned int j) const {
if (!mTransposed) {
assert (i < mRowCount);
assert (j < mColCount);
return (*mParentMatrix) (i + mParentRowStart, j + mParentColStart);
}
return (*mParentMatrix) (j + mParentRowStart, i + mParentColStart);
}
val_type& operator() (const unsigned int i, const unsigned int j) {
if (!mTransposed) {
assert (i < mRowCount);
assert (j < mColCount);
return (*mParentMatrix) (i + mParentRowStart, j + mParentColStart);
}
assert (j < mRowCount);
assert (i < mColCount);
return (*mParentMatrix) (j + mParentRowStart, i + mParentColStart);
}
Block transpose() const {
Block result (*this);
result.mTransposed = mTransposed ^ true;
return result;
}
private:
matrix_type *mParentMatrix;
const unsigned int mParentRows;
const unsigned int mParentCols;
const unsigned int mParentRowStart;
const unsigned int mParentColStart;
const unsigned int mRowCount;
const unsigned int mColCount;
bool mTransposed;
};
template <typename matrix_type, typename val_type>
inline std::ostream& operator<<(std::ostream& output, const Block<matrix_type, val_type> &block) {
unsigned int i,j;
for (i = 0; i < block.rows(); i++) {
output << "[ ";
for (j = 0; j < block.cols(); j++) {
output << block(i,j);
if (j < block.cols() - 1)
output << ", ";
}
output << " ]";
if (block.rows() > 1 && i < block.rows() - 1)
output << std::endl;
}
return output;
}
}
#endif /* SIMPLEMATHBLOCK_H */