Try   HackMD

キーワード: 離散フーリエ変換、高速離散フーリエ変換、多倍長演算、1変数多項式

はじめに: 内容と背景

離散フーリエ変換は、導出の部分やそこに絡む直観をすっ飛ばすと、やっていることはVandermonde行列という特殊行列を用いた行列積です。

  • これは一般的な教科書にも書かれている知られた話です。
  • 例えば、手元にある この応用数学の本 は(Vandermonde行列という固有名詞は出てこないのですが) このスタイルで説明されています。

一方で、離散フーリエ変換といえば、高速っしょ!!という名言(要出典)もある通り、高速フーリエ変換です。はい。実験のセクションでみる通り、相当速くなります。

ということで、高速化をVandermonde行列を起点に再導出する、という備忘録的な記事というのが、この文章の正体です。同じような説明は探せば出るので、新しい結果などは全く含んでいないです。

高速化の話をしたいものの、離散フーリエ変換が既に存在しているところから話を始めると面白くないのと、一方で連続フーリエ変換経由で離散フーリエ変換の導出をやる一般的な方法だと長くなりすぎます。

そこで本記事では一つの工夫として、多倍長演算の実装という、これまた結局Vandermonde行列積に行き着く別のストーリーを採用します。多倍長演算の実装に離散フーリエ変換を使うのは非常に枯れた方法で、この話の展開の仕方も新しいものではないです。

あくまでよく知られた話をまとめたメモ程度の記事です。

前提知識

  • 多項式を知っていて、多項式の積が定義・実行できる。
  • 行列積を定義・実行ができる。
  • 逆行列の定義を知っている。
  • Vandermonde行列というのをきいたことがある。

1. 主役: Vandermonde Matrix

この記事では、

n×n サイズの Vandermonde(ヴァンデルモンド)行列を、2つのパラメータ
α
n
を持つ形で表すことにします:

Vα,n=(11111αα2αn11α2(α2)2(α2)n11αn1(αn1)2(αn1)n1)

先に書いておいてなんですがVandermonde行列は、次の問題設定のセクションでは使いません。でも問題設定の後のセクションから使います。

ノート: 後で逆行列

V1 を使うことになるので、
α
は何らかの体の値だと思ってください。具体的なイメージを持ちたいので使う体を先に教えてくれという方にお知らせすると、複素数体と有限体
Fp
を使います。

疑問: Vandermonde行列を既知の方は、この行列の中身には色んなバリエーションがある(Wikipediaのエントリ)ことを知っているので、何故上の形を選ぶか?という 疑問 があるかと思います。これは解決されなければなりません。この要素の並びにしている理由はセクション3ならびにセクション6でお知らせします。

2. 問題設定: 多倍長整数とその積

多倍長整数型というのは、改めてなにかと言われるとやや説明がしづらいのですが、1バイト整数とか4バイト整数とか、ああいう最小値最大値がある数(数値型)ではなく、幾らでも大きい値が書けるような数値型です。

多倍長整数(型)では、例えば以下のような

(12345678987654321)2=152415789666209420210333789971041

大きな数字や、その積を考えます。

この記事では、多倍長整数型がない環境に、自力で新たに実装しようというストーリーを考えます。PythonやRubyやHaskell(Integer)やJava(BigInteger)は言語組み込みの多倍長整数を持ちますが、一方でCやC++やRustだと多倍長整数型は組み込みの型ではないです。とはいえ提供ライブラリがあるのでそれを使えば良いので、別に困りはしないです。

現実的には自分で頑張るよりも、きっちり実装してくれているライブラリ、GNU GMP https://gmplib.org/ などを使うのが筋です。
ということは明記しつつ、それでも何とかやってみましょう。

多倍長整数の実現

多桁の数字をどう表現するか考えてすぐ思いつくのは、数を要素とするリストによって表現する方法かと思います。ここではそれと実質的に同じことをする「1変数多項式」による表現を採用します。つまり

12341x3+2x2+3x+4

のようにして、

x=10を代入すると元の数に戻るような1変数
x
上の多項式として記号的に表現する、ということです。

どうしてもデータ構造的に捉えたい方は、リストや辞書型で

{ x^3: 1, x^2: 2, x^1: 3, x^0: 4 }

のように内部的に表現すると思ってください。

多項式での表現を前提にすると、乗算はどうなるか見てみます。
一例として、

5678=4368

という何の変哲もない計算を、多項式の乗算として処理します:

(5x+6)×(7x+8)=35x2+82x+48.

