diff --git a/compiler/compiler.go b/compiler/compiler.go index 758d2adc..d750f12e 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1837,6 +1837,25 @@ func (c *Compiler) parseBinOp(op token.Token, typ types.Type, x, y llvm.Value, p cplx = c.builder.CreateInsertValue(cplx, r, 0, "") cplx = c.builder.CreateInsertValue(cplx, i, 1, "") return cplx, nil + case token.MUL: + // Complex multiplication follows the current implementation in + // the Go compiler, with the difference that complex64 + // components are not first scaled up to float64 for increased + // precision. + // https://github.com/golang/go/blob/170b8b4b12be50eeccbcdadb8523fb4fc670ca72/src/cmd/compile/internal/gc/ssa.go#L2089-L2127 + // The implementation is as follows: + // r := real(a) * real(b) - imag(a) * imag(b) + // i := real(a) * imag(b) + imag(a) * real(b) + // Note: this does NOT follow the C11 specification (annex G): + // http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf#page=549 + // See https://github.com/golang/go/issues/29846 for a related + // discussion. + r := c.builder.CreateFSub(c.builder.CreateFMul(r1, r2, ""), c.builder.CreateFMul(i1, i2, ""), "") + i := c.builder.CreateFAdd(c.builder.CreateFMul(r1, i2, ""), c.builder.CreateFMul(i1, r2, ""), "") + cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{r.Type(), i.Type()}, false)) + cplx = c.builder.CreateInsertValue(cplx, r, 0, "") + cplx = c.builder.CreateInsertValue(cplx, i, 1, "") + return cplx, nil default: return llvm.Value{}, c.makeError(pos, "todo: binop on complex number: "+op.String()) } diff --git a/testdata/float.go b/testdata/float.go index 91223023..431d724c 100644 --- a/testdata/float.go +++ b/testdata/float.go @@ -61,7 +61,9 @@ func main() { c64 = 5+2i println("complex64 add: ", c64 + -3+8i) println("complex64 sub: ", c64 - -3+8i) + println("complex64 mul: ", c64 * -3+8i) c128 = -5+2i println("complex128 add:", c128 + 2+6i) println("complex128 sub:", c128 - 2+6i) + println("complex128 mul:", c128 * 2+6i) } diff --git a/testdata/float.txt b/testdata/float.txt index cd75cd21..ac300477 100644 --- a/testdata/float.txt +++ b/testdata/float.txt @@ -25,5 +25,7 @@ (+6.666667e-001+1.200000e+000i) complex64 add: (+2.000000e+000+1.000000e+001i) complex64 sub: (+8.000000e+000+1.000000e+001i) +complex64 mul: (-1.500000e+001+2.000000e+000i) complex128 add: (-3.000000e+000+8.000000e+000i) complex128 sub: (-7.000000e+000+8.000000e+000i) +complex128 mul: (-1.000000e+001+1.000000e+001i)