Integrate function with arguments using quadrature

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Integrate function with arguments using quadrature

Boost - Users mailing list
Hello,

I'm trying to integrate functions with BOOST quadrature routines. So far they have been extremely impressive accuracy-wise, particularly with multiprecision features.

I wish to integrate a function and pass some arguments to it. These arguments can be scalars, matrices, structs or objects. I was wondering if there is an example that explores this. Would I need to use a boost.function? Or would a function pointer work?

I currently have an implementation using GSL_functions which explicitly allow the function and parameters to be passed as pointers. I am curious if I can do something similar with boost.

Thank you.


--
Anirban Pal




_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: Integrate function with arguments using quadrature

Boost - Users mailing list

 

 

From: Boost-users <[hidden email]> On Behalf Of Anirban Pal via Boost-users
Sent: 14 August 2020 22:57
To: [hidden email]
Cc: Anirban Pal <[hidden email]>
Subject: [Boost-users] Integrate function with arguments using quadrature

 

Hello,

 

I'm trying to integrate functions with BOOST quadrature routines. So far they have been extremely impressive accuracy-wise, particularly with multiprecision features.

 

I wish to integrate a function and pass some arguments to it. These arguments can be scalars, matrices, structs or objects. I was wondering if there is an example that explores this. Would I need to use a boost.function? Or would a function pointer work?

 

I currently have an implementation using GSL_functions which explicitly allow the function and parameters to be passed as pointers. I am curious if I can do something similar with boost.

 

I suspect so.

 

Are these example any help to you?

 


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: Integrate function with arguments using quadrature

Boost - Users mailing list
In reply to this post by Boost - Users mailing list

On 14/08/2020 22:56, Anirban Pal via Boost-users wrote:

> Hello,
>
> I'm trying to integrate functions with BOOST quadrature routines. So
> far they have been extremely impressive accuracy-wise, particularly
> with multiprecision features.
>
> I wish to integrate a function and pass some arguments to it. These
> arguments can be scalars, matrices, structs or objects. I was
> wondering if there is an example that explores this. Would I need to
> use a boost.function? Or would a function pointer work?

To create a reusable single-valued functor that integrates from [a, x]
for fixed a, then I think some nested lambda expressions would work:

    auto integral = [](double x)
    {  // Integrates from 0 to x:
       static tanh_sinh<double> integrator;
       static auto f = [](double x) { return 5 * x + 7; };
       return integrator.integrate(f, 0.0, x);
    };
    std::cout << integral(2) << std::endl;
    std::cout << integral(4.5) << std::endl;

I'm not sure what you had in mind with non-scalar arguments, but if you
need to evaluate the above at multiple x values [x_1, x_2.... x_n] then
conceivably you could integrate from

[a, x_0]

[x_1, x_2]

....

[x_n-1, x_n]

and then sum to get the integrals

[a, x_0]

[a, x_1]

....

[a, x_n]

Which may or may not be more efficient.

HTH, John.

>
> I currently have an implementation using GSL_functions which
> explicitly allow the function and parameters to be passed as pointers.
> I am curious if I can do something similar with boost.
>
> Thank you.
>
>
> --
> Anirban Pal
>
>
>
>
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> https://lists.boost.org/mailman/listinfo.cgi/boost-users

--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: Integrate function with arguments using quadrature

Boost - Users mailing list

Thank you John and Paul for your responses. Allow me to be more clear.

I’m considering something like the following function f0, which depends on x and some additional arguments given by the vector A. The vector A is unknown at compile time and computed during execution. The function f0 is to be integrated at a constant value for A (computed at runtime) with a range for x. The range is also computed at runtime, but it can be explicitly passed to the integrator.integrate call.

Lambda expressions seem to be the way to go. However, lambda expressions do not seem to easily capture local variables. In the following code, I've managed to get a lambda expression for the function f(x) = f0(x,A) and I can integrate that. However, I can only use the global variable B_global instead of B_local.

#include <iostream>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/math/quadrature/tanh_sinh.hpp>
#include <boost/bind/bind.hpp>
#include <functional>

typedef boost::multiprecision::cpp_bin_float_100 Real;

Real B_global[] = {0.0, 0.5, 1.0};

Real f0 (Real x, Real *A)
{
    return x*( A[0]*A[0] + A[1]*A[1] + A[2]*A[2] );
}

int main(int argc, char **argv)
{
    using namespace boost::math::quadrature;
    using namespace std::placeholders;
    tanh_sinh<Real> integrator;

    Real *B_local; B_local = (Real *)malloc(3*sizeof(Real));
    B_local[0] = 0.0; B_local[1] = 0.5, B_local[2] = 1.0;

    auto f = [](Real x) { return std::bind(f0, _1, B_global)(x); }; //If I use B_local, I get the error: ‘B_local’ is not captured
    Real Q = integrator.integrate(f, 0.0, 1.0);

    std::cout << std::setprecision(std::numeric_limits<Real>::max_digits10)
     << "Comp.: " << Q << std::endl;

    return 0;
}



