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 mean_angle(deg []float64) float64 {
	sum := 0i
	for _, x := range deg {
		sum += cmplx.Rect(1, deg2rad(x))
	}
	return rad2deg(cmplx.Phase(sum))
}
Example #3
0
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)
}
Example #4
0
func TestGoertzel(t *testing.T) {
	samplerate := 1024
	blocksize := 1024
	freq := 128
	samples := make([]float64, blocksize)
	w := 2 * math.Pi / float64(samplerate)
	for i := 0; i < blocksize; i++ {
		samples[i] = math.Sin(float64(i) * float64(freq) * w)
	}
	g := NewGoertzel([]uint64{128, 129}, samplerate, blocksize)
	g.Feed(samples)
	m := g.Magnitude()
	if e := math.Pow(float64(blocksize)/2, 2); !approxEqual(m[0], e, 1e-8) {
		t.Errorf("Goertzel magnitude = %f. Want %f", m[0], e)
	}
	if !approxEqual(float64(m[1]), 0.0, 1e-10) {
		t.Errorf("Foertzel magnitude = %f. Want 0.0", m[1])
	}
	c := g.Complex()
	if e, m := math.Sqrt(math.Pow(float64(blocksize)/2, 2)), cmplx.Abs(complex128(c[0])); !approxEqual(m, e, 1e-8) {
		t.Errorf("Goertzel magnitude = %f. Want %f", m, e)
	}
	if e, p := -math.Pi/2, cmplx.Phase(complex128(c[0])); !approxEqual(p, e, 1e-12) {
		t.Errorf("Goertzel phase = %f. Want %f", p, e)
	}
}
Example #5
0
func complexToInt(a []complex128) []int {
	r := make([]int, len(a))
	for n, v := range a {
		// Convert complex phase to percentage int
		r[n] = int(((cmplx.Phase(v) + math.Pi) / math.Pi) * 100)
	}
	return r
}
Example #6
0
// HSLWheelMap generates a ColorMap from a ComplexMap, using a the HSL color
// space with the Argument of the point as the hue, and a nonlinear mapping of
// the absolute value of the point as the lightness.
func HSLWheelMap(fnc ComplexMap) ColorMap {
	return func(point complex128) color.Color {
		val := fnc(point)

		add := math.Pow(cmplx.Abs(val), 2.0)
		// map to [0,1]
		L := add / (add + 1.0)

		// See wikipedia. This is a fairly bad implementation of the algorithm.

		H := (3.0 * cmplx.Phase(point) / math.Pi) + 3.0

		// Get the values being used
		C := (1.0 - math.Abs(2.0*L-1.0))
		X := C * (1.0 - math.Abs(math.Mod(H, 2.0)-1.0))

		// Giant semi-conditional, again, see wikipedia.
		var R1, G1, B1 float64
		switch math.Floor(H) {
		case 0:
			R1 = C
			G1 = X
		case 1:
			R1 = X
			G1 = C
		case 2:
			G1 = C
			B1 = X
		case 3:
			G1 = X
			B1 = C
		case 4:
			R1 = X
			B1 = C
		case 5:
			R1 = C
			B1 = X
		default:
			// Pass on this, 0 initialization is good.
		}

		// m is the "minimum" value of each color.
		m := (L - C/2.0)
		// Convert from [0,1] RGB to [0,255] RGB (and add m while we're at it).
		r := round(255.0 * (R1 + m))
		g := round(255.0 * (G1 + m))
		b := round(255.0 * (B1 + m))

		// We're done. Replace all of the above once Go adds HSL support.
		return color.RGBA{r, g, b, 255}
	}
}
Example #7
0
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()))
	}
}
/* Calculates a color value from a complex number. Brightness is inverse to the
   distance from 0. Color value is dependent on the angle from the real axis,
   starting with red. */
