サインカーブのテイラー展開

J言語でサインコサインはo.(オードット)という関数を使って、左側引数に1だとサイン、2だとコサインが計算できます。
先日書いた「多項式によるサインカーブhttp://d.hatena.ne.jp/niming538/20100106の係数をテイラー展開で算出できるのではないかと思いついてやってみたらできたのでご紹介。

   sin=:1&o.
   cos=:2&o.
   sin t.i.10
0 1 0 _0.166667 0 0.00833333 0 _0.000198413 0 2.75573e_6
   sin t.i.10r1
0 1 0 _1r6 0 1r120 0 _1r5040 0 1r362880
   cos t.i.10r1
1 0 _1r2 0 1r24 0 _1r720 0 1r40320 0

t.(ティードット)というのがテイラー展開するための動詞です。
10r1というのは結果を有理数(分数)で表示させるために入力を有理数にしたものです。
sin=:1&o.の&はo.の左側引数1をo.と結びつけて単項動詞を作るための接続詞です。
i.(アイドット)はゼロから右側引数(整数)までの整数を生成する動詞です。


多項式によるサインカーブhttp://d.hatena.ne.jp/niming538/20100106では、p.(ピードット)という多項式(polynomial)を計算する動詞を使って、サインカーブ、コサインカーブを書きました。

   fc=: 1 0 _1r2 0 1r24 0 _1r720 0 1r40320 & p.
   fs=: 0 1 0 _1r6 0 1r120 0 _1r5040 & p.
   x=: 1r3*i:10
   plot x; (fs x),:fc x
   fs=: 0 1 0 _1r6 0 1r120 0 _1r5040 & p.

ここで使った係数とテイラー展開で算出した係数とが一致しているのが分かります。


Math for the Layman by Kenneth Iversonでこの係数を算出するプログラムが紹介されています。

   ps=: % @ ! * 2 & | * _1: ^ 3: = 4: | ]
   ps 0 1 2 3 4 5 6 7 8 9 10r1
0 1 0 _1r6 0 1r120 0 _1r5040 0 1r362880 0

このpsを解析してみました。また、コサインの方に相当するpcを作ってみました。
psは動詞がずらずらと並んでいてどのように引数が処理されるのかぱっと見ではわかりません。
まず、psとだけタイプして引数を与えずにエンターを押します。すると文法の解析結果が表示されます。

   ps
 +-------+-+-----------------------------------+
 |+-+-+-+|*|+-------+-+-----------------------+|
 ||%|@|!|| ||+-+-+-+|*|+---+-+---------------+||
 |+-+-+-+| |||2|&|||| ||_1:|^|+--+-+--------+|||
 |       | ||+-+-+-+| ||   | ||3:|=|+--+-+-+||||
 |       | ||       | ||   | ||  | ||4:|||]|||||
 |       | ||       | ||   | ||  | |+--+-+-+||||
 |       | ||       | ||   | |+--+-+--------+|||
 |       | ||       | |+---+-+---------------+||
 |       | |+-------+-+-----------------------+|
 +-------+-+-----------------------------------+

これにより、大きく3つの部分からなる関数であることが分かります。
3つの部分の関数それぞれをf g hとすると(f g h) xは(f x) g (h x)と処理されますので、それぞれについて解析します。

   (% @ !) i.10r1
1 1 1r2 1r6 1r24 1r120 1r720 1r5040 1r40320 1r362880
   (2&| * _1:^3:=4:|]) i.10r1   
0 1 0 _1 0 1 0 _1 0 1
   2&| i.10r1
0 1 0 1 0 1 0 1 0 1
   (3:=4:|])i.10r1
0 0 0 1 0 0 0 1 0 0
   _1: ^ (3:=4:|])i.10r1
_1
   (_1: ^ 3:=4:|])i.10r1
1 1 1 _1 1 1 1 _1 1 1
   (0 1 0 1 0 1 0 1 0 1) * (1 1 1 _1 1 1 1 _1 1 1)
0 1 0 _1 0 1 0 _1 0 1

これで階乗の逆数の数列に0 1 0 _1 0 1 0 _1 0 1をかけたものであることがわかります。
さて、同じ考え方でコサインの方のpcを作るためには、1 0 _1 0 1 0 _1 0 1 0という数列を作らなければなりません。

   (_1: ^ 2:=4:|])i.10r1
1 1 _1 1 1 1 _1 1 1 1
   2&| i.10r1
0 1 0 1 0 1 0 1 0 1
   2&|>: i.10r1
1 0 1 0 1 0 1 0 1 0
   (2&|@>:) i.10r1
1 0 1 0 1 0 1 0 1 0
   (2&|@>: * _1: ^ 2: = 4: | ]) i.10r1
1 0 _1 0 1 0 _1 0 1 0
   pc=:% @ ! * 2&|@>: * _1: ^ 2: = 4: | ]
   pc i.10r1
1 0 _1r2 0 1r24 0 _1r720 0 1r40320 0

完成!

以上