How to call a static function? - c++

I have defined 2 functions in my class Matrix as follows (in Matrix.hpp)
static Matrix MCopy( Matrix &a );
static Matrix MatInvert( Matrix &x )
static double MatDet( Matrix &x ); // Matdef function
In my Matrix.Cpp file, I defined these functions as follows:
Matrix Matrix::MatCopy( Matrix &a )
{
Matrix P( a.getRow() , a.getCol() , Empty );
int j=0;
while( j != P.getRow() ){
int i=0;
while( i != P.getCol() ){
P(j,i)=a(j,i);
++i;
}
++j;
}
return P;
}
Matrix Matrix::MatInvert( Matrix &x )
{
Matrix aa = Matrix::MatCopy(x); // i got error message here
int n = aa.getCol();
Matrix ab(n,1,Empty);
Matrix ac(n,n,Empty);
Matrix ad(n,1,Empty);
if(MatLu(aa,ad)==-1){
assert( "singular Matrix" );
exit(1);
}
int i=0;
while( i != n ){
ab.fill(Zero);
ab (i,0)=1.0;
MatRuecksub(aa, ab,ac,ad,i);
++i;
}
return ac;
}
ok this is the my MatDef function
double Matrix::MatDet( Matrix &x )
{
double result;
double vorz[2] = {1.0, -1.0};
int n = x.getRow();
Matrix a = Matrix::MatCopy(x);
Matrix p( n, 1, Empty);
int i = MatLu(a, p);
if(i==-1){
result = 0.0;
}
else {
result = 1.0;
int j=0;
while(j != n){
result *= a( static_cast<int>(p(j,0)) ,j);
++j;
}
result *= vorz[i%2];
}
return result;
}
but when I compile this, I get an error telling me that:
line 306:no matching function for call to ‘Matrix::Matrix[Matrix]’:
note: candidates are: Matrix::Matrix[Matrix&]
note:in static member function ‘static double Matrix ::MatDet[Matrix&]’:
I can not understand what the problem is since I am new to C++ programming, so please help me in fixing this error.
Where I have used
Matrix aa = Matrix::MatCopy(x);
It shows same error message like line 306 but with different notes so I think MatDef is not a problem.
Please give your comments to solve this. Thanks!

If you have a class called A and it has a static function foo you would call it this way
A::foo();
Reading material

It seems that you are trying to access a variable of the class from a static member function of that class. Static member functions cannot access regular variables of the class.
You need to check the link that #Woot4Moo suggested:
non-static vs. static function and variable

Related

How do I feed arrays into a linspace function in C++?