記号の注意: この記事では、多項式の積を

× で表します。

結果の多項式を左から順番に読んで

358248 が答えかというと、そうではなくて、
x=10
によって評価してあげる必要があり、そうすると

3500+820+48=4368

として正しい結果を得ることができます。

いや、

x=10で評価するって言っても、評価した後の数字を表現する数値型がないという話じゃないの、というのはその通りです。
実際には、下の桁から上に向かって繰り上がり処理をして、多項式のままで「正しい形(係数が9以下の形)」に変形します。つまり:

  1. 484x+8
    にして、
    35x2+(82+4)x+8
    にする。
  2. 86x8x2+6x
    として、
    (35+8)x2+6x+8
    にする。
  3. 43x24x3+3x2
    として、
    4x3+3x2+6x+8
    にする。

こういう感じでやれば、積も実行できそうです。

実装の注意:
積を実行したい多項式の次数が巨大になるにつれ、結果の多項式の係数に「相当」巨大な数が出てきます。この係数が実装言語で表現可能な整数の最大値を超えていると、そもそも上のような正規化以前の問題として、正しい多項式が表現できなくなります。この辺をどう解決するかは実用上は重要なのですが、今回は実装はそこまで頑張りたくないのでこのトピックはskipします。

次のセクションへのつなぎ

多倍長整数型の積は定義できました。
今の実装は、多項式の積をナイーブに実行するものになっています。

この実装を高速化したいです。
というのは、2つの多項式の積は素朴にやると

O(N2) (Nは次数)の計算になって、
N
が数十万とか数百万になると、しっかり遅くなるんですよね。
一方でこれから見る方法で
O(NlogN)
まで持っていけて、実験のセクションでも見ますが、実行速度に顕著に差が出ます。

3. 高速化の準備: 畳み込み積とアダマール積

このセクションでは、高速化の準備として、2つの1変数

x上の多項式
p1,p2
について、以下のことを示します:

V1((Vp1)(Vp2))=p1×p2.

失礼しました。記号が沢山出てきてしまいました。各記号は

となっています。同じことですが、以下の図式を可換にしたいと言っています:

多項式世界p1, p2×p1×p2VV1行列世界Vp1, Vp2(Vp1)(Vp2)

この定理には Convolution theorem という格好良さげな名前がついているのですが(Link 1 2)、Hadamard積が何者かわからないとなんとも言い難いので、とりあえず各積について見ていきます。

3つの積について

行列積、Hadamard積、Convolution積について一応述べます。

行列積は分かっているものとしますが、上の等式をみると、Vandermonde行列と多項式の積をとっています。いつのまに多項式が行列になったのかというと、これは記号をabuseしていまして、正確には多項式を次のように列ベクトルと同一視しています:

k3x3+k2x2+k1x+k0(k0k1k2k3).

さて問題の行列のHadamard積ですが、これはサイズの一致する2つの行列上の積で、point-wise(各点毎)に積を実行するタイプのものです:

(a1a2a3a4a5a6)(b1b2b3b4b5b6)=(a1b1a2b2a3b3a4b4a5b5a6b6)

これだけです。この積にHadamard積という格好良い名前がついているんだなあ以上の理解は、少なくとも今回は不要です。

なんだ随分簡単だなあ というとその感想そのものが一つのミソになっていて、Vandermonde行列をかけて行列の世界に移すと、(今まさに高速化しようとしている比較的重たい計算である)多項式の積が、要素別積に化けるというのがConvolution theoremのエッセンスです。

最後に、Convolution積ですが、これは多項式の積の格好良い呼び方です。以上なのですが、それだけだと寂しいので、一応よく見かけるようなformalな書き方をやっておくと:

i=0i=Knixi×j=0j=Kmjxj=0k2K(i+j=knimj)xk

となり、右辺は、2つの

K次多項式(左辺)の畳み込み積を実行して得られる多項式での
xk
の係数

nkm0+nk1m1++n1mk1+n0mk

になると言っています。

Convolution theoremが 2次多項式の積 で成立することの確認

どのサイズのVandermonde行列でも成り立つのですが、具体的に話をみたいので、以下の2つの二次多項式について考えることにします:

p1=a2x2+a1x+a0(a0a1a200), p2=b2x2+b1x+b0(b0b1b200)

待てい。どこから0が出てきたということについては急いで説明させてください。

p1
p2
の畳込み積の結果を格好つけて行列表示すると:
p1×p2=(a0b0a1b0+a0b1a2b0+a1b1+a0b2a2b1+a1b2a2b2)

