March 02, 2008pow(x, 2) vs (x * x) どっちが速いか
[Computer]
プログラムを書いていて少し気になることがありました。べき乗を求めるpowという関数がありますが、二乗の場合はpow(x, 2)と書くのと(x * x)と書くので、どちらが速く実行されるのでしょうか。早速ベンチマークを取ってみようということになりました。 僕の予想としては、コンパイラが最適化してくれるおかげでどちらでも同じ結果が得られるだろうという予想です。皆さんはどうでしょうか。結果は続きをどうぞ。 続きを読む "pow(x, 2) vs (x * x) どっちが速いか"March 13, 2008狼と香辛料このところ更新をサボりがちですが、なんとか苦境を乗り切れそうな兆しが見えてきましたので、久々に軽めの内容で更新を行おうと思います。 詳細は公式サイトに譲りますが、概略を述べると、時は教会や貴族が存在したころ、主人公の行商人ロレンスと、その相棒の賢すぎる狼娘ホロの旅先珍道中を描いたファンタジー作品です。行商人の話ということもあって、町から町へ物を売りさばきつつ、儲かっただの損をしたのの笑あり涙ありの話となっています。 ということで、ニヤニヤしたいファンタジー好きの方にはお勧めです。なお近辺で貸して欲しいという方いましたら貸します。 March 14, 2008operator=()と継承
[Computer]
拙作のC++行列ライブラリmatrix.hのメンテナンスを久しぶりにやってみているのですが、部分行列の代入の解釈で少し考えることがありました。簡易的なコードで書くと以下のような問題です。 Matrix m1, m2;
m.partialMatrix = m2; このとき部分行列への代入は、元の行列の書き換えもおこなうべき(上の例でいうとm1も変更されて然るべき)であると思います。現在の実装では行列を構成する要素データ、そして行列という箱、これら2つを別々に管理するフライウェイトパターンを用いていました。そのため代入については要素ごとの代入を行わず中身全体をつけかえる動作をしており、上記のような元の行列まで書き換えるということを想定していませんでした。 そこで部分行列を適当な子クラスで表現し、子クラスで代入演算子のオーバーロードを行うことによって、上記の問題の解決をはかろうとしました。つまり部分行列への代入は要素ごとの代入を行う一方、それ以外の行列では要素をまとめて付け替えるだけというフライウェイトパターンの共存を目指しました。 前置きがながくなってしまいましたが、ここで表題にあるとおりの代入演算子の問題に引っかかりました。どうも代入演算子を継承先でオーバーロードした際、そのオーバーライド(言葉がややこしいですね、笑)が通常の関数と異なるようなのです。違いを明らかにするため、検証用のプログラムoperator_equal_test.cppを書いてみました。要約をすると問題が生じるのは以下のようなケースでした。 class A {
public: A(){} virtual ~A() {} self_t &operator=(const A &a){ cout << "A::operator=(A)"; return *this; } }; class B : public A { int main(){ cout << "a = a => "; a = a; cout << endl; // (1) return 0; さて結果はどうなるでしょうか。(1)、(2)ではAが左辺オペランド、(3)、(4)ではBが左辺オペランドなので通常の関数と同様に考えるのであれば、(1)、(2)ではA::operator=(A)が、(3)、(4)ではB::operator=(A)が呼び出されそうなものです。しかし(4)では意表をついてA::operator=(A)が呼ばれます。VC2005/2008 Express Edition、gcc 3.4.4で試して同一の結果がでたので、おそらくC++の仕様でないかと思います(現在調査中ですが、ご存知でしたら是非お教えください)。なお(4)のケースでA::operator=(A)を呼ばれないようにするためには、B::operator=(B)なる関数を定義する必要がありました。もし、さらに深い継承関係がある場合には、親クラス::operator=(親クラス)で子クラス=子クラスを捕捉することも可能です。 以上のような検証の末、できあがったのが行列ライブラリmatrix.h(1.28)です。まだまだ改良の余地がありそうですが、よろしければ使ってみてください。 March 21, 2008SWIGによる行列/複素数 C++ライブラリのRubyへの移植
[Computer]
プログラミングの練習がて作成しているC++の行列ライブラリ(matrix.h)、並びに複素数ライブラリ(complex.h)があります。このような標準的なライブラリはどの言語においても先達が素晴らしいプログラムを用意してくれているので、それを新たに作ることは"車輪の再発明"、すなわち時間の浪費という非常に疎まれる行為であることには違いないのですが、今まで自身で育ててきたものは出来が悪くてもかわいいものです。そこで自作の行列、複素数C++ライブラリをRubyに移植してみることにしました。 Rubyへの移植ということですが、RubyはC/C++との親和性を非常に意識しているので、C/C++でプログラムを書くことによって新たな拡張ライブラリを追加できます。このプログラムを書くにあたっては、既に用意されたRubyの言語としての機能と、新たに付け加えたい機能のインターフェイスを取るために、Ruby側で既に用意した関数を使いつつ、型の変換やクラスの階層構造の指示等を行うことになります。すなわち、付け加えたい機能の部分のプログラムが既にある場合には、このインターフェイスの部分の記述だけをすればよく、そのようなプログラムをラッパーと呼んでいます。今回はこのラッパーを作成することによって、C++で書かれた行列、複素数をRubyから使えるようにしました。 このラッパー、実はほぼ全自動で生成することが可能です。表題にあるSWIGがその役割を果たしてくれます。SWIGは、C/C++言語で書かれたプログラムの構造を解析し、対象となるスクリプト言語にあわせたラッパーを生成してくれます。特殊な指示、例えば、あの関数はスクリプト言語から呼び出して欲しくない、あるいは、あの関数に別名をつけたい、といった事情は手動で記述する必要がありますが、それ以外の部分についてはSWIGが全て解決してくれるのです。またSWIGは対象言語としてRuby以外にも、PerlやJavaは勿論のこと、様々な言語に対応しています。 SWIGはどのようなプログラムを解析してラッパーを生成するのか、また全自動で対応できない場合にはどうすればよいのか、といった内容を記述したインターフェイスファイルを入力とし、出力がラッパーとなります。今回の場合はFenrirMath.iというファイルがそのファイルにあたり、行列/複素数の解析を行うことや、関数に別名をつける指示などを盛り込んでみました。ラッパーが生成されたら、あとは対象とする言語にあわせて拡張ライブラリをビルドする作業(Rubyならextconf.rbによるmakefile生成後make)にうつるわけですが、その作業はmakefileで自動化してみました。もしビルドを試されるようでしたら、足りないファイルはcommonディレクトリ等で探してみてください。 以上をもって無事移植が完了しました。Rubyに元々用意されている複素数/行列ライブラリとの比較のためにFenrirMathTest.rbというテストユニットを書いてみましたが、自作ライブラリと元々あるライブラリとで動作結果が一致しました。これで、これからは元のC++ライブラリも含めて安心して使えます。目下の課題としては、cygwin+gcc 3.4.4による行列式の計算がえらく遅いことで、VC2008を利用したビルドにもチャレンジしてみようと思います。 ※その後、FFTも統合しました。上記リンクは常に最新のファイルに飛んでいますので、更新は反映されています。 ※※その後、sqrt(平方根)の計算ができるようになっています。 March 27, 2008秋月GPSモジュール@4800円秋月電子でGPSモジュールキットが売り出されたとのことなので、早速購入しました。単価4800円と、なかなか手頃な値段です。
上の写真を見ていただければわかるかと思いますが、GPSモジュールを分解してしまいました。もともとパッチアンテナ付きの一体型モジュールとして売られていたのですが、中身が気になって仕方がなかったのです(笑)。分解後はパッチアンテナ付き金属ケースとモジュール基板の2つの部品に分離します。 秋月の商品広告に謳っている通り、GPSチップメーカでは有名どころのSiRFが載っています。型番はベースバンドがGSP2e/LP-7456(QFP)、フロントエンドがGRF2i/LP(QFN)を使っていました。以前、Novatelのsuperstar2でベースバンド信号を取りだす方法を示しましたが、BGAのチップではなかったのでそれと同じことができそうです。つまりはソフトウェアGPSの母体と成りうるモジュールで、分解した甲斐がありました。機能ブロックごとに注釈をつけるとこんな感じになります。 ベースバンド信号はフロントエンドとベースバンドの2つのチップの間を走っていると思いますが、データシートをよく確認してから判断をしたいと思います。ちなみに分解の方法ですが、以下の写真において赤丸がついた部分の半田をなんとかすれば基板の表側と対面することができます。僕は『SMD取り外し』で紹介した低融点半田を活用しました。 全部で5箇所です。まず外側3箇所についてはずした後、中央の2つの小さい赤丸(パッチアンテナの給電線とケースにつながっている)を同時に温めて分離させることができました。 ※その後、中間周波数抽出を試みました。 |
かれんだ~
スポンサード リンク
|