I figured I need to use boost::bind.
Also, I wanted to use boost:bind but I was unsuccessful. So I retreated to std::bind for now.

Thank you.


On Sun, 16 Aug 2020 at 06:51, John Maddock via Boost-users <[hidden email]> wrote:

On 14/08/2020 22:56, Anirban Pal via Boost-users wrote:
> Hello,
>
> I'm trying to integrate functions with BOOST quadrature routines. So
> far they have been extremely impressive accuracy-wise, particularly
> with multiprecision features.
>
> I wish to integrate a function and pass some arguments to it. These
> arguments can be scalars, matrices, structs or objects. I was
> wondering if there is an example that explores this. Would I need to
> use a boost.function? Or would a function pointer work?

To create a reusable single-valued functor that integrates from [a, x]
for fixed a, then I think some nested lambda expressions would work:

    auto integral = [](double x)
    {  // Integrates from 0 to x:
       static tanh_sinh<double> integrator;
       static auto f = [](double x) { return 5 * x + 7; };
       return integrator.integrate(f, 0.0, x);
    };
    std::cout << integral(2) << std::endl;
    std::cout << integral(4.5) << std::endl;

I'm not sure what you had in mind with non-scalar arguments, but if you
need to evaluate the above at multiple x values [x_1, x_2.... x_n] then
conceivably you could integrate from

[a, x_0]

[x_1, x_2]

....

[x_n-1, x_n]

and then sum to get the integrals

[a, x_0]

[a, x_1]

....

[a, x_n]

Which may or may not be more efficient.

HTH, John.

>
> I currently have an implementation using GSL_functions which
> explicitly allow the function and parameters to be passed as pointers.
> I am curious if I can do something similar with boost.
>
> Thank you.
>
>
> --
> Anirban Pal
>
>
>
>
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> https://lists.boost.org/mailman/listinfo.cgi/boost-users

--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--
Anirban Pal




_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: Integrate function with arguments using quadrature

Boost - Users mailing list
In you lambda expression, you have to capture B_local :

    auto f = [&](Real x) { return std::bind(f0, _1, B_local)(x); };

The [&] tells the compiler to capture variables by reference automatically.

On Mon, Aug 17, 2020 at 2:26 AM Anirban Pal via Boost-users <[hidden email]> wrote:

Thank you John and Paul for your responses. Allow me to be more clear.

I’m considering something like the following function f0, which depends on x and some additional arguments given by the vector A. The vector A is unknown at compile time and computed during execution. The function f0 is to be integrated at a constant value for A (computed at runtime) with a range for x. The range is also computed at runtime, but it can be explicitly passed to the integrator.integrate call.

Lambda expressions seem to be the way to go. However, lambda expressions do not seem to easily capture local variables. In the following code, I've managed to get a lambda expression for the function f(x) = f0(x,A) and I can integrate that. However, I can only use the global variable B_global instead of B_local.

#include <iostream>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/math/quadrature/tanh_sinh.hpp>
#include <boost/bind/bind.hpp>
#include <functional>

typedef boost::multiprecision::cpp_bin_float_100 Real;

Real B_global[] = {0.0, 0.5, 1.0};

Real f0 (Real x, Real *A)
{
    return x*( A[0]*A[0] + A[1]*A[1] + A[2]*A[2] );
}

int main(int argc, char **argv)
{
    using namespace boost::math::quadrature;
    using namespace std::placeholders;
    tanh_sinh<Real> integrator;

    Real *B_local; B_local = (Real *)malloc(3*sizeof(Real));
    B_local[0] = 0.0; B_local[1] = 0.5, B_local[2] = 1.0;

    auto f = [](Real x) { return std::bind(f0, _1, B_global)(x); }; //If I use B_local, I get the error: ‘B_local’ is not captured
    Real Q = integrator.integrate(f, 0.0, 1.0);

    std::cout << std::setprecision(std::numeric_limits<Real>::max_digits10)
     << "Comp.: " << Q << std::endl;

    return 0;
}



I figured I need to use boost::bind.
Also, I wanted to use boost:bind but I was unsuccessful. So I retreated to std::bind for now.

Thank you.


On Sun, 16 Aug 2020 at 06:51, John Maddock via Boost-users <[hidden email]> wrote:

On 14/08/2020 22:56, Anirban Pal via Boost-users wrote:
> Hello,
>
> I'm trying to integrate functions with BOOST quadrature routines. So
> far they have been extremely impressive accuracy-wise, particularly
> with multiprecision features.
>
> I wish to integrate a function and pass some arguments to it. These
> arguments can be scalars, matrices, structs or objects. I was
> wondering if there is an example that explores this. Would I need to
> use a boost.function? Or would a function pointer work?

To create a reusable single-valued functor that integrates from [a, x]
for fixed a, then I think some nested lambda expressions would work:

    auto integral = [](double x)
    {  // Integrates from 0 to x:
       static tanh_sinh<double> integrator;
       static auto f = [](double x) { return 5 * x + 7; };
       return integrator.integrate(f, 0.0, x);
    };
    std::cout << integral(2) << std::endl;
    std::cout << integral(4.5) << std::endl;

