I'm revamping an old application that use Numerical Recipes' dmatrix quite extensively. Since one of the reasons I'm working on the application is because its code is about to be opened, I want to replace all of the Numerical Recipes code with code that can be freely distributed.
dmatrix is a function that returns a matrix of doubles. The called supplies the lower and upper bound for each index, like so:
double **mat = dmatrix(1,3,1,3);
mat now has 3 rows, from 1 to 3, and 3 columns, from 1 to 3, so that mat[1][1] is the first element and mat[3][3] is the last.
I looked at various C++ matrix implementations, none of them allowed me to specify the lower bound of each dimension. Is there something I can use, or do I have to write yet another matrix class for this?
I believe that you can easily make a wrapper of some other matrix implementation to add the lower bound feature. Example (untested):
class Matrix {
OtherMatrix m;
int lowerX, lowerY;
public:
Matrix(int lx, int hx, int ly, int hy) :
m(hx-lx, hy-ly),
lowerX(lx), lowerY(ly) { }
MatrixCol operator[] (int x) {
return {this, x};
}
};
class MatrixCol {
friend class Matrix;
Matrix* mm;
int x;
public:
double& operator[] (int y) {
return mm->m[x - mm->lowerX, y - mm->lowerY];
}
};
This may require a little more robust implementation depending on your use case. But this is the basic idea, expand from it.
Related
I am trying to write a function which will take in multiple indices and do something based on the values in an array at those indices. If I do not declare the arrays as arguments to the function (which will always operate on the same two arrays) I get X/Y was not declared in this scope, but if I do attempt to declare them, I get "error: declaration of ‘X’ as multidimensional array must have bounds for all dimensions except the first," and the bounds are not known until runtime.
Is there any way to do this in a function, or do I have to explicitly write the code in main every time?
Code:
double foo(int A, int B, int t){//A, B, and t are indices
int x = X[A][t]-X[B][t]; //X and Y are 2D arrays
int y = Y[A][t]-Y[B][t];
double d;
//do some math ...
return d;
}
int main{
.
.
.
int X[nPeople][tMax]={0};
int Y[nPeople][tMax]={0};
.
.
.
for(int t=0; t<tMax; t++){
for(int n=0; n<nPeople; n++){
foo(n,a,t);
}
}
.
.
.
return 0;
}
There are multiple ways:
1- Use built-in std::vector library with the following inclusion:
#include <vector>
Vectors are dynamic arrays so when you initialize them they do not have a strict capacity which you can never change. On constrast, they grow larger with each element you push or insert. As far as I can see you are dealing with matrices so you need two dimensional arrays, no problem. Here is the code for it:
std::vector<std::vector<int> >
2- Use global variables. Variables that are declared outside of the functions are considered global so they will be visible to every function beneath it. Altough it is not considered to be good coding practise because of the bugs it may cause in a large scale problem, if you are confident enough that it will not pose a threat to your code safety/cleanness, go ahead use it!
3- Use dynamically allocated arrays and pass the pointers as parameters so that you can deal with any size you want
There are several ways a function can work with data:
Use global data:
std::vector<std::vector<int>> X;
std::vector<std::vector<int>> Y;
double foo(int A, int B, int t){ //A, B, and t are indices
int x = X[A][t]-X[B][t]; // X and Y are global 2D arrays
int y = Y[A][t]-Y[B][t];
double d;
//do some math ...
return d;
}
unfortunately shown too many times in sample code, but (mutable) global have lot of issues (hard to test, hard to re-use the code, hard to reason about the code)
Pass them as arguments:
double foo(const std::vector<std::vector<int>>& X, // X and Y are 2D arrays
const std::vector<std::vector<int>>& Y, // As we can see, so unneeded comment
int A, int B, int t){ //A, B, and t are indices
int x = X[A][t]-X[B][t];
int y = Y[A][t]-Y[B][t];
double d;
//do some math ...
return d;
}
bind them using a class:
class C
{
std::vector<std::vector<int>> X;
std::vector<std::vector<int>> Y;
public:
double foo(int A, int B, int t){ //A, B, and t are indices
int x = X[A][t]-X[B][t]; // X and Y are member 2D arrays (it should be trivial (`this->` might help), so comment not needed neither)
int y = Y[A][t]-Y[B][t];
double d;
//do some math ...
return d;
}
};
care to create coherent classes and avoid god class (which have mostly same default as global).
I'm trying to learn how to create a class which properly initializes a vectors of vectors to implement a matrix. The code below doesn't work, after running the constructor the vector has size 0. The program prints 0 and attempts to access elements of it result in errors.
My first question is what is wrong with the code and how to fix it.
My second question is if there is a better approach to creating a class to implement a matrix dynamically using vectors or similar objects from the STL.
Code:
class Matrix{
std::vector<std::vector<int> > Mat;
public:
Matrix(int n, int m);
void set(int a, int b, int Value);
int get(int a, int b);
void size();
};
Matrix::Matrix(int n, int m){
std::vector<std::vector<int> > Mat(n, vector<int>(m));
}
void Matrix::size(){
std::cout << std::endl << Mat.size() << std::endl;
}
int Matrix::get(int a, int b){
return Mat[a][b];
}
void Matrix::set(int a, int b, int Value){
Mat[a][b]=Value;
}
int main(int argc, char** argv) {
Matrix M(10,10);
M.size();
return 0;
}
1) Current code
The problem is that Mat is already constructed when you enter the body of your constructor. What you do is just redefine a local Mat which hides the member having the same name and which vanishes as soon as you exit the constructor.
Try this instead:
Matrix::Matrix(int n, int m) : Mat(n, vector<int>(m)) {
}
2)Are there better approaches ?
it all depend on what you intend to do, whar atre your constraints, and what are the trade-offs:
If the size of you matrixes is not always defined at compile time, this kind of implementation is fairly good, and the code very readable.
If you have many rather small vectors, one alternative could be to flatten the internal representation of the matrix to a unidimensional vector. You'd spare some vectors, but have to calculate the flatened index for the getter and the setter. If your Matrix class would provide a lot of matrix operations, would make the code less readable (i.e. Mat[n][m] vs. Mat[n*width+m])
If the size of your matrix is determined at compile time (e.g. you use only 2D or 3D matrixes), it could make sense to use std::array instead of std::vector: the compiler could then make use of the known sizes to generate faster code.
This code:
Matrix::Matrix(int n, int m){
std::vector<std::vector<int> > Mat(n, vector<int>(m));
}
will default construct the member-variable Mat, and then, separately, try to construct a local variable Mat, unrelated to the member. To initialize the member variable, you'll want to use a member initializer list:
Matrix::Matrix(int n, int m)
: Mat(n, std::vector<int>(m))
{ }
As a side-note, size() should return the size, not print it, and if your getter returned an int& instead of an int, you wouldn't need a setter with the code duplication.
in the constructor you should initialize using the following instead
Matrix::Matrix(int n, int m) {
Mat = std::vector<std::vector<int> > (n, std::vector<int>(m));
}
or use the way mentioned in the other answers
What is the equivalent matrix-like C-array of a nested std::vector (for C and C++ interop)?
For example, if one wanted to treat std::vector<std::vector<int>> as some kind of int arr[n][m], where n is the dimension of the outer vector and m of the inner vector, then what structure would one use in C?
This is motivated by wanting to have a similar correspondence between matrices in C and C++ as for vectors in:
https://stackoverflow.com/a/1733150/4959635
Based on additional information in the comments, let me suggest you do something like this instead:
class TwoDimVector {
public:
TwoDimVector(int num_cols, int num_rows)
: m_num_cols(num_cols)
, m_num_rows(num_rows)
, m_data(m_num_cols * m_num_rows, 0)
{ }
int & ix(int row, int col) {
return data[num_cols * row + col];
}
const int m_num_rows;
const int m_num_cols;
private:
std::vector<int> m_data;
}
When you do nested vectors, there's a lot of extra work happening. Also, with nested vectors, the data is not contiguous, making it hard to work with any C-apis. Notice with this data structure, the size is fixed at construction time and accessible. This is designed to be row contiguous, so for C interoperability you can access extra raw pointers like so:
TwoDimVector tdv(4,3);
int * raw = &tdv.ix(0,0);
int * raw_second_row = &tdv.ix(1,0);
Just note: if you pass this into a function, be sure to pass by reference:
void do_work(TwoDimVector & tdv) {
...
}
If you don't pass by reference, it will copy everything, which is a bunch of (typically unnecessary) work.
Maybe, this code
void translate(const vector< vector >& vec){
int m = vec.size(), n = 0;
for (vector<int>& deep : vec) // search maximum size if nested vectors
{
if (deep.size() > n)
n = deep.size();
}
int arr[m][n];
m = n = 0;
for (vector<int>& deep : vec){
for (int& x : deep)
{
arr[m][n] = x;
++n;
}
++m;
}
// So, I really don't know how you can return this array :(
}
You see, it code is BAD, you mustn't do it !!!
If you writing on C++ you should using std::vector - it is easier.
C-like arrays is heritage from C, you shouldn't using they
I am using trying to solve the Shortest Path problem in C++. For that I have created the following Graph() constructor.
Graph::Graph(int NumberOfVertices){
this->NumberOfVertices=NumberOfVertices;
cout<<"Graph()"<<endl;
//declaring the weight matrix
WeightMatrix=new int*[NumberOfVertices];
for(int a=0;a<NumberOfVertices;a++)
WeightMatrix[a]=new int[NumberOfVertices];
//initialising the weight matrix
WeightMatrix[NumberOfVertices][NumberOfVertices]={0};
ShortestPathArray=new int[NumberOfVertices];
}
I have two questions.
Why is a simple declaration like
WeightMatrix=new int[NumberOfVertices][NumberOfVertices] not allowed? I tried doing so but there were errors. I found the solution online, but am not able to understand it.
The initialization step is not working. The code doesn't proceed further than this statement WeightMatrix[NumberOfVertices][NumberOfVertices]={0};
When I comment out this step everything works fine.
Question #1:
The type of WeightMatrix is int**, so you cannot initialize it with new int[...].
As you seem to have already fixed in your code, the right way is to initialize it with new int*[...].
Question #2:
Initializing an array to a list of values is allowed only at declaration. For example:
int WeightMatrix[M][N] =
{
{1,2,3,...},
{4,5,6,...},
...
};
So you can fix the compilation error by changing this:
WeightMatrix[NumberOfVertices][NumberOfVertices]={0};
To this:
for (int i=0; i<NumberOfVertices; i++)
for (int j=0; j<NumberOfVertices; j++)
WeightMatrix[i][j] = 0;
Why is a simple declaration like WeightMatrix=new int[NumberOfVertices][NumberOfVertices] not allowed? I tried doing so but there were errors. I found the solution online, but am not able to understand it.
It should help to compare this to creation of an array on the stack, for which you can do:
int my_array[X][Y];
When you later say my_array[x][y], the compiler's record of the value Y is used to find the int value at address &my_array + x * Y + y. But, when you use new and specify a dimension at run-time, the compiler isn't obliged to store the dimension(s) involved - that would adversely affect run-time memory usage and performance. Without such dimensions though, the compiler can't support a [x][y] notation, so it's misleading to let you use new as if it were creating a multi-dimensional array. In practice, implementations sometimes store the single allowed array dimension in some extra memory they ask for when you use new[] so they can iterate over the right number of elements to call destructors, but they might want to avoid that for types such as int that require no destruction.
The expectation is that you'll work out the total number of elements you need:
int* weightMatrix = new int[NumberOfVertices * NumberOfVertices];
Then what's conceptually weightMatrix[x][y] can be stored at weightMatrix[x * NumberOfVertices + y] (or if you prefer weightMatrix[x + NumberOfVertices * y]).
I recommend writing a simple class that has an operator to provide a convenient notation ala matrix(x, y):
template <typename T>
class Matrix
{
Matrix(size_t X, size_t Y = X) : X_(X), Y_(Y), p_(new T[X * Y]) { }
~Matrix() { delete[] p_; }
T& operator()(size_t x, size_t y) { return p_[x * Y + y]; }
const T& operator()(size_t x, size_t y) const { return p_[x * Y + y]; }
size_t X_, Y_;
T* p_;
};
Then you can write simpler, cleaner and more robust client code:
Matrix matrix(20, 10);
matrix(4, 2) = 13;
You can also easily put checks in operator() to catch out-of-bound indexing during development and testing.
Suppose we want two constructors for a class representing complex numbers:
Complex (double re, double img) // construct from cartesian coordinates
Complex (double A, double w) // construct from polar coordinates
but the parameters (number and type) are the same: what is the more elegant way
to identify what is intended? Adding a third parameter to one of the constructors?
It is better to add static methods with appropriate names and let them to create the objects.
static Complex createFromCartesian(double re, double img);
static Complex createFromPolar(double A, double w);
You can't have two constructors (or any functions) with the same signatures. The best solution is probably to create classes for your coordinate types and overload on those. For example:
struct CartCoord {
CartCoord( double re, double img ) : mRe(re), mImg(img) {}
double mRe, mImg;
};
struct PolarCoord {
PolarCoord( double a, double v ) : mA(a), mV(v) {}
double mA, mV;
};
Then your constructors become:
Complex( const CartCoord & c );
Complex( const PolarCoord & c);
In use:
Complex c( CartCoord( 1, 2 ) );
You can also use them with overloaded operators of the Complex class. For example, assuming you have a binary + operator for the class define as:
Complex operator+( const Complex &, const Complex & );
then:
Complex a( CartCoord( 0, 0 ) );
Complex b = a + PolarCoord( 1, 1 );
As we have a conversion constructor from PolarCoord to Complex, this will be used in the + expression. This is more natural (IMHO) than calling static functions to create the temporary..
This is an example of Koenig's dictum (or at least a version of it) - whenever faced with a difficult problem, introduce a new level of classes to solve it.
Use the named constructor idiom described here at the Parashift C++ FAQ.
You can't - if the method signatures are the same, you're stuffed.
Of course, you could always create a subclass for each type of coordinate system, but that's far from ideal - especially if you later find a good reason to want to subclass Complex for other reasons...
Instead of having two constructors, you need to have only one, but add a third parameter, for example:
Complex (double re, double img, enum type) {
if(type == polar) {
..treat as polar coordinates..
} else {
..treat as cartesian coordinates..
}
}
'enum type' can have a default type as well so you don't have to supply what type of coordinates you intend to use every time, the default should off course be what's most used.
Complex (double re, double img, enum type = polar);
Since no one mentioned it, you can use tags:
class Complex{
struct CartCoord{};
struct PolarCoord{};
Complex( CartCoord, double re, double img);
Complex( PolarCoord, double a, double v);
};
int main(){
auto c1 = Complex(Complex::CartCoord{}, 5, 6);
auto c2 = Complex(Complex::PolarCoord{}, 5, 6);
}
I don't know if it is good practice in C++ but I would name these two methods differently, at least for a maintainability point of view.
I would probably create more classes, but then I am an adept of Boost Strong Typedef library.
For me it does not make sense to use double to represent both coordinates, module and angles.
So I would have:
class CoordinateX {};
class CoordinateY {};
class Modulus {};
class Angle {};
class Complex
{
public:
Complex(CoordinateX, CoordinateY);
Complex(Modulus, Angle);
};
And there it's perfectly clear, and there is no ambiguity. Also you add some compile-time check of "units" in a loose sense. It rarely makes sense (if ever) to add an X-coordinate and an Y-coordinate, or worse a distance and an angle.
For me the more elegant way would be to create a class representing cartesian coordinates and another representing polar coordinates, then give object of the relevant class to the constructors.
That way you would have two constructor using different parameters.
I use this simple alternative way while practicing C++, I don't know if it is what you want.
class Vector{
public:
float x, y;
Vector();
Vector(float , float, bool);
float get_distance(Vector v); // find distance from another vector
float get_magnitude(); // find distance from origin point
Vector add(Vector v);
Vector subtract(Vector v);
Vector multiply(Vector v); // multiply by vector
Vector multiply(float scalar); // multiply by scalar
float get_angle();
};
Vector::Vector(float a, float b, bool is_cartesian = true){
if(is_cartesian){
x = a;
y = b;
}
else{
x = a * cos( b );
y = a * sin( b );
}
}