Disclaimer: this stuff is not my specialty.
I am trying to feed 2 different 3 column 1 row arrays into a linspace function using the NumCPP package, but i'm getting errors such as:
"no instance of function template "nc::linspace" matches the argument list -- argument types are: (float, float, int)" <-- from VSCode intelisense and "error: cannot convert ‘float’ to ‘float**’" when ran in terminal.
the code relating to this error goes as follows:
float** XYZ[3];
float** function(float array_A, float array_B, int C) {
XYZ** = nc::linspace<float**>(array_A, array_B, C);
return XYZ;
};
Towards the end of my code in the main function I define these parameters as:
float array_A [3]= {0,0,0};
float array_B [3]= {0,PI/4,0};
int C = 10000;
I did the same thing with python using numpy's linspace function and has no issues. C++ is tough, so any help is appreciated.
Here is an example of how to do it (without "C" style arrays)
#include <cassert>
#include <iostream>
#include <vector>
#include <NumCpp/Functions/linspace.hpp>
// in C++ std::vector (or std::array) are preferred over manually allocated "C" style arrays.
// this will avoid a lot of issues related to (pointer) type decay in which actual size information
// of arrays is lost, and it will avoid manual memory managment with new/delete.
// pass vector's by const& so they won't be copied
// make number_of_samples a size_t type since it should never be < 0 (which is allowed by int)
auto linspace(const std::vector<double>& arr1, const std::vector<double>& arr2, const std::size_t number_of_samples)
{
std::vector<std::vector<double>> retval;
assert(arr1.size() == arr2.size());
for (std::size_t n = 0; n < arr1.size(); ++n)
{
// linspace documentationhttps://dpilger26.github.io/NumCpp/doxygen/html/namespacenc.html#a672fbcbd2271d5fc58bd1b94750bbdcc
// in C++ linspace only accepts values, not array like stuff.
nc::NdArray<double> sub_result = nc::linspace(arr1[n], arr2[n], static_cast<nc::uint32>(number_of_samples));
// construct a std::vector<double> from nc::NdArray and put it at back of return value
retval.emplace_back(sub_result.begin(), sub_result.end());
}
return retval;
}
int main()
{
// Create two dynamically allocated arrays of doubles
std::vector<double> array_A{ 0.0, 1.0, 2.0 };
std::vector<double> array_B{ 4.0, 5.0, 6.0 };
// do a linspace on them (linespace is what you called function)
const std::size_t number_of_samples = 4;
auto result = linspace(array_A, array_B, number_of_samples);
// and show the output
std::cout << "result of linspace : \n";
for (const auto& arr : result)
{
bool comma = false;
// range based for loop over the result array to display output
for (const auto& value : arr)
{
if (comma) std::cout << ", ";
std::cout << value;
comma = true;
}
std::cout << "\n";
}
return 0;
}

Result of SelfAdjointEigenSolver saved as member is reinitialized when in another scope

I'm trying to run a pca on an block of an eigen matrix.
The observation in the input matrix are in columns.
I want to save the eigen vectors as a matrix for later use.
But the matrix (m_pcaCoefs) "gets reinitialized" when I use it in another scope, inside the class of course.
I'm pretty sure I'm missing something on how eigen works !
class foo {
public:
using InputMatrixType = Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>;
void computePca(InputMatrixType & inputMatrix)
{
// m_pcaCoefs is a private member of dense matrix type
size_t start = 1;
auto r = inputMatrix.rows();
auto c = inputMatrix.cols();
Eigen::Block<InputMatrixType> inputBlock
= inputMatrix.block( start, 0 ,r-start , c );
// center the data
m_pixelValueMeans = inputBlock.rowwise().mean();
inputBlock.colwise() -= m_pixelValueMeans;
// inputBlock is a d by n, where d is the number of observation
InputMatrixType cov = inputBlock * inputBlock.adjoint();
cov = cov / (c - 1);
Eigen::SelfAdjointEigenSolver<InputMatrixType> eig(cov);
InputMatrixType m_pcaCoefs = eig.eigenvectors();
// here m_pcaCoefs looks fine
std::cout << m_pcaCoefs.size() << std::endl; // output: 9
}
void print()
{
std::cout << m_pcaCoefs.size() << std::endl; // output: 0
}
protected:
InputMatrixType m_pcaCoefs;
}
int main()
{
foo test;
test.computePca(someMatrix); // outputs 9
test.print() // output 0
}
Any clue how to get the eigenvectors to be copied to m_pcaCoefs ?
InputMatrixType m_pcaCoefs = eig.eigenvectors();
this is not what you're thinking which is a member of your class.
you should just use:
m_pcaCoefs = eig.eigenvectors(); // use member m_pcaCoefs

C - Sorting struct element based on another element [duplicate]