func calculateColor(value complex128) Color {

	// See Wikipedia
	// http://en.wikipedia.org/wiki/Complex_number#Absolute_value_and_argument

	saturation := cmplx.Abs(value)

	// Assume that 2.2 is the max abs we can get, because sqrt(2*2 + 1) ~ 2.2

	saturation /= 2.2

	phase := cmplx.Phase(value) // Phase in [-Pi, Pi]

	if phase < 0 {
		phase = 2*math.Pi + phase
	}

	hue := phase / (2 * math.Pi)

	return hsv.Hsv2rgb(HSVColor{hue, saturation, 1})
}
Example #9
0
File: geo.go Project: yukirin/algo
// Angle determine the angle(radian) of two vectors
func Angle(u, v complex128) float64 {
	return cmplx.Phase(u / v)
}
Example #10
0
func mapColor(ct, limit int, z complex128) color.RGBA {
	if ct == 0 {
		return hsv(cmplx.Phase(z), 1.0, 1.0)
	}
	return hsv(cmplx.Phase(z), 1.0, 0.2)
}
Example #11
0
// Return information about analysed frequency k.
func (a Analysis) Info(k int) (frequency float64, amplitude float64, phase float64) {
	n := float64(len(a.Data))
	frequency = a.SampleRate * float64(k) / n
	x := a.Data[k]
	return frequency, cmplx.Abs(x) / n, -cmplx.Phase(x)
}
Example #12
0
// PolarDiscriminator returns the phase angle between two complex vectors
// equivalent to arg(a * conj(b)). The returned angle is in the range [-Pi, Pi].
func PolarDiscriminator(a, b complex128) float64 {
	return cmplx.Phase(a * cmplx.Conj(b))
}
Example #13
0
func KCMmeans(rawData [][]float64, k int, distanceFunction DistanceFunction, threshold int) ([]int, []Observation, error) {
	var minClusteredData []ClusteredObservation
	var means []Observation
	var err error
	max, trace := int64(0), make([]float64, k)
	for clusters := 1; clusters <= k; clusters++ {
		data := make([]ClusteredObservation, len(rawData))
		for ii, jj := range rawData {
			data[ii].Observation = jj
		}
		seeds := seed(data, clusters, distanceFunction)
		clusteredData, _ := kmeans(data, seeds, distanceFunction, threshold)

		counts := make([]int, clusters)
		for _, jj := range clusteredData {
			counts[jj.ClusterNumber]++
		}

		input := &bytes.Buffer{}
		for c := 0; c < clusters; c++ {
			/*err := binary.Write(input, binary.LittleEndian, rand.Float64())
			if err != nil {
				panic(err)
			}*/

			err := binary.Write(input, binary.LittleEndian, int64(counts[c]))
			if err != nil {
				panic(err)
			}

			for _, jj := range seeds[c] {
				err = binary.Write(input, binary.LittleEndian, jj)
				if err != nil {
					panic(err)
				}
			}

			for _, j := range clusteredData {
				if j.ClusterNumber == c {
					for ii, jj := range j.Observation {
						err = binary.Write(input, binary.LittleEndian, jj-seeds[c][ii])
						if err != nil {
							panic(err)
						}
					}
				}
			}
		}

		in, output := make(chan []byte, 1), &bytes.Buffer{}
		in <- input.Bytes()
		close(in)
		compress.BijectiveBurrowsWheelerCoder(in).MoveToFrontRunLengthCoder().AdaptiveCoder().Code(output)

		/*output := &bytes.Buffer{}
		writer := lzma.NewWriterLevel(output, lzma.BestCompression)
		writer.Write(input.Bytes())
		writer.Close()*/

		complexity := int64(output.Len())
		trace[clusters-1] = float64(complexity)
		fmt.Printf("%v %v\n", clusters, complexity)
		if complexity > max {
			max, minClusteredData, means = complexity, clusteredData, make([]Observation, len(seeds))
			for ii := range seeds {
				means[ii] = make([]float64, len(seeds[ii]))
				for jj := range seeds[ii] {
					means[ii][jj] = seeds[ii][jj]
				}
			}
		}
	}

	f := fft.FFTReal(trace)
	points, phase, complex := make(plotter.XYs, len(f)-1), make(plotter.XYs, len(f)-1), make(plotter.XYs, len(f))
	for i, j := range f[1:] {
		points[i].X, points[i].Y = float64(i), cmplx.Abs(j)
		phase[i].X, phase[i].Y = float64(i), cmplx.Phase(j)
		complex[i].X, complex[i].Y = real(j), imag(j)
	}

	p, err := plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "FFT Real"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err := plotter.NewScatter(points)
	if err != nil {
		panic(err)
	}
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(1)
	p.Add(scatter)
	if err := p.Save(8, 8, "fft_real.png"); err != nil {
		panic(err)
	}

	p, err = plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "FFT Phase"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err = plotter.NewScatter(phase)
	if err != nil {
		panic(err)
	}
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(1)
	scatter.Color = color.RGBA{0, 0, 255, 255}
	p.Add(scatter)
	if err := p.Save(8, 8, "fft_phase.png"); err != nil {
		panic(err)
	}

	p, err = plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "FFT Complex"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err = plotter.NewScatter(complex)
	if err != nil {
		panic(err)
	}
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(1)
	scatter.Color = color.RGBA{0, 0, 255, 255}
	p.Add(scatter)
	if err := p.Save(8, 8, "fft_complex.png"); err != nil {
		panic(err)
	}

	labels := make([]int, len(minClusteredData))
	for ii, jj := range minClusteredData {
		labels[ii] = jj.ClusterNumber
	}
	return labels, means, err
}
Example #14
0
func (o Scomplex128) Angle() RealNum {
	return Sfloat64(cmplx.Phase(complex128(o)))
}