Making The Road Blog

http://makingx.net/blog/

mtr2.0
Making The Road はmakingのお勉強用サイトです.PHP, Javascriptを中心にいろいろ試してoutputしていきたい.
当サイトの訪問者は24時間以内にこんな単語↓で検索されています (マウスオーバーすると単語を含むqueryを表示します!)

phpでFFTW3

PHP extensionをかじって,作ってみようと思ったのがFFTWのバインディング.
正直,PHPでFFTW使いたいと思っているわけではないし,そもそもFFTWって何?ってレベル.学校の演習でちょろっと触っただけ.
もっと言うとC言語もよくわかんね.
でもPHP extensionの練習としてはなかなか面白そうだなとは思っていた.とりあえず,流行のCodegen_PECLでさくっと書いてみた.実装は実データの 1 次元離散フーリエ変換のみ.

fftw.xml

こんな感じ.

<? xml version="1.0" ?>
<extension name="fftw" version="0.0.1">
  <maintainers>
    <maintainer>
      <user>making</user>
      <email>makingx [at] gmail.com</email>
    </maintainer>
  </maintainers>
  <release>
    <version>0.0.1</version>
    <date>2007-08-12</date>
    <state>alpha</state>
    <notes>
      First version.
    </notes>
  </release>
 
  <deps language="c" platform="all">
    <with defaults="/usr/include">
      <header name="math.h" />
      <header name="fftw3.h" />
      <lib name="fftw3" platform="all" />
    </with>
  </deps>
 
  <functions>
  <function name="fft">
    <proto>array fft(array arr)</proto>
    <code>
      < ![CDATA[
      int size = zend_hash_num_elements(arr_hash);
      double in[size];
      fftw_complex out[size/2+1];
      fftw_plan p;
      int i=0;
      zval **entry;
      zval *re, *im;
 
      p = fftw_plan_dft_r2c_1d(size, in, out, FFTW_ESTIMATE);
 
      zend_hash_internal_pointer_reset(arr_hash);
      while( zend_hash_get_current_data(arr_hash, (void **) &entry ) == SUCCESS) {
      convert_to_double_ex(entry);
      in[i] = Z_DVAL_PP(entry);
      zend_hash_move_forward(arr_hash);
      i++;
      }
 
      fftw_execute(p);
 
      MAKE_STD_ZVAL(re);
      MAKE_STD_ZVAL(im);
      array_init(re);
      array_init(im);
      for (i = 0; i< size/2+1 ; i++) {
        add_next_index_double(re,out[i][0]);
        add_next_index_double(im,out[i][1]);
      }
      add_index_zval(return_value,0,re);
      add_index_zval(return_value,1,im);
      fftw_destroy_plan(p);
      ]]>
    </code>
  </function>
  </functions>
</extension>

ぼくはさくらインターネットで強引に環境作っているから実際に試したときとは若干違うが(fftw.hをフルパスで書いたり,できたMakefileをいじったり).Codegen_PECL使ってる時点でわかると思うがPHP5をインストールしてます.prefixは$HOMEです.
参考にしたのはこのページ

和訳...

codegen & インストール

ここはいつものように

pecl-gen -f fftw.xml
cd fftw
phpize
./configure
make
make install
echo "extension=fftw.so" >> ~/www/php.ini

まあ実際はこんなスムーズにはいかなかったが,理論上はこれでいいはず.

example

PHPコード1

define('LENGTH',16);
 
$in = array();
$in2 = array();
 
for ($i = 0;$i &lt; LENGTH; $i++) {
    $in[$i] = ($i % 2 ==0) ? 1 : -1;
    $in2[$i] = cos($i * M_PI / LENGTH) + cos($i * 2 * M_PI / LENGTH) + cos($i * 4 * M_PI / LENGTH);
 }
var_dump($in);
var_dump(fft($in));
var_dump($in2);
var_dump(fft($in2));

出力結果

array(16) {
  [0]=>
  int(1)
  [1]=>
  int(-1)
  [2]=>
  int(1)
  [3]=>
  int(-1)
  [4]=>
  int(1)
  [5]=>
  int(-1)
  [6]=>
  int(1)
  [7]=>
  int(-1)
  [8]=>
  int(1)
  [9]=>
  int(-1)
  [10]=>
  int(1)
  [11]=>
  int(-1)
  [12]=>
  int(1)
  [13]=>
  int(-1)
  [14]=>
  int(1)
  [15]=>
  int(-1)
}
array(2) {
  [0]=>
  array(9) {
    [0]=>
    float(0)
    [1]=>
    float(0)
    [2]=>
    float(0)
    [3]=>
    float(0)
    [4]=>
    float(0)
    [5]=>
    float(0)
    [6]=>
    float(0)
    [7]=>
    float(0)
    [8]=>
    float(16)
  }
  [1]=>
  array(9) {
    [0]=>
    float(0)
    [1]=>
    float(0)
    [2]=>
    float(0)
    [3]=>
    float(0)
    [4]=>
    float(0)
    [5]=>
    float(0)
    [6]=>
    float(0)
    [7]=>
    float(0)
    [8]=>
    float(0)
  }
}
array(16) {
  [0]=>
  float(3)
  [1]=>
  float(2.6117715941011)
  [2]=>
  float(1.6309863136978)
  [3]=>
  float(0.50704626348109)
  [4]=>
  float(-0.29289321881345)
  [5]=>
  float(-0.53421998053204)
  [6]=>
  float(-0.32442334882146)
  [7]=>
  float(-0.021682429308611)
  [8]=>
  float(1.1102230246252E-16)
  [9]=>
  float(-0.41186307334087)
  [10]=>
  float(-1.0897902135516)
  [11]=>
  float(-1.6453604465712)
  [12]=>
  float(-1.7071067811865)
  [13]=>
  float(-1.155892961124)
  [14]=>
  float(-0.21677275132474)
  [15]=>
  float(0.6502010332946)
}
array(2) {
  [0]=>
  array(9) {
    [0]=>
    float(1)
    [1]=>
    float(9)
    [2]=>
    float(9)
    [3]=>
    float(1)
    [4]=>
    float(1)
    [5]=>
    float(1)
    [6]=>
    float(1)
    [7]=>
    float(1)
    [8]=>
    float(1)
  }
  [1]=>
  array(9) {
    [0]=>
    float(0)
    [1]=>
    float(-6.7248642982736)
    [2]=>
    float(-2.5837133103639)
    [3]=>
    float(-1.5446859686887)
    [4]=>
    float(-1.0195911582083)
    [5]=>
    float(-0.67759496338973)
    [6]=>
    float(-0.41892890977907)
    [7]=>
    float(-0.20091904348225)
    [8]=>
    float(0)
  }
}

これってあってんの?FFTWの出力ってどう見たらいいの?
C言語はよく分かんないのでおかしなことしてたらつっこんでください.あとはもうちょっとFFTWを学んでから続きを実装するかも.
まあExtensionは楽しいってことはわかった.

カテゴリー: PECL, PHP, C | コメント( 0 ) | 2007/08/14 11:52:20 by making
ソーシャルブックマーク: add to hatena hatena.comment (0) add to del.icio.us (0) add to livedoor.clip (0) add to Yahoo!Bookmark (0) Total: 0
トラックバックURL:

Leave a Reply

求人