Creating a C ++ function from an argument list

I am writing a function f to be used in the Runge Kutta integral.

output RungeKutta(function f, initial conditions IC, etc.)

Since the function will be called many times, I am looking for a way to generate the function f at compile time.

In this case, the function f depends on a fixed list of parameter vectors p, where p is sparse and fixed before compiling the code. To be specific,

double function f(vector<double> x) {
    return x dot p;
}

Since it is psparse, point-to-point in is fnot the most effective. Hard coding is x dot psimilar to a method, but p can be very long (1000).

What are my options?

Writes another program (taking pas input) to generate a .cpp file just for me?

Thanks for the comments. Here is a more specific example for a differential equation.

dy / dx = f_p (x)

f_p (x):

p = [0, 1, 0]; x = [x1, x2, x3]

double f_p(vector<double> x) {
     return x2;  // This is what I meant by hard-coding
}

:

   double f(vector<double> p, vector<double> x) {
       double r = 0;
       for (i=0; i < p.length(); i++) {
              r += p[i]*x[i];
        }
        return r;
   }
+4
3

, , , "" , , . , , , , , .

++ , : . ++ (.. Turing) , , .

( , http://ideone.com/BDtBt7). , . , / . , , p . , . , , , .

#include <array>
#include <iostream>
#include <vector>

constexpr std::array<double, 5> p = { 1.0, 0.0, 3.0, 5.0, 0.0 };

template<size_t index, bool isZero>
struct DotProductCalculator
{
    static double Calculate(const std::vector<double>& xArg)
    {
        return (xArg[index] * p[index]) 
            + DotProductCalculator<index - 1, p[index - 1] == 0.0>::Calculate(xArg);
    }
};

template<>
struct DotProductCalculator<0, true>
{
    static double Calculate(const std::vector<double>& xArg)
    {
        return 0.0;
    }
};

template<>
struct DotProductCalculator<0, false>
{
    static double Calculate(const std::vector<double>& xArg)
    {
        return xArg[0] * p[0];
    }
};

template<size_t index>
struct DotProductCalculator<index, true>
{
    static double Calculate(const std::vector<double>& xArg)
    {
        return 0.0 + DotProductCalculator<index - 1, p[index - 1] == 0.0>::Calculate(xArg);
    }
};

template<typename ArrayType>
double f_p_driver(const std::vector<double>& xArg, const ArrayType& pAsArgument) 
{
     return DotProductCalculator<std::tuple_size<ArrayType>::value - 1, 
                            p[std::tuple_size<ArrayType>::value -1] == 0.0>::Calculate(xArg); 
}

int main() 
{
    std::vector<double> x = { 1.0, 2.0, 3.0, 4.0, 5.0 };
    double result = f_p_driver(x, p);
    std::cout << "Result: " << result;
    return 0;
}
+3

, p . : , , "", , , , , 0. 10% , -, , , .

, p , :

class dotProduct {
    std::vector<double> p;
public:
    dotProduct(std::vector<double> const& p): p(p) {}
    double operator()(std::vector<double> const& x) const {
        return std::inner_product(p.begin(), p.end(), x.begin());
    }
};
// ...
... RungeKutta(dotProduct(p), initial conditions IC, etc.);

++ 11 :

... RungeKutta([=](std::vector<double> const& x) {
        return std::inner_product(p.begin(), p.end(), x.begin());
    }, intitial conditions IC, etc.);

std::vector<std::pair<double, std::size_t>>, , :

class sparseDotProduct {
    typedef std::vector<std::pair<double, std::size_t>> Vector;
    Vector p;
public:
     sparsedotProduct(std::vector<double> const& op) {
         for (std::size_t i(0), s(op.size()); i != s; ++i) {
             if (op[i]) {
                 p.push_back(std::make_pair(op[i], i));
             }
         }
     }
     double operator()(std::vector<double> const& x) {
         double result(0);
         for (Vector::const_iterator it(p.begin()), end(p.end()); it != end; ++it) {
             result += it->first * x[it->second];
         }
         return result;
     }
};

, , p .

, , 10% . . , , . , - , , .

+2

, P , . , , "" - , :

| a1 b1  0  0  0  0  0 d1 |
| c1 a2 b2  0  0  0  0  0 |
| 0  c2 a3 b3  0  0  0  0 |
| 0  0  c3 a4 b4  0  0  0 |
| 0  0  0  c4 a5 b5  0  0 |
| 0  0  0  0  c5 a6 b6  0 |
| 0  0  0  0  0  c6 a7 b7 |
| e1 0  0  0  0  0  c7 a8 |

/, :

A = [a1, a2, a3, a4, a5, a6, a7, a8]
B = [b1, b2, b3, b4, b5, b6, b7]
C = [c1, c2, c3, c4, c5, c6, c7]
D = [d1]
E = [e1]

X = [x1, x2, x3, x4, x5, x6, x7, x8] :

Y = X . M

Y[0] =               X[0] * A[0] + X[1] * C[0] + X[7] * E[0]
Y[1] = X[0] * B[0] + X[1] * A[1] + X[2] * C[1]

.

:

Y[i] = X[i-7] * D[i] + X[i-1] * B[i] + X[i] * A[i] + X[i+1] * C[i] + X[i+7] * E[i]

In cases where access to arrays is out of range ( < 0or >= 8should be considered as being evaluated as 0. In order not to damage the check out of bounds, you can actually save each diagonal and the vector itself in large arrays that have leading and trailing elements filled with zeros .

Note that this will also cache heavily, since all calls to the array are linear.

+1
source

All Articles