Create a function in the memory to call it later - c++

Ok, my question is probably stupid, but I will regreat not asking it.
I would like to know if it is possible to create a function during program execution and then be able to call it later. This function will not be hard coded because it depends on many initial parameters decided by the program user. The objective would be to avoid calling these parameters, each time we need to call this function and hence, gain execution time and memory. I will give a minimalist example because I believe my question is not so easy to understand just with words.
In this example, I have a class Parameters that contain parameters A1, A2, A3 used to solve an equation. These parameters vary due to initial conditions. The second class CalculFunction uses these Parameters to solve the equation at the moment t. The way it is coded, each time I have to evaluate a new moment t', I have to go through the Parameters objects again to solve the equation. However, I would like to store directly a function in the memory, that contains the correct parameters and can be evaluated at t1, t2 etc.. without requiring to call startCalculation(const double & t, const double & initValue) method again.
My goal is to construct the function only one time and have in the memory a function f[i] = initValue * sum( A1[i][j] / A2[i][j] * exp( -A3[i] * t) where the sum occurs on j. Hence, I just call fi to get results without reconstructing the whole loops on j.
class Parameters
{
public:
Parameters();
QVector<double> & getA1(){return m_a1;};
QVector<double> & getA2(){return m_a2;};
double & getA3(){return m_a3;};
private:
QVector<double> m_a1;
QVector<double> m_a2;
double m_a3;
};
class CalculFunction
{
public:
CalculFunction(const QVector<Parameters> & allParam): m_parameters(allParam);
void startCalculation(const double & t, const double & initValue)
{
for(int i = 0; i < m_parameters.size(); i++)
{
m_results.append(0.);
for(int j = 0; j < m_parameters[i].getA1().size(); j++)
{
m_results[i] += m_parameters[i].getA1()[j] / m_parameters[i].getA2()[j] * exp(- (m_parameters[i].getA3() ) * t );
}
m_results[i] *= initValue;
}
}
private:
QVector<Parameters> m_parameters;
QVector<double> m_results;
};

You are looking for functor then. Functor is a class that is capable to storing internal states but has the operator() member that acts like a function.
class AFunc
{
public:
AFunc(A1 a1, A2 a2, A3 a3) : a1(a1), a2(a2), a3(a3) {}
T operator()(arguments ...) {
T t
...
return t;
}
private:
A1 a1;
A2 a2;
A3 a3;
};
where T is the return type.
You can have as many arguments in the constructor and operator(...) as you need.
You would just call it like
AFunc af(a1, a2, a3);
T t = af(arguments ...);
in your code.

I would re-envision your Parameters class. At the moment, it is a glorified struct, some data with getters, but no logic. Instead of simply storing the parameters, you could view it as your function. Put the logic of how to calculate a value at a particular time in this class. If you want it to look like a function call, you can use operator(), but you could also use a named member function, perhaps eval(). Let's go with the operator for now.
class Function // Not the best name, but good enough for now.
{
public:
Function(QVector<double> param1, QVector<double> param2, double param3) :
m_a1(std::move(param1)),
m_a2(std::move(param2)),
m_a3(param3)
{}
// This is what will evaluate your function at a given time. This will not
// speed up the execution, but it does help improve data encapsulation.
double operator()(double t)
{
double result = 0.0;
for(int j = 0; j < m_a1.size(); j++)
{
result += m_a1[j] / m_a2()[j] * exp(- m_a3 * t );
}
return result;
}
private:
const QVector<double> m_a1; // Add `const` to these if you want to
const QVector<double> m_a2; // emphasize that they do not change
const double m_a3; // after initialization.
};
All that's happened is some logic got shifted into this class. There is no expected savings in execution time. The savings comes when you try to write your other class.
class CalculFunction
{
public:
CalculFunction(const QVector<Function> & allParam): m_parameters(allParam) {}
void startCalculation(const double & t, const double & initValue)
{
for(int i = 0; i < m_parameters.size(); i++)
m_results.append(m_parameters[i](t) * initValue); // Invoke operator() here
}
private:
QVector<Function> m_parameters;
QVector<double> m_results;
};
The overall code is shorter and more organized, optimizing the programmer's time.

Related

Changing old code which is difficult to understand

My main trouble comes from void setWSparsity(const ExponentialSparsityTemplate(& t)(double wSparsity, double SparsityExp));, t.sparsity(p, _decay), and the "SparsityTemplate" of which there are more than one kind. I either get the header definition to compile and not the code or vice-versa. How should these definitions be properly setup?
The example below does not compile but demonstrates what I am struggling with. I would like to have 2 or more different SparsityTemplates and properly use const and private variables. Initialization was missing and I attempted to add that. The sample takes code from a linear algebra library, so namespaces have been removed.
_Ws as does _t comes from a linear algebra namespace
#include <cmath>
#include "matrix.h"
/**
* Sparsity template with exponential increase depending on the time
* index p.
*/
class Deconvolver
{
class SparsityTemplate
{
public:
virtual double sparsity(double p) const;
virtual ~SparsityTemplate() = default;
};
class ExponentialSparsityTemplate: public SparsityTemplate
{
public:
ExponentialSparsityTemplate(double sparsity, double sparsityexp) :
_sparsity(sparsity), _decay(sparsityexp) {}
virtual ~ExponentialSparsityTemplate() = default;
void setWSparsity(const ExponentialSparsityTemplate(& t)(double wSparsity, double SparsityExp));
private:
double _sparsity = 0;
double _decay = 0;
};
void setWSparsity(const ExponentialSparsityTemplate(& t)(double wSparsity, double SparsityExp));
};
int main()
{
double wSparsity = 0.01;
double wSparsityExp = 1.7;
// The Matrix is 10 x 5 and is filled by a generator function
Matrix x(10, 5, );
Deconvolver d(x, 10, 3);
d.setWSparsity(
ExponentialSparsityTemplate(wSparsity, wSparsityExp));
}
void Deconvolver::setWSparsity(
const ExponentialSparsityTemplate(& t)(double wSparsity, double wSparsityExp))
{
_sparsity = wSparsity * std::pow(sparsityexp, p);
for (unsigned int p = 0; p < _t; ++p)
{
for (unsigned int j = 0; j < _wS[p]->cols(); ++j)
{
for (unsigned int i = 0; i < _wS[p]->rows(); ++i)
_wS[p]->at(i, j) = t.sparsity(p, _decay);
}
}
}
The problem was a combination of things:
C++ Virtual function being hidden
https://www.learncpp.com/cpp-tutorial/constructors-and-initialization-of-derived-classes/
In my project some virtual functions had used the same name as those in the initialization list and as I was trying to initialize and remove unused variables, I had disturbed hidden virtual functions which I hadn't fully understood. The exact same names being used made the code very difficult to follow so I went back to the original code and more slowly applied name changes to private variables and member initialization lists, and then made changes to virtual functions. I used () not {} for parameters in point 2 but the example was helpful as the same name was not used.

operator= overload in C++

I need some help with operator assignment. This is code:
Sinusoid.h:
class Sinusoid : public Component
{
float fs, f, A, fi;
int N;
double *array;
public:
Sinusoid(float fs, float f, float Ts, float fi, float A);
void count(int type=1);
void clear();
~Sinusoid();
double *getArray() { return this->array; }
double*& operator=(Sinusoid* const &rhs) {
return rhs->array;
};
};
main.cpp:
#include "headers.h"
int main()
{
int N = 1000 * 2.5;
Sinusoid *sinus = new Sinusoid(1000, 15, 2.5, (M_PI / 4), 0.7);
double **answers = new double*[7];
for (int i = 0; i < 7; i++) {
answers[i] = new double[N];
}
//lab1
//Zad1
sinus->count(1);
answers[0] = sinus;
return 0;
}
When i build this code i've got the following problem:
C2440 '=': cannot convert from 'Sinusoid *' to 'double *' main.cpp:15
I know that i can assign two classes with overloaded operator "=" but i want to take a private member of class (double *array;). I know that i can do it by "getArray()" method but i want to learn more "beautiful" practice. Hope you will help me.
Thank you.
Your double*& operator=(Sinusoid* const &rhs) operator doesn't do what you apparently think it does.
An operator= member function allows you to have an instance of the class (Sinusoid) on the left side of an assignment and an instance of the parameter type (Sinusoid*) on the right side. So what you wrote would let you do:
Sinusoid* pointer = whatever;
Sinusoid object;
object = pointer;
Obviously that's not what you intended. (And probably not something you'll ever want.)
The return type of the operator= doesn't have any influence on this fundamental usage. All it means is that the result of object = pointer is then a double*&. So it would let you write:
double* foo;
foo = (object = pointer);
And that's still not helpful for what you want.
Since answers[0] is a pointer, there's no way to create a custom assignment operator for it. However the language has a different mechanism which can be used here. You can create an implicit conversion operator for your class so that compiler is allowed to convert/decay it into a different type when reasonable. Try adding the following to your class:
operator double* () {
return rhs->array;
}
That should work for the case you want.
Although personally I don't think there's anything wrong with leaving the usage to require calling getArray() in the first place. Sometimes the clarity of an explicit function call can make it easier to read what's actually going on.
Try...
class Sinusoid : public Component {
...
operator double*() {
return array;
}
and the usage
answers[0] = *sinus;

C++ Using member functions from a similar virtual public class

Suppose I have a bunch of inherited classes like this:
...and they all serve the purpose of making all sorts of polynomials. Class X is mainly a variable tank, classes A, B, etc are all virtual public X and each creates ont type of polynomial, class Y makes the calls. Besides A and B, any other class can be added.
Now, everything works but for a newly added "virtual public" class I need to reuse some member function(s) from other classes, here from A inside class B. I tried to make the simplest example:
#include <iostream>
#include <cmath>
#include <functional>
// variable tank
class X
{
protected:
// general variables
double *m_c;
int m_n;
double m_w;
// funcX related
double m_r;
int m_i {0};
public:
~X() = default;
/* Simple bracketed root-finding. This is called from more than
* one "virtual public" classes.
*/
const double funcX(const double &x, const double &y, \
std::function<const double(const double&, const int&)> fp, \
const int &k)
{
double a {x}, b {y}, fmid;
while (m_i<100)
{
m_r = 0.5*(a + b);
fmid = fp(m_r, k);
if (fabs(b-a) <= 1e-3)
break;
if (fmid < 0)
b = m_r;
else
a = m_r;
++m_i;
}
return m_r;
}
};
// one of the many classes that generate polynomials
class A: virtual public X
{
public:
void funcA(const int &n)
{
// set order
m_n = n;
// calculate X::m_c[i]
m_c = new double[m_n+1];
for (short i=0; i<=m_n>>1; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i<<1] = sgn/((i + 1.0)*(i + 1.0));
}
// The polynomial is zero somewhere, use funcX() to find where.
m_w = funcX(5.0, 0.0, \
[this](const double &x, const int &n) \
{ return calcA(x, n); }, \
m_n);
}
// calculates the value of the polynomial of order n, at x
const double calcA(const double &x, const int &n) const
{
double out {static_cast<double>(m_c[0])};
for (short i=1; i<=n; ++i)
out = m_c[i] + x*out;
return out;
}
};
class B: virtual public X
{
private:
A m_a; // otherwise the lambda function does not "catch" it
public:
void funcB(const int &n)
{
// same as in A
m_n = n;
// same as in A, calculate coefficients
m_c = new double[m_n+1];
for (short i=0; i<=m_n; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i] = sgn/((i + 1)<<1);
}
/* Here I need A::calcA(). Instead of duplicating the code,
* I want to call it through X::funcX(). The code compiles,
* but it crashes.
*/
m_w = funcX(0.5, 1.0, \
[this](const double &x, const int &n) \
{ return m_a.calcA(x, n); }, \
m_n);
}
const double getW() const { return m_w; }
};
class Y: public A, public B
{
public:
Y(const int &n, const int &i)
{
// call one of the "virtual public" classes through i
switch (i)
{
case 1: funcA(n); break;
case 2: funcB(n); break;
}
}
void printC() { for (short i=0; i<=m_n; ++i) std::cout << m_c[i] << '\n'; }
void printW() { std::cout << m_w << '\n'; }
void printA(const double &x, const double &n) { std::cout << A::calcA(x, n) << '\n'; }
};
int main(int argc, char *argv[])
{
int N {6};
Y *y;
for (short i=1; i<=2; ++i)
{
y = new Y(N, i);
y->printC();
y->printW();
y->printA(1.2, N);
}
return 0;
}
class X:
X::funcX() is a simple root-finding algorithm which gets called in more than one virtual public classes (A, B, etc). m_c, m_n, m_w are shared variables.
classes A and B:
their main function is funcA() (and funcB(), and so on) and it creates the polynomial (in the body, there's a for loop), based on the calculated order, X::m_n. Evaluating the polynomial is A::calcA(). This needs to be either called by class B, too, or redefined. I'd rather avoid the latter because of the code bloating. It also doesn't look very "professional" for my fairly beginner level...
class Y
This calls any of the virtual public classes based on argument i (the switch/case).
The code compiles, but crashes. It prints the case for. This example points to A::funcA() as the culprit, but in the original program I can see that the coeficients, m_c[i], are not even initialized with dynamic memory, as in trying to print out m_c[0] crashes. I tried moving the new double[] insode the function in A, but that doesn't work.
I don't know how to make it. Does this make sense, is it possible? If yes, how?
Edit: Forgot to add that I can't just move calcA() from A to the top, in X, because each polynomial is evaluated differently, as in there are shortcuts, changes, in every one that makes it possible to have different, optimized evaluations for each polynomial. I could make X::calcA() a universal one, but there will be a performance penalty, which I'd rather not pay.
It seems that your problem is induced by problems with design. When you need to use methods from other class that may mean:
The is a problem with "single responsibility" principle. Class does too much. For example numerical equation solving algorithms are self-sufficient entities and shouldn't be part of polynomial. They can work with any polynomial.
There is a problem with inheritance tree. For example a common ancestor should be created and that common methods should be in it. Note, that if you can't find short and understandable name for that ancestor, then this is not the solution.
Inheritance is not used properly. For example I can't see virtual methods in your code which is strange.
Let's get closer to your example. You are using virtual multiple inheritance which is considered to be very heavy pattern and usually should not be used. Moreover, there are no virtual methods in your code, so you actually do not use inheritance at all. You either must drop inheritance, or think of common methods which make sense for all your classes. For functions this seems to be an ability to calculate function value in specified point. Then move all code, that is not describing polynomials or functions out of the classes. Move out numerical solvers. This will allow to reuse them for all your classes, that support needed interface. Get rid of Y class at all. It seems, that it is needed to emulate virtual methods with switches and enums. You don't need it, rename funcA and funcB just to func if they are semantically the same and do the same thing for different types of polynomials.

How to store a parametric matrix like a function in C++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have a matrix M, whose each element is dependent on a single variable t in a different quadratic form without the constant.
Just for example,
M[1,1] = 2t^2 + 4t
M[3,2] = t^2 - 5t
M[2,4] = -t^2 + 5t
The matrix is acquired after a series of calculation and each element, or say, the coefficients before t^2 and t, are figured out through a combination of a bunch of other functions.
I was wondering how I can store the matrix like a function M(t) so each time I can call the function to generate a matrix with different t.
Thanks!
UPDATE:
The purpose is to get the smallest eigenvalue of the matrix given different t, so I was thinking I could generate a matrix each time and feed it to a eigenvalue solver to get the smallest eigenvalue for each t.
From my limited understanding, what you are after is a function at specific point, for this, I would use a std::function<double(double)> (i.e. function that takes one double and returns a double (the result.) I guess that's what you are after? And each location of the matrix can be initialized with a lambda - e.g
// Assume my dumb matrix is a 2d vector
vector<vector<function<double(double)>>> matrix;
matrix[1][1] = [](double t) { return /* formula for: 2t^2 + 4t */ ; }
etc.
you should create a class name Matrix and this class has a constructor which has only one parameter t.
// quadratic polynomial
class QuadPoly {
public:
QuadPoly(double _c2, double _c1, double _c0) : c2(_c2), c1(_c1), c0(_c0) {}
// ... other constructors, assignment
double operator()(double t) const {return (c2*t+c1)*t+c0;}
// ... maybe operator+ operator-, if necessary
private:
double c0, c1, c2;
};
// numerical Matrix
template<class T> class Matrix {
public:
// ... constructors, destructor, assignment
const T& operator()(int row, int col) const;
T& operator()(int row, int col);
// ... anything else
friend class QuadPolyMatrix;
private:
int nRows, nCols;
int nVals; // nRows*nCols
double* pVals; // or maybe double**
};
// matrix of quadratic polynomials
class QuadPolyMatrix : public Matrix<QuadPoly> {
public:
Matrix<double> operator() (double t) const;
};
1. Functions hardcoded
If you really need a matrix object, you can make a class with t in constructor and function, which returns values.
class CMatrix {
public:
CMatrix( double t_ ) : t( t_ ) {}
double GetElement( int row, int col ) const {
if( row == 3 && col == 2 ) {
return t * t - t * 5;
} else if( ) ...
}
private:
double t;
};
After that you can construct CMatrix mat( t );
And then get elements by mat.GetElement( 3, 2 );.
2. More versatile variant.
Make typedef of functions (they all have the same signature double f( double t )) and an array of pointers to functions. Then, you can make a SetFunction method, which sets a function in a given coordinate and GetElement calls function in given coordinate with parameter, which is stored in the field (like prev. example). But in this case you must set all needed functions before calling.

compare function in lower bound

I have following structure
enum quality { good = 0, bad, uncertain };
struct Value {
int time;
int value;
quality qual;
};
class MyClass {
public:
MyClass() {
InsertValues();
}
void InsertValues();
int GetLocationForTime(int time);
private:
vector<Value> valueContainer;
};
void MyClass::InsertValues() {
for(int num = 0; num < 5; num++) {
Value temp;
temp.time = num;
temp.value = num+1;
temp.qual = num % 2;
valueContainer.push_back(temp);
}
}
int MyClass::GetLocationForTime(int time)
{
// How to use lower bound here.
return 0;
}
In above code I have been thrown with lot of compile errors. I think I am doing wrong here I am new to STL programming and can you please correct me where is the error? Is there better to do this?
Thanks!
The predicate needs to take two parameters and return bool.
As your function is a member function it has the wrong signature.
In addition, you may need to be able to compare Value to int, Value to Value, int to Value and int to int using your functor.
struct CompareValueAndTime
{
bool operator()( const Value& v, int time ) const
{
return v.time < time;
}
bool operator()( const Value& v1, const Value& v2 ) const
{
return v1.time < v2.time;
}
bool operator()( int time1, int time2 ) const
{
return time1 < time2;
}
bool operator()( int time, const Value& v ) const
{
return time < v.time;
}
};
That is rather cumbersome, so let's reduce it:
struct CompareValueAndTime
{
int asTime( const Value& v ) const // or static
{
return v.time;
}
int asTime( int t ) const // or static
{
return t;
}
template< typename T1, typename T2 >
bool operator()( T1 const& t1, T2 const& t2 ) const
{
return asTime(t1) < asTime(t2);
}
};
then:
std::lower_bound(valueContainer.begin(), valueContainer.end(), time,
CompareValueAndTime() );
There are a couple of other errors too, e.g. no semicolon at the end of the class declaration, plus the fact that members of a class are private by default which makes your whole class private in this case. Did you miss a public: before the constructor?
Your function GetLocationForTime doesn't return a value. You need to take the result of lower_bound and subtract begin() from it. The function should also be const.
If the intention of this call is to insert here, then consider the fact that inserting in the middle of a vector is an O(N) operation and therefore vector may be the wrong collection type here.
Note that the lower_bound algorithm only works on pre-sorted collections. If you want to be able to look up on different members without continually resorting, you will want to create indexes on these fields, possibly using boost's multi_index
One error is that the fourth argument to lower_bound (compareValue in your code) cannot be a member function. It can be a functor or a free function. Making it a free function which is a friend of MyClass seems to be the simplest in your case. Also you are missing the return keyword.
class MyClass {
MyClass() { InsertValues(); }
void InsertValues();
int GetLocationForTime(int time);
friend bool compareValue(const Value& lhs, const Value& rhs)
{
return lhs.time < rhs.time;
}
Class keyword must start from lower c - class.
struct Value has wrong type qualtiy instead of quality
I dont see using namespace std to use STL types without it.
vector<value> - wrong type value instead of Value
Etc.
You have to check it first before posting here with such simple errors i think.
And main problem here that comparison function cant be member of class. Use it as free function:
bool compareValue(const Value lhs, const int time) {
return lhs.time < time ;
}
class is the keyword and not "Class":
class MyClass {
And its body should be followed by semicolon ;.
There can be other errors, but you may have to paste them in the question for further help.
You just want to make compareValue() a normal function. The way you have implemented it right now, you need an object of type MyClass around. The way std::lower_bound() will try to call it, it will just pass in two argument, no extra object. If you really want it the function to be a member, you can make it a static member.
That said, there is a performance penalty for using functions directly. You might want to have comparator type with an inline function call operator:
struct MyClassComparator {
bool operator()(MyClass const& m0, MyClass const& m1) const {
return m0.time < m1.time;
}
};
... and use MyClassComparator() as comparator.