1

I have this C++ program:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cmath>

using namespace std;

double dx2(int t, int x, int dx)
{
    return (-9.8*cos(x));
}

int square(int x) 
{
    return (x*x);
}

double RK4(float t, float x, float dx, float h)
{
    double k1, k2, k3, k4, l1, l2, l3, l4, diff1, diff2;
    k1 = h*dx2(t,x,dx);
    l1 = h*k1;
    k2 = h*dx2(t+h/2,x+l1/2,dx+k1/2);
    l2 = h*k2;
    k3 = h*dx2(t+h/2,x+l2/2,dx+k2/2);
    l3 = h*k3;
    k4 = h*dx2(t+h,x+l3,dx+k3);
    l4 = h*k4;
    diff1 = (l1+2*l2+2*l3+l4)/float(6);
    diff2 = (k1+2*k2+2*k3+k4)/float(6);
    double OUT[] = {diff1, diff2};
    return OUT;
}

int main()
{
    double diff, t, t0, t1, x, x0, dx, dx0, h, N;
    N = 1000;
    t0 = 0;
    t  = t0;
    t1 = 10;
    x0 = 0;
    x  = x0;
    dx0 = 0;
    dx  = dx0;
    h = (t1 - t0) / float(N);

    for(int i = 1; i<=N; i++) {
        diff = RK4(t,x,dx,h);
        x = x + diff;
        t = t + h;
    }
    cout << diff;
    return 0;
}

As you can see in this program I am solving the 2nd-order differential equation (if there is a way to insert LaTeX equations into my question please tell me):

d2x/dt2= -9.8 cos(x)

which is an example of the simple pendulum's equations of motion. The problem lines are 33 and 34. In it I am attempting to define the first element of the OUT array as diff1 and the second element as diff2. Whenever I compile this program (named example.cpp) I get the error:

g++ -Wall -o "example" "example.cpp" (in directory: /home/fusion809/Documents/CodeLite/firstExample)
example.cpp: In function ‘double RK4(float, float, float, float)’:
example.cpp:33:9: error: cannot convert ‘double*’ to ‘double’ in return
  return OUT;
         ^~~
Compilation failed.
3
  • Can you create an array of enum? Commented Jul 11, 2016 at 4:18
  • 3
    Whoever downvotes questions like this, please be so kind as to leave a note why. Thank you. To me, it sounds alright, even though it's asking what might look obvious to an experienced C++ programmer. Remember that science people don't necessarily know programming languages. Commented Jul 11, 2016 at 4:58
  • Well, most code seems to be irrelevant to the problem, whatever that is. That, combined with the title, makes it unclear what the question is about. Commented Jul 11, 2016 at 6:11

3 Answers 3

3

Exactly, since you're returning an array of double's, that decays to double*, but the function is defined to return double. An array of type T and the type T are different types in C++, and they can't be converted between, generally speaking.

In this case, you might be better off with a std::pair<T1, T2> (#include <utility>) since you're using C++ and the standard library, or a structure with two fields of type double. Look up std::pair<> and std::tie<>, the former being used to make pairs of elements of different types, and the latter being used to make tuples of different types of arbitrary size.

When you write the std::pair's elements to std::cout, use the first, second members to access the pair's fields. A std::pair can't be directly output using the overloaded stream operator for std::cout.

Edit:

#include <utility>

std::pair<double, double> RK4(float t, float x, float dx, float h)
{
    /* snip */
    diff1 = (l1+2*l2+2*l3+l4)/float(6);
    diff2 = (k1+2*k2+2*k3+k4)/float(6);
    return {diff1, diff2};
}

int main()
{
    double x, dx;
    /* snip */
    for(int i = 1; i<=N; i++) {
        std::pair<double, double> diff = RK4(t,x,dx,h);
        // or use with C++11 and above for brevity
        auto diff = RK4(t,x,dx,h);
        x = x + diff.first;
        dx = dx + diff.second;
        t = t + h;
    }
    cout << x << " " << dx << "\n" ;
    return 0;
}
Sign up to request clarification or add additional context in comments.

9 Comments

first and second are public data members, not functions.
Sorry, I keep confusing that. Thank you for the note.
OK. I'm trying to follow what you mean, it's just I'm trying to keep in mind exactly what this means I need to do to my code... Your answer seems too theoretical rather than applied, could you per chance show me how it should be implemented with my previous example?
Can you please clarify what you mean by adding an array of two doubles to the diff variable of type double in main()? Adding an array to a scalar variable makes little sense. This information is required for me to provide a definition of main(), as currently I can't seem to figure out what is being added to diff.
You mean the x=x+diff? Well I probably should rewrite it to x=x+diff[1] and dx=dx+diff[2]. I just do not know how to add the first element of diff to the scalar, x, and the second element of diff to dx.
|
1

The return type of your RK4 function is double, which is a single value, but you're trying to return an array of two of them. That won't work. You could change the return type to double* and use new double[2] to allocate an array, but it'd be simpler and safer to use std::pair<double, double> as the return type. Then you can just do return { diff1, diff2 };.

5 Comments

Changing 33 / 34 to return { diff1, diff2 }; gives: g++ -Wall -o "example" "example.cpp" (in directory: /home/fusion809/Documents/CodeLite/firstExample) example.cpp: In function ‘double RK4(float, float, float, float)’: example.cpp:32:24: error: cannot convert ‘<brace-enclosed initializer list>’ to ‘double’ in return return { diff1, diff2 }; ^ Compilation failed.
You need to first change the return type to std::pair<double, double>.
How? I am new to C++, sorry if what I am asking seems trivial to you, I'm just trying my best to pick up this language.
Just change the double RK4 to std::pair<double, double> RK4 at the top of the function. That's the part that says what type of data the function returns.
See this answer or my answer below. What exactly can't you understand?
1

To return several values from function you have several choice:

  • as all you returned type are identical, you may return array:

    std::array<double, 2> RK4(float t, float x, float dx, float h)
    {
        // ...
        return {{diff1, diff2}};
    }
    

    or std::vector

    std::vector<double> RK4(float t, float x, float dx, float h)
    {
        // ...
        return {{diff1, diff2}};
    }
    
  • You may return std::tuple or std::pair (limited to 2 elements):

    std::pair<double, double> RK4(float t, float x, float dx, float h)
    {
        // ...
        return {{diff1, diff2}};
    }
    

    or

    std::tuple<double, double> RK4(float t, float x, float dx, float h)
    {
        // ...
        return {{diff1, diff2}};
    }
    
  • You may also create a custom class

    struct RK4Result
    {
        double diff1;
        double diff2;
    };
    
    RK4Result RK4(float t, float x, float dx, float h)
    {
        // ...
        return {diff1, diff2};
    }
    
  • And for type expensive to move, you may use any previous method, but by out parameters:

    struct RK4Result
    {
        double diff1;
        double diff2;
    };
    
    void RK4(float t, float x, float dx, float h, RK4Result& res)
    {
        // ...
        res = {diff1, diff2};
    }
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.