となります。ここのサイズと揃えたい、すなわち2次多項式の積の結果が4次多項式になるので、それに併せて
p1
p2
も行列で見るときには0でpaddingしています。そうしないと我々のconvolution theoremにおける行列の型が左辺と右辺で不一致するので……

あとはConvolution theoremが成立していることを確認したいのですが、実際には次の形の等式を示します:

(Conv)(Vp1)(Vp2)=V(p1×p2)

示すといっても、各行ごと

15 に一致していることを確認するだけです。

(Conv)の左辺の計算は多項式の畳み込み積

V×p1=(111111αα2α3α41α2(α2)2(α2)3(α2)41α3(α3)2(α3)3(α3)41α4(α4)2(α4)3(α4)4)(a0a1a200)

です。

λ=α1 と置くと、(Conv)の左辺の
15
行目は

(a0+a1λ1+a2λ2+0λ3+0λ4)×(b0+b1λ1+b2λ2+0λ3+0λ4)=a0b0+(a1b0+a0b1)λ1+(a2b0+a1b1+a0b2)λ2+(a2b1+b1a2)λ3+(a2b2)λ4

になります。
これは、一変数

λ上の多項式の計算としてみることができます。
勿論、実際には
λ
は変数ではないです。気持ちの話です。

(Conv)の右辺の計算は列ベクトル表現の多項式化

a0b0+(a1b0+a0b1)λ1+(a2b0+a1b1+a0b2)λ2+(a2b1+b1a2)λ3+(a2b2)λ4

これは列ベクトルでの表現を、一つの多項式に読み替えただけになります。

セクション1で書いたVandermonde行列の形についての注意

上の話は、次のVandermonde行列形でも成立します(確認してみてください):

()(1αα2α3α41α2(α2)2(α2)3(α2)41α3(α3)2(α3)3(α3)41α4(α4)2(α4)3(α4)41α5(α5)2(α5)3(α5)4)

一方で、

(11111αα2α3α4α5α2(α2)2(α2)3(α2)4(α2)5α3(α3)2(α3)3(α3)4(α3)5α4(α4)2(α4)3(α4)4(α4)5),(αα2α3α4α5α2(α2)2(α2)3(α2)4(α2)5α3(α3)2(α3)3(α3)4(α3)5α4(α4)2(α4)3(α4)4(α4)5α5(α5)2(α5)3(α5)4(α5)5)

のように、左端が1で揃っていないVandermonde形では、左辺と右辺が一般には一致しません。確認してみてください。

ということは、セクション1のVandermonde行列の形ではなくて、

()でも良いのではないか?ということになります。Convolution theoremを成立させるところまでで言えばそうです。
しかし、
()
は、以降で見ていく高速化のところで少し問題になります。具体的にはここで説明しますが、結局のところ、セクション1のVandermonde行列の形を選ぶと色々都合が良いということになります。

一般化

今回は二次多項式を具体的に使って計算に基づいて確認しましたが、任意次数でも明らかに成立する議論なので、任意サイズの行列でconvolution theoremが成立します。

フーリエ変換では複素数体上の話で同じことが展開されるので、どこまで一般化出来るか分かりづらいのですが、別に複素数体でなくても、どの体(または可換環)上のVandermonde行列を用いても、(Conv)の形 は成立します。

注意点として、(Conv)の形はもともと示したかった convolution theorem:

V1((Vp1)(Vp2))=p1×p2.

とは違います。行列の世界に送る時に使う行列の逆行列がとれる必要があるのですが、その保証のためにVandermonde行列を使っていて、これが一つのポイントになります。

また、Vandermonde行列の旨味はそれだけに留まらず、以下で見るように分割統治法を用いた行列積の高速化の鍵ともなっています。

4. 高速Vandermonde行列積

ここまでで、convolution theoremを経由することで、多項式の積(畳み込み積)を実行する別の手段があることをみました。
すなわち、

V\hyphen によって行列の世界に送って、色々やったあとに
V1\hyphen
で戻せばよいということです。

ここから高速フーリエ変換の肝である分割統治法を、Vandermonde行列積の高速実行という視点からみていきます。

まずは行列の世界に送る側の

V\hyphenを考えますが、
具体的な計算も実行したいので、例として、
n=8
のVandermonde行列
Vα,n
を考えます。つまり

(r0r1r2r7)=(11111αα2α71α2(α2)2(α2)71α7(α7)2(α7)7)(x0x1x2x7).

勿論これをそのまま計算しても良いのですが、