This question already has an answer here:
How to sort an array of structs in C?
(1 answer)
Closed 6 years ago.
I have a C struct declared as below (just a simple example):
typedef struct
{
float score;
char* name;
}
person;
So, along the program, I changed the value of the person's score (i gave them an initial value). So, i plan to put all of the scores inside a vector and sort them. Then, I would like to print a list of the name of all the persons, starting from biggest score to smallest score. Any idea on this last part? I'm not sure how to code it. Thanks.
Similar to the C++ approach above, there is a library function in the C standard library called qsort. It is based upon a comparision function, that creates the ordering on the array members.
For your case a minimal example could look like this:
#include <stdlib.h>
#include <stdio.h>
// Definitiion of a person
typedef struct person
{
float score;
char *name;
} person;
// Some small epsilon
#define EPSILON 1.0e-3f
// Comaprision function. Returns <0 for a<b =0 for a=b and >0 for a>b
static int compare_people( const void *a, const void *b )
{
// Cast to the correct pointer type
const person *p1 = (const person*) a;
const person *p2 = (const person*) b;
// There are different ways of comparing floats to each other. In this case we use |a - b| < epsilon for some small epsilon
float difference = p2->score - p1->score;
if( difference <= -EPSILON )
{
return -1;
}
else if( difference >= +EPSILON )
{
return +1;
}
return 0;
}
int main()
{
// Initialize list of people
size_t num_people = 5;
person people[num_people];
people[0].score = 0.3f;
people[0].name = "Homer";
people[1].score = 1.4f;
people[1].name = "Marge";
people[2].score = 0.02f;
people[2].name = "Bart";
people[3].score = 13.2f;
people[3].name = "Lisa";
people[4].score = 1.0f;
people[4].name = "Maggie";
// Print unsorted
printf( "Unsorted:\n" );
for( size_t i = 0; i < num_people; ++i )
{
printf( " %s - %2.2f\n", people[i].name, people[i].score );
}
printf( "\n" );
// Sort
qsort( people, num_people, sizeof(person), &compare_people );
// Print sorted
printf( "Sorted:\n" ) ;
for( size_t i = 0; i < num_people; ++i )
{
printf( " %s - %2.2f\n", people[i].name, people[i].score );
}
printf( "\n" );
// Done
return EXIT_SUCCESS;
}
Note the comment about comparing floating point values.
If you are using Linux, you can investigate system calls and functions of the C standard library by looking up the corresponding man page, e.g.
man qsort
For example you ll have
vector<person> vec;
Now you want sort this using sort from STL
You first must create method for operator " < "
bool operator<(const person& a, const person& b){
return a.score<b.score;
}
I hope this helps you I m sorry for my bad grammar :)
Example of usage
sort(vec.begin(),vec.end(),[](const person& a, const person&b){return b<a});
Now your vector of person will be sorted upside - down order.

C++ Making a 2D boolean matrix

