cmplxs: add Real, Imag and Complex functions
MODIFY
cmplxs/cmplxs.go
cmplxs/cmplxs.go
@@ -85,6 +85,22 @@ func Count(f func(complex128) bool, s []complex128) int {
return n
}
+// Complex fills each of the elements of dst with the complex number
+// constructed from the corresponding elements of real and imag.
+// A panic will occur if the lengths of arguments do not match.
+func Complex(dst []complex128, real, imag []float64) []complex128 {
+ if len(dst) != len(real) || len(dst) != len(imag) {
+ panic("cmplxs: length of destination does not match length of the source")
+ }
+ if len(dst) == 0 {
+ return dst
+ }
+ for i, r := range real {
+ dst[i] = complex(r, imag[i])
+ }
+ return dst
+}
+
// CumProd finds the cumulative product of elements of s and store it in
// place into dst so that
// dst[i] = s[i] * s[i-1] * s[i-2] * ... * s[0]
@@ -292,6 +308,21 @@ func HasNaN(s []complex128) bool {
return false
}
+// Imag places the imaginary components of src into dst.
+// A panic will occur if the lengths of arguments do not match.
+func Imag(dst []float64, src []complex128) []float64 {
+ if len(dst) != len(src) {
+ panic("cmplxs: length of destination does not match length of the source")
+ }
+ if len(dst) == 0 {
+ return dst
+ }
+ for i, z := range src {
+ dst[i] = imag(z)
+ }
+ return dst
+}
+
// LogSpan returns a set of n equally spaced points in log space between,
// l and u where N is equal to len(dst). The first element of the
// resulting dst will be l and the final element of dst will be u.
@@ -463,6 +494,21 @@ func Prod(s []complex128) complex128 {
return prod
}
+// Real places the real components of src into dst.
+// A panic will occur if the lengths of arguments do not match.
+func Real(dst []float64, src []complex128) []float64 {
+ if len(dst) != len(src) {
+ panic("cmplxs: length of destination does not match length of the source")
+ }
+ if len(dst) == 0 {
+ return dst
+ }
+ for i, z := range src {
+ dst[i] = real(z)
+ }
+ return dst
+}
+
// Reverse reverses the order of elements in the slice.
func Reverse(s []complex128) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {

MODIFY
cmplxs/cmplxs_test.go
cmplxs/cmplxs_test.go
@@ -14,6 +14,7 @@ import (
"golang.org/x/exp/rand"
"gonum.org/v1/gonum/cmplxs/cscalar"
+ "gonum.org/v1/gonum/floats"
)
const (
@@ -183,6 +184,69 @@ func TestCumProd(t *testing.T) {
areSlicesEqual(t, truth, emptyReceiver, "Wrong cumprod returned with empty receiver")
}
+func TestComplex(t *testing.T) {
+ for i, test := range []struct {
+ dst []complex128
+ real, imag []float64
+ want []complex128
+ panics bool
+ }{
+ {},
+ {
+ dst: make([]complex128, 4),
+ real: []float64{1, 2, 3, 4},
+ imag: []float64{1, 2, 3, 4},
+ want: []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
+ },
+ {
+ dst: make([]complex128, 3),
+ real: []float64{1, 2, 3, 4},
+ imag: []float64{1, 2, 3, 4},
+ panics: true,
+ },
+ {
+ dst: make([]complex128, 4),
+ real: []float64{1, 2, 3},
+ imag: []float64{1, 2, 3, 4},
+ panics: true,
+ },
+ {
+ dst: make([]complex128, 4),
+ real: []float64{1, 2, 3, 4},
+ imag: []float64{1, 2, 3},
+ panics: true,
+ },
+ {
+ dst: make([]complex128, 4),
+ real: []float64{1, 2, 3, 4},
+ imag: []float64{1, 2, 3, math.NaN()},
+ want: []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
+ },
+ } {
+ var got []complex128
+ panicked := Panics(func() {
+ got = Complex(test.dst, test.real, test.imag)
+ })
+ if panicked != test.panics {
+ if panicked {
+ t.Errorf("unexpected panic for test %d", i)
+ } else {
+ t.Errorf("expected panic for test %d", i)
+ }
+ }
+ if panicked || test.panics {
+ continue
+ }
+ if !Same(got, test.dst) {
+ t.Errorf("mismatch between dst and return test %d: got:%v want:%v", i, got, test.dst)
+ }
+ if !Same(got, test.want) {
+ t.Errorf("unexpected result for test %d: got:%v want:%v", i, got, test.want)
+ }
+ }
+
+}
+
func TestCumSum(t *testing.T) {
s := []complex128{3 + 1i, 4 + 2i, 1 + 3i, 7 + 4i, 5 + 5i}
receiver := make([]complex128, len(s))
@@ -481,6 +545,54 @@ func TestHasNaN(t *testing.T) {
}
}
+func TestImag(t *testing.T) {
+ for i, test := range []struct {
+ dst []float64
+ src []complex128
+ want []float64
+ panics bool
+ }{
+ {},
+ {
+ dst: make([]float64, 4),
+ src: []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
+ want: []float64{1, 2, 3, 4},
+ },
+ {
+ dst: make([]float64, 3),
+ src: []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
+ panics: true,
+ },
+ {
+ dst: make([]float64, 4),
+ src: []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
+ want: []float64{1, 2, 3, math.NaN()},
+ },
+ } {
+ var got []float64
+ panicked := Panics(func() {
+ got = Imag(test.dst, test.src)
+ })
+ if panicked != test.panics {
+ if panicked {
+ t.Errorf("unexpected panic for test %d", i)
+ } else {
+ t.Errorf("expected panic for test %d", i)
+ }
+ }
+ if panicked || test.panics {
+ continue
+ }
+ if !floats.Same(got, test.dst) {
+ t.Errorf("mismatch between dst and return test %d: got:%v want:%v", i, got, test.dst)
+ }
+ if !floats.Same(got, test.want) {
+ t.Errorf("unexpected result for test %d: got:%v want:%v", i, got, test.want)
+ }
+ }
+
+}
+
func TestLogSpan(t *testing.T) {
// FIXME(kortschak)
receiver1 := make([]complex128, 6)
@@ -798,6 +910,53 @@ func TestReverse(t *testing.T) {
}
}
+func TestReal(t *testing.T) {
+ for i, test := range []struct {
+ dst []float64
+ src []complex128
+ want []float64
+ panics bool
+ }{
+ {},
+ {
+ dst: make([]float64, 4),
+ src: []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
+ want: []float64{1, 2, 3, 4},
+ },
+ {
+ dst: make([]float64, 3),
+ src: []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
+ panics: true,
+ },
+ {
+ dst: make([]float64, 4),
+ src: []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
+ want: []float64{1, 2, 3, math.NaN()},
+ },
+ } {
+ var got []float64
+ panicked := Panics(func() {
+ got = Real(test.dst, test.src)
+ })
+ if panicked != test.panics {
+ if panicked {
+ t.Errorf("unexpected panic for test %d", i)
+ } else {
+ t.Errorf("expected panic for test %d", i)
+ }
+ }
+ if panicked || test.panics {
+ continue
+ }
+ if !floats.Same(got, test.dst) {
+ t.Errorf("mismatch between dst and return test %d: got:%v want:%v", i, got, test.dst)
+ }
+ if !floats.Same(got, test.want) {
+ t.Errorf("unexpected result for test %d: got:%v want:%v", i, got, test.want)
+ }
+ }
+
+}
func TestSame(t *testing.T) {
s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
s2 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}

cmplxs: add Real, Imag and Complex functions