xの偶数添字 (
x0,x2,x4,x6
) と奇数添字 (
x1,x3,x5,x7
) に分解して計算してみます(天下り的ではありますが)。

偶数添字部分の計算では、

xについて偶数部を取り出して、それに対応する列ベクトルたちを
V
から取り出して、左からかけます:
(e0e1e2e7)=(E=)(11111α2α4α61(α2)2(α2)4(α2)61(α7)2(α7)4(α7)6)(x0x2x4x6)

同様にして奇数添字部分だけとってくると

(o0o1o2o7)=(O=)(1111αα3α5α7α2(α2)3(α2)5(α2)7α7(α7)3(α7)5(α7)7)(x1x3x5x7)

とした上で、

ri=ei+oiが明らかに成立します。

ここから「2つ」やることがあります。

工夫1

Oはかなり
E
に似た構造をしているので、この発想を元に、まず
E
で計算して、
α
が足りない部分をHadamard積で補うことで、
O
行列を消去します:

(o0o1o6o7)=(1αα2α7)(E(x1x3x5x7))

工夫2

工夫1を経て、計算のコアが

E(y0y1y2y3)

の形をしていることが分かったので、この計算ステップを減らす工夫をします。

β=α2としてこの式を書き直すと:
(11111ββ2β31β2(β2)2(β2)31β3(β3)2(β3)31β4(β4)2(β4)31β5(β5)2(β5)31β6(β6)2(β6)31β7(β7)2(β7)3)(y0y1y2y3)

(横棒は単に視覚的なもので、値として深い意味があったりはしません。)

ここで

α8=β4=1 が成立する
α
を選んでおけば
嬉しいことが起こります。つまり

E=(Vβ,4Vβ,4)

が成立して、ブロック行列積により

EY=(Vβ,4YVβ,4Y)whereY=(y0y1y2y3)

となります。4x4のVandermonde行列積を一度やって、それをコピーすれば良いので、もとの8x8の行列積の計算を半分のサイズの行列積の計算に帰着できました。

まとめると、まず

(v0v1v2v3)=Vα2,4(x0x2x4x6)

の計算をして、次に

(w0w1w2w3)=Vα2,4(x1x3x5x7)

としたあとで、以下が成立します:

Vα,8(x0x1x2x3x4x5x6x7)=(v0v1v2v3v0v1v2v3)+(1αα2α3α4α5α6α7)(w0w1w2w3w0w1w2w3)

一般的な高速フーリエ変換を知っている方の頭の中には「あのどこからかやってくるマイナス1倍はどこ?」という疑問があるかもしれません。何を言っているか分からない方は、そこは自然にカバーできているので、安心して次のセクションまで読み飛ばしてください。

α8=1であり、かつ
α,α2,,α7,α8
の全てが異なっている場合には(後でみますが、これはVandermonde行列が逆行列を持つために必要な条件です)、
α4=1
でなければならないので、以下が成立します:

(1αα2α3α4α5α6α7)=(1αα2α31αα2α3)

一般的な高速フーリエ変換の説明で

1が出てくるのは、まさにこの部分です。

再帰構造

既に明らかになっていますが、結局のところ

Vα,8の計算が、うまいこと
Vα2,4
という縦横半分サイズの行列積に置き換わりました。

ここで話を止める必要はなくて、この4x4の行列積すらも、再帰的に

Vα4,2 を用いた形に変形できます。

より大きい

n=32から話をはじめると、
Vα,32\hyphen
の形の計算は、
Vα2,16
を用いた計算に書き換えることができて、この計算が更に
Vα4,8
を用いた計算に書き換えることができて……という次第です。

5. Vandermonde行列上で要求される性質

高速Vandermonde変換では、行列のサイズを縦横半分にしていきたいので、スタート地点となる行列の形は、2のべき乗の

Vα,2n=(11111αα2α2n11α2(α2)2(α2)2n11α2n1(α2n1)2(α2n1)2n1)

です。

また、

α2n=1が成立する必要もあります。この条件を (V1) と呼びます。

Vandermonde行列が逆行列を持つためには、2列目の値が全て異なること、すなわち

1,α,α2,α3,,α2n1 の全てが異なる値を取らなければなりません。
これはVandermonde行列の行列式が差積で与えられるという基本的な結果から明らかです。この条件を (V2) と呼びます。

それでは、両方の条件を満たす

α を上手いこと作るための2つの例を見てみます。

複素数体による実現

1つ目の方法は、一般的なフーリエ変換で用いられるものですが、複素数体上で

