2012-09-10

SCIP in C++11 ― 2.4節その4


メッセージパッシングと問題2.75

メッセージパッシングだとこんなにコンパクトになるのかー。
ただ、関数で複素数を表現している分、基礎の部分をしっかり作っていないと、
この上にさらにモノを載せるのは、C++では結構大変かもしれない。
メッセージパッシングは3章で頻繁に使うだけに、
自前のListのコードを見なおしておかないとなあ。

実部、虚部といった内部パラメターをもったデータの表現というと、
配列なり構造体なりクラスなり作って、そのメンバにデータを入れるというのしか、
今まで考えたことがなかった。
が、ここでは2.1.3節でChurch数をやった時のように、関数でデータが表現され、
内部パラメターはクロージャのキャプチャで取得される。
さらっと短く書かれているが、実は全然新しい考え方だ。

Schemeで最初勉強していて、3章で特に回路シミュレータとか始まった途端に、
何をやっているのかがわからなくなった。
感じたのは、初めて学ぶSchemeというかlispに不慣れであることと、
根本にあるらしい発想の飛躍とが、自分の中で分離できていないこと。
そこで言語自体は慣れているC++でやってみるかと始めた
C++11の勉強もしたいというのもある)わけだが、
どうも重要なポイントはこの、関数とクロージャによるデータ表現にあるか?

問題2.76はコードを書くわけでないのでパス

----
typedef double Field;
typedef function<List(string)> Complex;

const List applyGeneric
(const string operation, const Complex& argument)
{return(argument(operation));}


template<typename XType,typename YType>
const Complex makeFromRealImag(const XType& x,const YType& y)
{
    const Complex dispatch
        =[x,y](const string operation){
        const List xList(makeLeaf(x));
        const List yList(makeLeaf(y));
        if(operation=="real-part"){
            return(xList);}
        else if(operation=="imag-part"){
            return(yList);}
        else if(operation=="magnitude"){
            return(makeLeaf
                   (squareRoot
                    (value<Field>(square(xList)+square(yList)))));
        }
        else if(operation=="angle"){
            return(makeLeaf
                   (arcTangent2(value<Field>(yList),
                                value<Field>(xList))));
        }
        cerr<<"No method for these types --- make-from-real-imag"
        <<listString(makeList(operation,xList,yList))<<endl;
        exit(1);
        return(makeLeaf(0.0));
    };
    return(dispatch);
}

template<typename RType,typename AType>
const Complex makeFromMagAng(const RType& r,const AType& a)
{
    const Complex dispatch
        =[r,a](const string operation){
        const List rList(makeLeaf(r));
        const List aList(makeLeaf(a));
        if(operation=="real-part"){
            return(makeLeaf(value<Field>(rList)*
                        cosine(value<Field>(aList))));
        }
        else if(operation=="imag-part"){
            return(makeLeaf(value<Field>(rList)*
                        sine(value<Field>(aList))));
        }
        else if(operation=="magnitude"){return(rList);}
        else if(operation=="angle"){return(aList);}
        cerr<<"No method for these types --- make-from-mag-ang"
        <<listString(makeList(operation,rList,aList))<<endl;
        exit(1);
        return(makeLeaf(0.0));
    };
    return(dispatch);
}

//---------abstraction barrier---------
const List realPart(const Complex& z)
{return(applyGeneric("real-part",z));}

const List imagPart(const Complex& z)
{return(applyGeneric("imag-part",z));}

const List magnitude(const Complex& z)
{return(applyGeneric("magnitude",z));}

const List angle(const Complex& z)
{return(applyGeneric("angle",z));}


//---------abstraction barrier---------
int main(int argc, char** argv)
{
    const Complex c1(makeFromRealImag(1.0,2.0));
    cout<<"c1 (rectangular) = "
        <<listString(makeList(realPart(c1),imagPart(c1)))<<endl;
    cout<<"(magnitude c1) = "<<listString(magnitude(c1))<<endl;

    cout<<endl<<"Excersize2.75:"<<endl;
    const Complex c2(makeFromMagAng(1.0,M_PI/4.0));
    cout<<"c2 (polar) = "
        <<listString(makeList(magnitude(c2),angle(c2)))<<endl;
    cout<<"(real-part c2) = "<<listString(realPart(c2))<<endl;

    return(0);
}
----
出力
----
c1 (rectangular) = (1 2)
(magnitude c1) = 2.23606797749979

Excersize2.75:
c2 (polar) = (1 0.7853981633974483)
(real-part c2) = 0.7071067811865476


0 件のコメント :

コメントを投稿