I am making a program where I have 2 vectors (clientvec and productslist) and I need to create a 2D boolean matrix where the columns is the size of productslist vector and the lines is the size of clientvec vector, but it gives me this error:
"expression must have a constant value"
Here is the code I used:
unsigned int lines = clientvec.size();
unsigned int columns = productslist.size();
bool matrixPublicity[lines][columns] = {false};
Pls help me..
Edit: I am new at c++ so assume I know nothing xD
Edit2: I already know for the answers that I cannot initialize an array with non constant values, now the question is how can I put them after initialize...
The error message is clear: :expression must have a constant value"
It means the array dimension cannot be of variable type. Only enums or pre-processor defined constants are valid.
See for more info:
Why can't I initialize a variable-sized array?
Edit: Since you mentioned you are new to C++, here is a piece of code that might help you:
#include <iostream>
#include <vector>
#include <bitset>
int main()
{
unsigned int lines = 10;
const unsigned int columns = 5;
std::vector<std::bitset<columns>> matrixPublicity;
matrixPublicity.resize(lines);
for(int i=0; i < lines; i++)
{
for(int j=0; j < columns; j++)
std::cout << matrixPublicity[i][j] <<' ';
std::cout<<'\n';
}
}
note that in this case, columns must be constant.
Edit 2: And if the size of lines are not the same, then you must stick to vector types:
typedef std::vector<bool> matrixLine;
std::vector<matrixLine> matrixPublicity;
now you can use resize method for the i-th line of the matrix, e.g.
matrixPublicity[1].resize(number_of_columns_in_line_2);
What you are trying to do would be the same as this:
std::vector<unsigned int> v1 { 1, 2, 3, 4, 5 };
std::vector<unsigned int> v2 { 6, 7, 8, 9 };
bool mat[v1.size()][v2.size()] = false;
This is how the compiler will interpret it without the temporaries and this is invalid. When you declare an array of any type its size has to be known at compile time.
bool mat[2][3] = false; // still invalid
bool mat[2][3] = { false }; // Okay
const int x = 5;
const int y = 7;
bool mat[x][y] = false; // invalid
bool mat[x][y] = { false }; // okay
// Even this is invalid
std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 4, 5, 6, 7 };
const std::size_t x1 = v1.size();
const std::size_t y1 = v2.size();
bool mat2[x1][y1] = { false }; // Still won't compile.
Value to declare an array must be a constant expression.
Instead of making an array as you have tried to do, you could make a class template that will construct a matrix like object for you. Here is what I have come up with, now the overall design or pattern of this template will fit your condition but the actual implementation to generate the internal matrix will depend on your data and what you intend.
#include <vector>
#include <iostream>
#include <conio.h>
template <class T, class U>
class Matrix {
private:
std::vector<T> m_lines;
std::vector<T> m_cols;
std::vector<U> m_mat;
std::size_t m_size;
std::size_t m_lineCount;
std::size_t m_colsCount;
public:
Matrix() {};
Matrix( const std::vector<T>& lines, const std::vector<T>& cols ) :
m_lines(lines),
m_cols(cols),
m_lineCount( lines.size() ),
m_colsCount( cols.size() )
{
addVectors( lines, cols );
}
void addVectors( const std::vector<T>& v1, const std::vector<T>& v2 ) {
m_lines = v1;
m_cols = v2;
m_lineCount = m_lines.size();
m_colsCount = m_cols.size();
for ( unsigned int i = 0; i < m_lineCount; ++i ) {
for ( unsigned int j = 0; j < m_colsCount); j++ ) {
// This will depend on your implementation and how you
// construct this matrix based off of your existing containers
m_mat.push_back(m_lines[i] & m_cols[j]);
}
}
m_size = m_mat.size();
}
std::size_t size() const { return m_size; }
std::size_t sizeRows() const { return m_lineCount; }
std::size_t sizelColumns() const { return m_colsCount; }
std::vector<U>& getMatrix() const { return m_mat; }
std::vector<T>& getLines() const { return m_lines; }
std::vector<T>& getColumns() const { return m_columns; }
bool operator[]( std::size_t idx ) { return m_mat[idx]; }
const bool& operator[]( std::size_t idx ) const { return m_mat[idx]; }
};
int main() {
std::vector<unsigned> v1{ 1, 0, 1, 1, 0 };
std::vector<unsigned> v2{ 0, 1, 1, 1, 0 };
Matrix<unsigned, bool> mat1( v1, v2 );
int line = 0;
for ( unsigned u = 0; u < mat1.size(); ++u ) {
line++;
std::cout << mat1[u] << " ";
if ( line == mat1.sizeRows() ) {
std::cout << "\n";
line = 0;
}
}
std::cout << "\nPress any key to quit.\n" << std::endl;
_getch();
return 0;
}
Output
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
With this template class you can create a matrix of any type U by passing in two vectors for type T. Now how you construct the matrix will be implementation dependent. But this class is reusable for different types.
You could have two vectors of type doubles, and construct a matrix of unsigned chars, or you could have two vectors of user defined class or struct types and generate a matrix of unsigned values. This may help you out in many situations.
Note: - This does generate a compiler warning, no errors though and it prints and displays properly, but the compiler warning generated by MSVS 2015 is warning C4800: unsigned int: forcing value to bool true or false (performance warning)
This is generated for I am doing a bit wise & operation on to unsigned values; but that is why I set my initial vectors to be passed to this class template's constructor to have all 1s & 0s as this is meant for demonstration only.
EDIT - I made an edit to the class because I noticed I had a default constructor and had no way to add vectors to it, so I added an extra member variable, and an addVectors function, and moved the implementation from the defined constructor to the new function and just ended up calling that function in the defined constructor.
Creating an array isn't that difficult :)
A matrix (2D/3D/...-array) is unfortunately a little bit different if you want to do it your way!
But first of all you should know about the stack and the heap!
Lets have a look at these 2:
Stack:
A stack variable/array/matrix/... is only valid between the nearest 2 -> {} <- which you normally call a "codeblock". The size of it was defined during the "compile time" (the time where the compiler translates your code into the machine language). That means the size of your array needs to be set.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
std::cin >> size;
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' which is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//this is not valid!
int intArray[size()] = {};
return 0;
}
Heap:
A heap variable/array/matrix/... is valid until you delete it. That also means that a heap var is created during the run-time(from starting your program until you close/stop it)! This is allows you to define it's size.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' whic is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//creating an array with a non-static size
//works like this:
//int can also be a 'bool'
int* intArray = new int[arraySize()];
// ^ the star means you are pointing to
//an adress inside of your memory which has
//the size of an int (per element)
//That's why they are called "pointers"!
//Right now it points to the beginning of the
//array.
// ^ the keyword "new" says that
//you are allocating memory on the heap.
// ^
//then you have to say which kind of array
//it is which is the same you gave the pointer
// ^
//now you give it the size of that array
//this time it can be return value or the size
//of a variable
//as I mentioned...you have to delete this array on your own
//if you dont do that your program will crash
//maybe not after starting but it will!
//SO NEVER NEVER NEVER... forget about it
delete intArray[];
//^ write delete
// ^
//then the name of your array
// ^
//at the end of it write these 2 brackets
//thex say you wanna remove the whole array!
//why? because you can also create/delete
//heap variables not only arrays.
return 0;
}
Creating a matrix on the heap is unfortunately not that easy.
But it is essential to know how a 1D-array works before going to further dimensions! That's why I did this tutorial!
Klick here to see how to create a matrix on the heap
Klick here to learn more about the heap
Klick here to choose the best result of this theme
I hope I could help you :)!

