func mergeChannels(in1 <-chan []complex128, in2 <-chan []complex128) chan []complex128 { out := make(chan []complex128) go func() { fmt.Printf("Writing...\n") for cIn1 := range in1 { cIn2 := <-in2 if len(cIn1) != len(cIn2) { panic("oops, columns don't match... :(") } cOut := make([]complex128, len(cIn1), len(cIn1)) for i := range cIn1 { power1, angle1 := cmplx.Polar(cIn1[i]) power2, angle2 := cmplx.Polar(cIn2[i]) cOut[i] = cmplx.Rect(power1, angle1) if i > 48 && i <= 72 { cOut[i] = 0 } // HACK variable to stop go complaining about unused variables :( cIn2[i] = cmplx.Rect(power2, angle2) } out <- cOut } close(out) }() return out }
func addPolar(a, b Polar) Polar { // Add polar coordinates (5,140) and (3,70) x := cmplx.Rect(a.radius, a.angle) y := cmplx.Rect(b.radius, b.angle) radius, angle := cmplx.Polar(x + y) return Polar{radius, angle} }
func (s *Soldier) Step() { ref := s.refPoint() switch s.Current { case Halt: case ForwardMarch: s.Pt += complex(vel, 0)*s.Dir - ref*complex(gain, 0) + complex(velRand, 0)*complex(rand.Float64(), rand.Float64()) s.P.Move(real(s.Pt), imag(s.Pt)) case LeftWheel: v := velMax if s.Adj[0] == nil { _, cols := s.C.f.RowCols(len(s.C.s)) v *= float64(cols-s.Col()+1) / float64(cols+1) th := velMax / (2 * math.Pi * float64(cols+1)) s.Dir *= cmplx.Rect(1, th) } else { v = vel } s.Pt += complex(v, 0)*s.Dir - ref*complex(gain, 0) + complex(velRand, 0)*complex(rand.Float64(), rand.Float64()) s.P.Move(real(s.Pt), imag(s.Pt)) case RightWheel: v := velMax if s.Adj[0] == nil { _, cols := s.C.f.RowCols(len(s.C.s)) v *= float64(s.Col()+1) / float64(cols+1) th := velMax / (2 * math.Pi * float64(cols+1)) s.Dir *= cmplx.Rect(1, -th) } else { v = vel } s.Pt += complex(v, 0)*s.Dir - ref*complex(gain, 0) + complex(velRand, 0)*complex(rand.Float64(), rand.Float64()) s.P.Move(real(s.Pt), imag(s.Pt)) // case LeftTurn, RightTurn: // s.Color() case Reform: s.Pt -= ref*complex(gainRef, 0) - complex(velRand, 0)*complex(rand.Float64(), rand.Float64()) s.P.Move(real(s.Pt), imag(s.Pt)) if cmplx.Abs(s.Pt-ref) < 0.1 { s.Orders(Halt) } } if s.Adj[0] != nil { s.Dir = cmplx.Rect(1, cmplx.Phase(s.Adj[0].Position()-s.Position())) } }
func mean_angle(deg []float64) float64 { sum := 0i for _, x := range deg { sum += cmplx.Rect(1, deg2rad(x)) } return rad2deg(cmplx.Phase(sum)) }
func roots(n int) []complex128 { r := make([]complex128, n) for i := 0; i < n; i++ { r[i] = cmplx.Rect(1, 2*math.Pi*float64(i)/float64(n)) } return r }
func logInterpolate(a complex128, b complex128, proportion float64) complex128 { // TODO - precalc arg/norm outside the loop. if cmplx.Abs(a) < cmplx.Abs(b) { return logInterpolate(b, a, 1-proportion) } z := b / a zArg := cmplx.Phase(z) if zArg > 0 { // aArg -> bArg, or aArg -> bArg + 2PI, whichever is closer if zArg > math.Pi { zArg -= 2 * math.Pi } } else { // aArg -> bArg, or aArg -> bArg - 2PI, whichever is closer if zArg < -math.Pi { zArg += 2 * math.Pi } } zLogAbs := math.Log(cmplx.Abs(z)) cArg, cLogAbs := zArg*proportion, zLogAbs*proportion cAbs := math.Exp(cLogAbs) return a * cmplx.Rect(cAbs, cArg) }
func agm(a, g complex128) complex128 { for cmplx.Abs(a-g) > cmplx.Abs(a)*ε { a, g = (a+g)*.5, cmplx.Rect(math.Sqrt(cmplx.Abs(a)*cmplx.Abs(g)), (cmplx.Phase(a)+cmplx.Phase(g))*.5) } return a }
func ditfft2(x, y []complex128, n, s int) { if n == 1 { y[0] = x[0] return } ditfft2(x, y, n/2, 2*s) ditfft2(x[s:], y[n/2:], n/2, 2*s) for k := 0; k < n/2; k++ { tf := cmplx.Rect(1, -2*math.Pi*float64(k)/float64(n)) * y[k+n/2] y[k], y[k+n/2] = y[k]+tf, y[k]-tf } }
func TwiddleFactors(N int, ifft bool) []complex128 { out := make([]complex128, N) inv := 1 if ifft { inv = -1 } for i := 0; i < N/2; i++ { out[i] = cmplx.Rect(1, math.Pi*float64(-2*i*inv)/float64(N)) } return out }
func main() { i := 1 fmt.Println("initial:", i) zeroval(i) fmt.Println("zeroval:", i) zeroptr(&i) fmt.Println("zeroptr:", i) fmt.Println("pointer:", &i) complex1 := cmplx.Rect(12, math.Pi/2) fmt.Println(complex1) add180ToComplexNumner(&complex1) fmt.Println(complex1) }
// Rotate rotate the origin center func Rotate(p complex128, rad float64) complex128 { return p * cmplx.Rect(1, rad) }
// LinearMap is linear mapping func LinearMap(u, v complex128) complex128 { return cmplx.Rect(cmplx.Abs(v)/cmplx.Abs(u), Angle(v, u)) }
// TODO - clean up a lot. func NewCQKernel(params CQParams) *CQKernel { // Constructor p := Properties{} p.sampleRate = params.sampleRate p.maxFrequency = params.maxFrequency p.binsPerOctave = params.binsPerOctave // GenerateKernel q := params.q atomHopFactor := params.atomHopFactor thresh := params.threshold bpo := params.binsPerOctave p.minFrequency = float64(math.Pow(2, 1/float64(bpo)) * float64(params.maxFrequency) / 2.0) p.Q = q / (math.Pow(2, 1.0/float64(bpo)) - 1.0) maxNK := float64(int(math.Floor(p.Q*p.sampleRate/p.minFrequency + 0.5))) minNK := float64(int(math.Floor(p.Q*p.sampleRate/ (p.minFrequency*math.Pow(2.0, (float64(bpo)-1.0)/float64(bpo))) + 0.5))) if minNK == 0 || maxNK == 0 { panic("Kernal minNK or maxNK is 0, can't make kernel") } p.atomSpacing = round(minNK*atomHopFactor + 0.5) p.firstCentre = p.atomSpacing * roundUp(math.Ceil(maxNK/2.0)/float64(p.atomSpacing)) p.fftSize = nextPowerOf2(p.firstCentre + roundUp(maxNK/2.0)) p.atomsPerFrame = roundDown(1.0 + (float64(p.fftSize)-math.Ceil(maxNK/2.0)-float64(p.firstCentre))/float64(p.atomSpacing)) if DEBUG { fmt.Printf("atomsPerFrame = %v (q = %v, Q = %v, atomHopFactor = %v, atomSpacing = %v, fftSize = %v, maxNK = %v, firstCentre = %v)\n", p.atomsPerFrame, q, p.Q, atomHopFactor, p.atomSpacing, p.fftSize, maxNK, p.firstCentre) } p.lastCentre = p.firstCentre + (p.atomsPerFrame-1)*p.atomSpacing p.fftHop = (p.lastCentre + p.atomSpacing) - p.firstCentre if DEBUG { fmt.Printf("fftHop = %v\n", p.fftHop) } dataSize := p.binsPerOctave * p.atomsPerFrame kernel := Kernel{ make([]int, 0, dataSize), make([][]complex128, 0, dataSize), } for k := 1; k <= p.binsPerOctave; k++ { nk := int(p.Q*p.sampleRate/(p.minFrequency*math.Pow(2, ((float64(k)-1.0)/float64(bpo)))) + 0.5) win := makeWindow(params.window, nk) fk := float64(p.minFrequency * math.Pow(2, ((float64(k)-1.0)/float64(bpo)))) cmplxs := make([]complex128, nk, nk) for i := 0; i < nk; i++ { arg := (2.0 * math.Pi * fk * float64(i)) / p.sampleRate cmplxs[i] = cmplx.Rect(win[i], arg) } atomOffset := p.firstCentre - roundUp(float64(nk)/2.0) for i := 0; i < p.atomsPerFrame; i++ { shift := atomOffset + (i * p.atomSpacing) cin := make([]complex128, p.fftSize, p.fftSize) for j := 0; j < nk; j++ { cin[j+shift] = cmplxs[j] } cout := fft.FFT(cin) // Keep this dense for the moment (until after normalisation calculations) for j := 0; j < p.fftSize; j++ { if cmplx.Abs(cout[j]) < thresh { cout[j] = complex(0, 0) } else { cout[j] = complexTimes(cout[j], 1.0/float64(p.fftSize)) } } kernel.origin = append(kernel.origin, 0) kernel.data = append(kernel.data, cout) } } if DEBUG { fmt.Printf("size = %v * %v (fft size = %v)\n", len(kernel.data), len(kernel.data[0]), p.fftSize) } // finalizeKernel // calculate weight for normalisation wx1 := maxidx(kernel.data[0]) wx2 := maxidx(kernel.data[len(kernel.data)-1]) subset := make([][]complex128, len(kernel.data), len(kernel.data)) for i := 0; i < len(kernel.data); i++ { subset[i] = make([]complex128, 0, wx2-wx1+1) } for j := wx1; j <= wx2; j++ { for i := 0; i < len(kernel.data); i++ { subset[i] = append(subset[i], kernel.data[i][j]) } } // Massive hack - precalculate above instead :( nrows, ncols := len(subset), len(subset[0]) square := make([][]complex128, ncols, ncols) // conjugate transpose of subset * subset for i := 0; i < ncols; i++ { square[i] = make([]complex128, ncols, ncols) } for j := 0; j < ncols; j++ { for i := 0; i < ncols; i++ { v := complex(0, 0) for k := 0; k < nrows; k++ { v += subset[k][i] * cmplx.Conj(subset[k][j]) } square[i][j] = v } } wK := []float64{} for i := int(1.0/q + 0.5); i < ncols-int(1.0/q+0.5)-2; i++ { wK = append(wK, cmplx.Abs(square[i][i])) } weight := float64(p.fftHop) / float64(p.fftSize) if len(wK) > 0 { weight /= mean(wK) } weight = math.Sqrt(weight) if DEBUG { fmt.Printf("weight = %v (from %v elements in wK, ncols = %v, q = %v)\n", weight, len(wK), ncols, q) } // apply normalisation weight, make sparse, and store conjugate // (we use the adjoint or conjugate transpose of the kernel matrix // for the forward transform, the plain kernel for the inverse // which we expect to be less common) sk := Kernel{ make([]int, len(kernel.data), len(kernel.data)), make([][]complex128, len(kernel.data), len(kernel.data)), } for i := 0; i < len(kernel.data); i++ { sk.origin[i] = 0 sk.data[i] = []complex128{} lastNZ := 0 for j := len(kernel.data[i]) - 1; j >= 0; j-- { if cmplx.Abs(kernel.data[i][j]) != 0 { lastNZ = j break } } haveNZ := false for j := 0; j <= lastNZ; j++ { if haveNZ || cmplx.Abs(kernel.data[i][j]) != 0 { if !haveNZ { sk.origin[i] = j } haveNZ = true sk.data[i] = append(sk.data[i], complexTimes(cmplx.Conj(kernel.data[i][j]), weight)) } } } return &CQKernel{p, &sk} }
func (Polar) CognizePolar(eye *be.Eye, v interface{}) { x := v.(Circuit) eye.Show("Complex", cmplx.Rect(x.FloatAt("R"), x.FloatAt("Theta"))) }
// randomComplex returns a random complex128 func randomComplex() complex128 { return cmplx.Rect(randomFloat(), randomFloat()) }
func add180ToComplexNumner(complexNumber *complex128) { r, θ := cmplx.Polar(*complexNumber) *complexNumber = cmplx.Rect(r, θ+math.Pi/2) }
func (s *Soldier) Row() int { if s.Adj[0] == nil { return 0 } return s.Adj[0].Row() + 1 } */ func (s *Soldier) Col() int { if s.Adj[1] == nil { return 1 } return s.Adj[1].Col() + 1 } var ( left complex128 = cmplx.Rect(1, 0.5*math.Pi) right complex128 = cmplx.Rect(1, -0.5*math.Pi) ) func (s *Soldier) refPoint() complex128 { var pt, tmp, dir complex128 if s.Adj[0] != nil { dir = s.Dir * left * left tmp = s.Adj[0].Position() pt += s.Pt - tmp - complex(spacing, 0)*dir } if s.Adj[3] != nil && s.ByLeft { dir = s.Dir * right tmp = s.Adj[3].Position() pt += s.Pt - tmp - complex(spacing, 0)*dir }