α=ei2πn とする方法です。

複素平面上でオイラーの公式を可視化するよくある図を思い出してもらいたいのですが、あの図のおかげで

αn=1になりつつも、
α,α2,,αn
は全て異なる値をとるというのが想起できます。よって簡単に (V1) と (V2) を満足できます。

この方法でVandermonde行列を具体化した場合に、上の方法で高速化したものが、離散高速フーリエ変換と呼ばれるものと一致しています。

じゃあ複素数体を使えば良いね、ということになるのですが、一般的なプログラミング言語の(組み込みの)複素数型は、float型とかdouble型とかlong double型の、精度に限りある数値型が使われているため(参考 1)、桁数に限りのない多倍長演算を実行するには誤差などの心配がつきまといます。

この点を考慮して、別の方法である有限体による実現もみておきます。

有限体による実現

別の方法による実現では、素数

pで整数を割って得られるような
Fp
があります。

Fpの定義は簡単で、

  • この体には
    {0,1,2,,p1}
    という
    p
    個の整数がおり
  • 足し算や掛け算は整数として計算したあとに
    p
    で余りを求める
  • 除算
    x/y
    については
    y0
    であれば、
    yz=1(modp)
    となる
    z
    が、
    p
    が素数であることより存在する(参考リンク 1) ので、それを使って
    xz
    をしたあとに
    p
    で余りを求める

とすれば良いです。

例えば

p=17 の場合は、
39=10(mod17)
となり、
3/9=32=6
になります。2が9の逆数なのは
29=1(mod17)
から分かります。
(3/9)9=69=3
が成立するので、除算も出来ていそうです。

とくに

p=17=24+1 のような
p=k2n+1
で表現されている素数については、フェルマーの小定理(参考 1 2) から、任意の
1<x<p
について

xk2n=(xk)2n=1(modp)

が成立することが分かるので、

α=xk として採用すれば、(V1)を満たします。実際、
p=17
のときには、
(31)16=1
が成立します。特にこの場合は

(mod17):31=3,32=9,33=10,34=13,35=5,35=15,36=11,37=16,38=14,39=8,310=7,311=4,313=12,314=2,315=6,316=1

により(V2)も満たすので、高速Vandermonde行列積に使えます。

しかし

p=17
α=3
として(V2)が成立するのは「偶然」です。
これを確認するために、別の例として、
p=3(25)+1=97
を考えてみます。

条件(V1)

3325=2725=1(mod97) がフェルマーの小定理から成立するのですが、一方で 
2724=16=1(mod97)
 が成立するので、(V2)が成立しません。

強調しますが、フェルマーの小定理は(V1)を保証してくれるだけです。
(V2)も満たす値の探索は、整数論の言葉で言えば、

(modp) における原始根を求める問題を解けば十分で、ということになると整数論に関する議論を使いたくなります。
このノートでは整数論の話は端折りますが、代表的な効率の良い手法は確立しているので、物凄く困ったことには一応なりません。

6. 高速逆Vandermonde行列積

ここまではVandermonde行列によって、多項式を行列の世界に送る側を高速化したのですが、最後に多項式の世界に戻ってくる際にはVandermonde行列の逆行列をかける必要があります。

逆行列についても高速化のための構造が備わっていなければ困るのですが、高速逆Vandermonde行列積が実行できることが、次のことから分かります:

Vα,n1=1n(11111αα2αn11α2(α2)2(α2)n11αn1(αn1)2(αn1)n1)

ここで

α
α
の積逆元で、複素数体で
α=ei2πn
の場合は複素共役
α=ei2πn
を取れば良いですし、
Fp
αn=1
ならば
α=αn1
です。

1nがついているのがちょっと気になりますが、これがないと

VV1=(n000n000n)

となるので仕方がないところです。ですが分割統治法を行う上では問題になりません。

αが(V1)と(V2)を満たす時、
α
もこれを満たすことに注意してください。すなわち、全く同じ方法で分割統治法により行列サイズを再帰的に半分にしていくことで、逆Vandermonde行列積も実行出来ます(最後に
1n
を全要素にかける必要はありますが)。

Vandermondeの行列式形に関する注意2

もし我々がVandermonde行列の形として

M=(1αα2α3α41α2(α2)2(α2)3(α2)41α3(α3)2(α3)3(α3)41α4(α4)2(α4)3(α4)41α5(α5)2(α5)3(α5)4)

を採用した場合は、既にみたようにconvolution theoremは成立します。
ただし、この行列の逆行列は、各要素を逆元で置き換えた

