Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzotinfena committed Apr 28, 2024
1 parent 0173f60 commit 78fa8ed
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/lorenzotinfena/goji

go 1.20
go 1.21

require (
github.com/stretchr/testify v1.8.4
Expand Down
71 changes: 71 additions & 0 deletions math/fft.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package math

import (
"math"
)

func FastFourierTransform(p []complex128, inverse bool) []complex128 {
n := len(p)
if n == 1 {
return p
}
p0 := make([]complex128, n/2)
p1 := make([]complex128, n/2)

for i := 0; i < n/2; i++ {
p0[i] = p[2*i]
p1[i] = p[2*i+1]
}

y0 := FastFourierTransform(p0, inverse)
y1 := FastFourierTransform(p1, inverse)

y := make([]complex128, n)

w := complex(1, 0)
var angle float64
if inverse {
angle = -(2 * math.Pi) / float64(n)
} else {
angle = (2 * math.Pi) / float64(n)
}
w1 := complex(math.Cos(angle), math.Sin(angle))
for i := 0; i < n/2; i++ {
y[i] = y0[i] + w*y1[i]
y[i+n/2] = y0[i] - w*y1[i]

if inverse {
y[i] /= 2
y[i+n/2] /= 2
}
w *= w1
}
return y
}

func MultiplyPolynomials(p1, p2 []int) []int {
n := 1
for n < len(p1)+len(p2) {
n *= 2
}
p1c := make([]complex128, n)
p2c := make([]complex128, n)
for i := 0; i < len(p1); i++ {
p1c[i] = complex(float64(p1[i]), 0)
}
for i := 0; i < len(p2); i++ {
p2c[i] = complex(float64(p2[i]), 0)
}
y1 := FastFourierTransform(p1c, false)
y2 := FastFourierTransform(p2c, false)
y := make([]complex128, n)
for i := 0; i < n; i++ {
y[i] = y1[i] * y2[i]
}
pc := FastFourierTransform(y, true)
p := make([]int, n)
for i := 0; i < n; i++ {
p[i] = int(math.Round(real(pc[i])))
}
return p
}
42 changes: 42 additions & 0 deletions math/fft_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package math_test

import (
"testing"

"github.com/lorenzotinfena/goji/math"
"github.com/stretchr/testify/assert"
)

func Test1MultiplyPolynomials(t *testing.T) {
p1 := []int{1, 2}
p2 := []int{1, 2}
n := 1
for n < len(p1)+len(p2) {
n *= 2
}
res := make([]int, n)

for i := 0; i < len(p1); i++ {
for j := 0; j < len(p2); j++ {
res[i+j] += p1[i] * p2[j]
}
}
assert.Equal(t, math.MultiplyPolynomials(p1, p2), res)
}

func Test2MultiplyPolynomials(t *testing.T) {
p1 := []int{1, 2, -3, 2, 5, -2}
p2 := []int{8, 2, 2, 5, -2, 1, 3, -3, 7}
n := 1
for n < len(p1)+len(p2) {
n *= 2
}
res := make([]int, n)

for i := 0; i < len(p1); i++ {
for j := 0; j < len(p2); j++ {
res[i+j] += p1[i] * p2[j]
}
}
assert.Equal(t, math.MultiplyPolynomials(p1, p2), res)
}

0 comments on commit 78fa8ed

Please sign in to comment.