开发者

<functional> (nested bind) problems with MSVC 2010

I have the following code (I'm sorry for the lengthiness):

double primeValue( const func1D &func,
                   const double lowerBound, const double upperBound,
                   const double pole )
{
    // check bounds
    if( lowerBound >= upperBound )
        throw runtime_error( "l开发者_如何转开发owerBound must be smaller than upperBound!" );

    // C++0x way of writing: fullFunc(x) = func(x)/(x-a)
    func1D fullFunc =
            bind( divides<double>(),              // division of
                  bind(func, _1),                 // f(x), with _1 = x
                  bind(minus<double>(), _1, pole) ); // by x-a, with _1 = x

    // pole not in domain
    if( pole<lowerBound || pole>upperBound)
    {
        cout << "Case 1" << endl;
        return integrateSimpson( fullFunc, 1000, lowerBound, upperBound );
    }
    // pole closer to upper bound
    else if( upperBound-pole < pole-lowerBound  )
    {
       cout << "Case 2" << endl;
       // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
       func1D specialFirstFunc =
                bind( std::divides<double>(),                               // division of
                      bind(minus<double>(),                                 // numerator:
                           bind(func, _1),                                  // f(x) minus
                           bind(func, bind(minus<double>(), 2.*pole, _1))), //f(2a-x)
                      bind(minus<double>(), _1, pole) );                    // denominator: x-a
        const double trickyPart = integrateSimpson( specialFirstFunc, 1000, pole+.000001, upperBound );

        const double normalPart = integrateSimpson( fullFunc, 1000, lowerBound, 2.*pole-upperBound );
        cout << "Tricky part: " << trickyPart << endl;
        cout << "Normal part: " << normalPart << endl;
        return trickyPart + normalPart;
    }
    else // pole closer to lower bound
    {
        cout << "Case 3" << endl;
        // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
        func1D specialFirstFunc =
                 bind( std::divides<double>(),                               // division of
                       bind(minus<double>(),                                 // numerator:
                            bind(func, _1),                                  // f(x) minus
                            bind(func, bind(minus<double>(), 2.*pole, _1))), //f(2a-x)
                       bind(minus<double>(), _1, pole) );                    // denominator: x-a
         const double trickyPart = integrateSimpson( specialFirstFunc, 1000, lowerBound, pole-.00001 );

         const double normalPart = integrateSimpson( fullFunc, 1000, 2.*pole-lowerBound, upperBound );
         cout << "Tricky part: " << trickyPart << endl;
         cout << "Normal part: " << normalPart << endl;
         return trickyPart + normalPart;
    }
}

It integrates functions over the real axis that contain a singularity (pole) using the principal values concept from the math domain of Complex Analysis. The bind and function parts modify the original function f(x) to

(f(x)-f(2*pole-x))/(x-a)

It even gives he correct result for my simple test case function. Additional details I can provide if requested:

typedef std::function<double (double)> func1D;
double integrateSimpson( func1D, const size_t nSteps, const double lowerBound, const double upperBound);

The latter integrates using the simple Simpson integration rule. Code can be provided, but isn't very relevant to the problem at hand.

This compiles fine with GCC 4.4+ (tested with 4.4.5 and 4.5.2 prerelease, CFLAGS="-O2 -std=c++0x -pedantic -Wall -Wextra"), but produces internal header errors (C2664) on MSVC 2010. (I can provide error output if needed, there are no references at all to my code (!)).

Have I found a bug in MSVC?

Thanks!


Why not just use a lambda? All of the binding stuff has been deprecated for this kind of purpose.

double primeValue( const func1D &func,
                   const double lowerBound, const double upperBound,
                   const double pole )
{
    // check bounds
    if( lowerBound >= upperBound )
        throw runtime_error( "lowerBound must be smaller than upperBound!" );

    // C++0x way of writing: fullFunc(x) = func(x)/(x-a)
    auto fullFunc = [=](double d) {
        return func(d) / (d - pole);
    };

    // pole not in domain
    if( pole<lowerBound || pole>upperBound)
    {
        cout << "Case 1" << endl;
        return integrateSimpson( fullFunc, 1000, lowerBound, upperBound );
    }
    // pole closer to upper bound
    else if( upperBound-pole < pole-lowerBound  )
    {
       cout << "Case 2" << endl;
       // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
       auto specialFirstFunc = [=](double x) -> double {
           double numerator = func(x) - func(2*pole - x);
           return numerator / (x - pole);
       };
        const double trickyPart = integrateSimpson( specialFirstFunc, 1000, pole+.000001, upperBound );

        const double normalPart = integrateSimpson( fullFunc, 1000, lowerBound, 2.*pole-upperBound );
        cout << "Tricky part: " << trickyPart << endl;
        cout << "Normal part: " << normalPart << endl;
        return trickyPart + normalPart;
    }
    else // pole closer to lower bound
    {
        cout << "Case 3" << endl;
        // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
       auto specialFirstFunc = [=](double x) -> double {
           double numerator = func(x) - func(2*pole - x);
           return numerator / (x - pole);
       };
         const double trickyPart = integrateSimpson( specialFirstFunc, 1000, lowerBound, pole-.00001 );

         const double normalPart = integrateSimpson( fullFunc, 1000, 2.*pole-lowerBound, upperBound );
         cout << "Tricky part: " << trickyPart << endl;
         cout << "Normal part: " << normalPart << endl;
         return trickyPart + normalPart;
    }
}

As for whether or not you actually found a bug in MSVC, I don't know, but your solution is definitely way unnecessary - this code is far cleaner and easier to maintain.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