N=(1αα2αn11α2(α2)2(α2)n11αn(αn)2(αn)n1)

とはなりません。

例えば

MN の左上の要素を考えてみると、これは

1+α+α2++αn1

となり、一方で

(1α)(1+α2+α3++αn1)=1αn(by calculus on polynomials)=0(by αn=1)

で、

α1なので、左上の要素は0となります。
よって

MN=(0)

となり、明らかに単位行列ではなく、

N
M
の逆行列ではないです。

7. 実装

複素数体を使った実装はたくさんあると思うので、

Fp の方法でやってみます。こちらの実装もたくさんあるわけですが。

そこそこ大きな多項式の積を考えたいので、次の設定を使います:

p=7220+1,α=37=2187.

この

p=7340033 が素数かどうかは、自分で頑張っても良いですし、Wolframalphaでも確認できます。

このときは、多項式積実行後の次数が

220までなら表現できるので、今回は
2203350k
 次数の多項式の積を実行してみます。
これはすなわち、約 35万桁 の整数同士の積を実行することになります。

C++で書いたプログラムはここにおいてあります: https://gist.github.com/yuezato/f965e51aac2ffd66924de9252b9bd897

コンパイルして実行してみると

$ g++ -std=c++11 -O3 fast_vt.cpp -Wall
$ ./a.out
Alpha(2187) = 3^7
P(7340033) = (7)*(2^20)+1
Multiply two polynomials whose degrees are 349525
Start calc
End calc. Elapsed: 377ms
Start naive

などが得られ、まずこのノートに書いた手法だと400ms秒足らずで自分の環境だと実行できていることが分かります。
その次の Start naive ですが、実装の正しさの確認のために、ナイーブな多項式積を実行して、これを高速化手法の結果と比較しようとするものの、数分待った程度では結果が全く返ってきません。

ということで十分高速化できているかなと思います。

念のためにもう少し小さいパラメータで実行してみると……

Alpha(243) = 3^5
P(163841) = (5)*(2^15)+1
Multiply two polynomials whose degrees are 10922
Start calc
End calc. Elapsed: 7ms
Start naive
End naiive. Elapsed: 1376ms
Ok
Alpha(125) = 5^3
P(786433) = (3)*(2^18)+1
Multiply two polynomials whose degrees are 87381
Start calc
End calc. Elapsed: 69ms
Start naive
End naiive. Elapsed: 92637ms
Ok
Alpha(177147) = 3^11
P(5767169) = (11)*(2^19)+1
Multiply two polynomials whose degrees are 174762
Start calc
End calc. Elapsed: 207ms
Start naive
End naiive. Elapsed: 530223ms
Ok

ということで相当高速化できていることが分かりました。

おわりに

高速フーリエ変換は、フーリエ変換の式の導出が先立っていて、その出てきた式に対して「上手いこと」分割統治法が働くので、とにかく高速に実行できるという説明になりがちです。

それはそれで良いのですが

  • 「なぜ」上手いこといくのか、その条件や構造が知りたい
  • どのくらい脆い・あるいは奇跡的にうまくいく状況なのか?
  • どういうケースであれば同じ様なことができるのか

といった類のことがどうしても気になるタイプの人達というのは一定居ると思っていて、自分がそれなのですが、その人達が納得するためには、もう少し一般的な立場で展開される構成が知りたいです。

そのような構成として、Vandermonde行列を中心にした説明はある程度うまくいくかなと思います。とはいえ、はじめにでも書いたのですが、このようなVandermonde行列で捉え直す話は新しい話では全くないです、ということは再度強調しておきます。

しかし一般化という観点からはあんまり踏み込めていないので、離散コサイン変換と関連があるChebyshev-Vandermonde変換(リンク 1 pdf)とその高速化まで綺麗に書けるのかなあ、なんかは調べてみたいのですが、結局使ったことがないので手がついていません。

他にやや気になっていることとしては、Convolution theoremまわりの証明を行列の言葉でもっと綺麗に書けないかなあ、というのがあります。
今回は多項式の畳み込み積を、行列の言葉や行列演算ではなく、普通の定義で済ませています。
一方で畳み込み積は、Toeplitz行列を用いた行列積の形で定義できるので、こっちを経由するともう少し綺麗かつ一般的かつ行列の性質ベースの話で済んで、そうするとHadamard行列以外とのinteractionも自然に色々出せないかなあ〜、みたいなやつです。
何かご存知の方は教えてください。