I'm not sure what you had in mind with non-scalar arguments, but if you
need to evaluate the above at multiple x values [x_1, x_2.... x_n] then
conceivably you could integrate from

[a, x_0]

[x_1, x_2]

....

[x_n-1, x_n]

and then sum to get the integrals

[a, x_0]

[a, x_1]

....

[a, x_n]

Which may or may not be more efficient.

HTH, John.

>
> I currently have an implementation using GSL_functions which
> explicitly allow the function and parameters to be passed as pointers.
> I am curious if I can do something similar with boost.
>
> Thank you.
>
>
> --
> Anirban Pal
>
>
>
>
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> https://lists.boost.org/mailman/listinfo.cgi/boost-users

--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--
Anirban Pal



_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: Integrate function with arguments using quadrature

Boost - Users mailing list
Thank you John and Kila.

On Thu, 20 Aug 2020 at 00:42, kila suelika via Boost-users <[hidden email]> wrote:
In you lambda expression, you have to capture B_local :

    auto f = [&](Real x) { return std::bind(f0, _1, B_local)(x); };

The [&] tells the compiler to capture variables by reference automatically.

On Mon, Aug 17, 2020 at 2:26 AM Anirban Pal via Boost-users <[hidden email]> wrote:

Thank you John and Paul for your responses. Allow me to be more clear.

I’m considering something like the following function f0, which depends on x and some additional arguments given by the vector A. The vector A is unknown at compile time and computed during execution. The function f0 is to be integrated at a constant value for A (computed at runtime) with a range for x. The range is also computed at runtime, but it can be explicitly passed to the integrator.integrate call.

Lambda expressions seem to be the way to go. However, lambda expressions do not seem to easily capture local variables. In the following code, I've managed to get a lambda expression for the function f(x) = f0(x,A) and I can integrate that. However, I can only use the global variable B_global instead of B_local.

#include <iostream>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/math/quadrature/tanh_sinh.hpp>
#include <boost/bind/bind.hpp>
#include <functional>

typedef boost::multiprecision::cpp_bin_float_100 Real;

Real B_global[] = {0.0, 0.5, 1.0};

Real f0 (Real x, Real *A)
{
    return x*( A[0]*A[0] + A[1]*A[1] + A[2]*A[2] );
}

int main(int argc, char **argv)
{
    using namespace boost::math::quadrature;
    using namespace std::placeholders;
    tanh_sinh<Real> integrator;

    Real *B_local; B_local = (Real *)malloc(3*sizeof(Real));
    B_local[0] = 0.0; B_local[1] = 0.5, B_local[2] = 1.0;

    auto f = [](Real x) { return std::bind(f0, _1, B_global)(x); }; //If I use B_local, I get the error: ‘B_local’ is not captured
    Real Q = integrator.integrate(f, 0.0, 1.0);

    std::cout << std::setprecision(std::numeric_limits<Real>::max_digits10)
     << "Comp.: " << Q << std::endl;

    return 0;
}



I figured I need to use boost::bind.
Also, I wanted to use boost:bind but I was unsuccessful. So I retreated to std::bind for now.

Thank you.


On Sun, 16 Aug 2020 at 06:51, John Maddock via Boost-users <[hidden email]> wrote:

On 14/08/2020 22:56, Anirban Pal via Boost-users wrote:
> Hello,
>
> I'm trying to integrate functions with BOOST quadrature routines. So
> far they have been extremely impressive accuracy-wise, particularly
> with multiprecision features.
>
> I wish to integrate a function and pass some arguments to it. These
> arguments can be scalars, matrices, structs or objects. I was
> wondering if there is an example that explores this. Would I need to
> use a boost.function? Or would a function pointer work?

To create a reusable single-valued functor that integrates from [a, x]
for fixed a, then I think some nested lambda expressions would work:

    auto integral = [](double x)
    {  // Integrates from 0 to x:
       static tanh_sinh<double> integrator;
       static auto f = [](double x) { return 5 * x + 7; };
       return integrator.integrate(f, 0.0, x);
    };
    std::cout << integral(2) << std::endl;
    std::cout << integral(4.5) << std::endl;

I'm not sure what you had in mind with non-scalar arguments, but if you
need to evaluate the above at multiple x values [x_1, x_2.... x_n] then
conceivably you could integrate from

[a, x_0]

[x_1, x_2]

....

[x_n-1, x_n]

and then sum to get the integrals

[a, x_0]

[a, x_1]

....

[a, x_n]

Which may or may not be more efficient.

HTH, John.

>
> I currently have an implementation using GSL_functions which
> explicitly allow the function and parameters to be passed as pointers.
> I am curious if I can do something similar with boost.
>
> Thank you.
>
>
> --
> Anirban Pal
>
>
>
>
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> https://lists.boost.org/mailman/listinfo.cgi/boost-users

--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--
Anirban Pal



_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--
Anirban Pal




_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users