なんじゃくにっき

プログラミングの話題中心。

Scalaでフーリエ変換(2)

前回書いたのを少し変更してみた。
複素数を扱うときはComplexクラスを使うようにした。
(ComplexクラスはA Scala Tutorialのに少し手を加えてみた)
http://www.scala-lang.org/docu/files/ScalaTutorial.pdf
  

// 複素数クラス
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary

def r = Math.sqrt(re * re + im * im) //絶対値
def arg = Math.atan(im / re) // 偏角

def + (that: Complex) = new Complex(re + that.re, im + that.im)
def - (that: Complex) = new Complex(re - that.re, im - that.im)
def * (that: Complex) = new Complex(re * that.re - im * that.im,
re * that.im + im * that.re)
def / (that: Complex) = new Complex((re * that.re + im * that.im) / that.r,
(im * that.re - re * that.im) / that.r)

override def toString = re + (if (im == 0.0) "" else
(if (im < 0) "-" else "+") + Math.abs(im) + "i")
}

 

    // 離散フーリエ変換
def dft(data: Seq[Double]) = {
val n = data.length

for (i <- 0 to n-1) yield (
new Complex((for (j <- 0 to n-1) yield
(data(j) * Math.cos(2.0 * Math.Pi * i * j / n) -
data(j) * Math.sin(2.0 * Math.Pi * i * j / n)))sum,
(for (j <- 0 to n-1) yield
(data(j) * Math.cos(2.0 * Math.Pi * i * j / n) +
data(j) * Math.sin(2.0 * Math.Pi * i * j / n)))sum))
}

使うときはこんな感じで

        val sampleData =
for (i <- 0 to 1000) yield (Math.cos(2 * Math.Pi * i / 25))

val a = DFT.dft(sampleData)

a foreach(aa => println(aa.r))

 
dftの引数にListを与えてやると動作が遅いです。
Listはランダムアクセスが遅いのがよく分かる。
ArrayかVectorあたりを与えてやるのが吉。