A little problem in handling 2-D arrays with class

class linklist4x4
{
private:
struct node4x4
{
double data[4][4];
node4x4 *link;
}*p;
public:
linklist4x4();
void append( double* num );
void add_as_first( double* num );
void addafter( int c, double* num );
//void del( double* num );
void display();
int count();
double* getdata(int c);
~linklist4x4();
};
The above is my class declaration.
Now below is a function declaration.
void linklist4x4::append(double* num)
{
node4x4 *q,*t;
if( p == NULL )
{
p = new node4x4;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
p->data[i][j]=num[i][j];//error line
p->link = NULL;
}
else
{
q = p;
while( q->link != NULL )
q = q->link;
t = new node4x4;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
t->data[i][j]=num[i][j];//error line
t->link = NULL;
q->link = t;
}
}
When i try to compile, it gives me an error saying that "error C2109: subscript requires array or pointer type" at the marked commented lines as shown.
Can anyone please help?
The num passed in is a single double pointer, but you are trying to index it with two subscripts. If you are really passing in a 4x4 double array, change the function signature to indicate that it is such.
"num" has a single indirection so you can't dereference it twice. Declare is as
double (*num)[4]
if you want it to accept a 2D matrix so that you can apply [] to it twice.
You have defined the method append to take a 1-D array of type double. But in the function you are making use of it as a 2-D array.
The data in each of your link list node is a 2-D array of double.
So your all your member functions should accept a 2-D array of double as argument.
Change:
void append( double* num );
void add_as_first( double* num );
void addafter( int c, double* num );
to
void append( double num[][4] );
void add_as_first( double num[][4] );
void addafter( int c, double num[][4] );
You're indexing num as if it were a 2D array or double pointer, while it is only one level deep.
double* num
num[i][j]
You can also use num[i*4+j] for accessing the data you require.