2012-07-31

SCIP in C++11 ― 1.3.1節その1


1.3.1節 引数としての手続き

最初は懸命にファンクタ使って、抽象ファンクタテンプレートを作り、スライシングに悩み、std::functionテンプレートクラスの使い方に悩み、後でラムダ出るしなあとテストしてもうまく行かなくてとか散々悩んで何度もコードを書き直し。
ラムダだけで押したらどうなるのかなと試してみたらなんと、すっげえよラムダ、ヤバイよラムダ、ラムダかわいいよラムダ。コードが一気にコンパクト化。これでやっと少し光が見えてきたか。

総和手続きと問題1.29
--------
template<typename TermResult, typename TermArgument,
         typename NextResult,typename NextArgument>
const TermResult sum
(const function<TermResult(TermArgument)>& term,
 const NextArgument& lower,
 const function<NextResult(NextArgument)>& next,
 const NextArgument& upper)
{
    if(lower>upper){return(0.0);}
    return(term(lower)+sum(term,next(lower),next,upper));
}

const function<int(int)> identity=
    [](const int x){return(x);};
const function<int(int)> increment=
    [](const int x){return(x+1);};

template<typename ResultType>
const ResultType squareFun(const ResultType x){return(x*x);}
template<typename ResultType>
const ResultType cubeFun(const ResultType x){return(pow(x,3));}

function<double(double)> piTerm=
    [](const double x){return(1.0/x/(x+2.0));};
function<double(double)> piNext=
    [](const double x){return(x+4);};
const int sumIntegers(const int lower, const int upper)
{
    return(sum(identity, lower,increment, upper));
}
const int sumSquareIntegers(const int lower, const int upper)
{
    const function<int(int)> square=squareFun<int>;
    return(sum(square, lower, increment, upper));
}
const double piSum(const int lower,const int upper)
{
    return(sum(piTerm,static_cast<double>(lower),
               piNext,static_cast<double>(upper))*8.0);
}

const double integral
(const function<double(double)>& f,
 const double lower, const double upper, const double dx)
{
    const function<double(double)> addDx
        =[dx](const double x){return(x+dx);};
    return(sum(f, lower+dx/2.0, addDx, upper)*dx);
}

const double simpsonIntegral
(const function<double(double)>& f,
 const double lower, const double upper, const double dx)
{
    const function<double(double)> add2Dx
        =[dx](const double x){return(x+2.0*dx);};
    const function<double(double)> simpsonF=[dx,&f](const double x){
        return(f(x-dx)+4.0*f(x)+f(x+dx));
    };
    return(sum(simpsonF, lower+dx, add2Dx, upper)*dx/3.0);
}

int main(int argc, char** argv)
{
    int lower(1);
    int upper(1000);

    cout<<"sum_{i="<<lower<<"}^{"<<upper
        <<"} i="<<sumIntegers(lower,upper)<<endl;
    upper=10;
    cout<<"sum_{i="<<lower<<"}^{"<<upper
        <<"} i^2="<<sumSquareIntegers(lower,upper)<<endl;
    upper=1000;
    cout<<"sum_{i="<<lower<<"}^{"<<upper
        <<"} 1/((4i+1)(4i+3))="<<piSum(lower,upper)<<endl;

    lower=0;
    upper=1;
    const double dx(0.001);
    const function<double(double)> cube=cubeFun<double>;
    cout<<setprecision(16)<<"integral_{"<<lower
        <<"}^{"<<upper<<"} cube(x) dx="
        <<integral(cube,static_cast<double>(lower),
                   static_cast<double>(upper),dx)<<endl;
    cout<<endl<<"Problem 1.29:"<<endl;
    cout<<setprecision(16)<<"integral_{"<<lower
        <<"}^{"<<upper<<"} cube(x) dx="
        <<simpsonIntegral(cube,static_cast<double>(lower),
        static_cast<double>(upper),dx)<<endl;
   
    return(0);
}
----
出力
----
sum_{i=1}^{1000} i=500500
sum_{i=1}^{10} i^2=385
sum_{i=1}^{1000} 1/((4i+1)(4i+3))=3.13959
integral_{0}^{1} cube(x) dx=0.2499998750000006
integral_{0}^{1} cube(x) dx=0.2500000000000006

0 件のコメント :

コメントを投稿