summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorKen Thompson <ken@golang.org>2010-02-18 17:55:11 -0800
committerKen Thompson <ken@golang.org>2010-02-18 17:55:11 -0800
commit801d06a1a2e3e5030c3b95f9c83ec3c7e1731d61 (patch)
tree8e48f03cba9d1407132102bb10745653ca4cd8a6 /src/cmd
parent1310f6f87b6f9c30baaf31b3afd3a3dd2f8ff698 (diff)
downloadgolang-801d06a1a2e3e5030c3b95f9c83ec3c7e1731d61.tar.gz
complex constant multiply and divide
R=rsc CC=golang-dev http://codereview.appspot.com/217041
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/gc/builtin.c.boot1
-rw-r--r--src/cmd/gc/const.c84
-rw-r--r--src/cmd/gc/runtime.go1
-rw-r--r--src/cmd/gc/typecheck.c4
-rw-r--r--src/cmd/gc/walk.c12
5 files changed, 92 insertions, 10 deletions
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index 1d881c9d8..6eed40230 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -9,6 +9,7 @@ char *runtimeimport =
"func \"\".printfloat (? float64)\n"
"func \"\".printint (? int64)\n"
"func \"\".printuint (? uint64)\n"
+ "func \"\".printcomplex (? complex128)\n"
"func \"\".printstring (? string)\n"
"func \"\".printpointer (? any)\n"
"func \"\".printiface (? any)\n"
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 1727e775a..f16c52d58 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -5,10 +5,12 @@
#include "go.h"
#define TUP(x,y) (((x)<<16)|(y))
-static Val tocplx(Val);
-static Val toflt(Val);
-static Val tostr(Val);
-static Val copyval(Val);
+static Val tocplx(Val);
+static Val toflt(Val);
+static Val tostr(Val);
+static Val copyval(Val);
+static void cmplxmpy(Mpcplx *v, Mpcplx *rv);
+static void cmplxdiv(Mpcplx *v, Mpcplx *rv);
/*
* truncate float literal fv to 32-bit or 64-bit precision
@@ -614,9 +616,10 @@ evconst(Node *n)
mpsubfltflt(&v.u.cval->imag, &rv.u.cval->imag);
break;
case TUP(OMUL, CTCPLX):
- goto illegal; // TODO
+ cmplxmpy(v.u.cval, rv.u.cval);
+ break;
case TUP(ODIV, CTCPLX):
- goto illegal; // TODO
+ cmplxdiv(v.u.cval, rv.u.cval);
break;
case TUP(OEQ, CTNIL):
@@ -793,6 +796,13 @@ unary:
mpnegflt(v.u.fval);
break;
+ case TUP(OPLUS, CTCPLX):
+ break;
+ case TUP(OMINUS, CTCPLX):
+ mpnegflt(&v.u.cval->real);
+ mpnegflt(&v.u.cval->imag);
+ break;
+
case TUP(ONOT, CTBOOL):
if(!v.u.bval)
goto settrue;
@@ -1187,3 +1197,65 @@ convconst(Node *con, Type *t, Val *val)
fatal("convconst %lT constant", t);
}
+
+// complex multiply v *= rv
+// (a, b) * (c, d) = (a*c - b*d, b*c + a*d)
+static void
+cmplxmpy(Mpcplx *v, Mpcplx *rv)
+{
+ Mpflt ac, bd, bc, ad;
+
+ mpmovefltflt(&ac, &v->real);
+ mpmulfltflt(&ac, &rv->real); // ac
+
+ mpmovefltflt(&bd, &v->imag);
+ mpmulfltflt(&bd, &rv->imag); // bd
+
+ mpmovefltflt(&bc, &v->imag);
+ mpmulfltflt(&bc, &rv->real); // bc
+
+ mpmovefltflt(&ad, &v->real);
+ mpmulfltflt(&ad, &rv->imag); // ad
+
+ mpmovefltflt(&v->real, &ac);
+ mpsubfltflt(&v->real, &bd); // ac-bd
+
+ mpmovefltflt(&v->imag, &bc);
+ mpaddfltflt(&v->imag, &ad); // bc+ad
+}
+
+// complex divide v /= rv
+// (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
+static void
+cmplxdiv(Mpcplx *v, Mpcplx *rv)
+{
+ Mpflt ac, bd, bc, ad, cc_plus_dd;
+
+ mpmovefltflt(&cc_plus_dd, &rv->real);
+ mpmulfltflt(&cc_plus_dd, &rv->real); // cc
+
+ mpmovefltflt(&ac, &rv->imag);
+ mpmulfltflt(&ac, &rv->imag); // dd
+
+ mpaddfltflt(&cc_plus_dd, &ac); // cc+dd
+
+ mpmovefltflt(&ac, &v->real);
+ mpmulfltflt(&ac, &rv->real); // ac
+
+ mpmovefltflt(&bd, &v->imag);
+ mpmulfltflt(&bd, &rv->imag); // bd
+
+ mpmovefltflt(&bc, &v->imag);
+ mpmulfltflt(&bc, &rv->real); // bc
+
+ mpmovefltflt(&ad, &v->real);
+ mpmulfltflt(&ad, &rv->imag); // ad
+
+ mpmovefltflt(&v->real, &ac);
+ mpaddfltflt(&v->real, &bd); // ac+bd
+ mpdivfltflt(&v->real, &cc_plus_dd); // (ac+bd)/(cc+dd)
+
+ mpmovefltflt(&v->imag, &bc);
+ mpsubfltflt(&v->imag, &ad); // bc-ad
+ mpdivfltflt(&v->imag, &cc_plus_dd); // (bc+ad)/(cc+dd)
+}
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 4b9b97136..e350c282d 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -20,6 +20,7 @@ func printbool(bool)
func printfloat(float64)
func printint(int64)
func printuint(uint64)
+func printcomplex(complex128)
func printstring(string)
func printpointer(any)
func printiface(any)
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index d36775b02..9804220d1 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -1370,6 +1370,10 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et, char *desc)
if(isint[nt->etype] || isfloat[nt->etype])
return 1;
+ // between versions of complex
+ if(iscomplex[t->etype] || iscomplex[nt->etype])
+ return 1;
+
// to string
if(istype(t, TSTRING)) {
// integer rune
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index e528e3f6c..e28cf288f 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -794,11 +794,13 @@ walkexpr(Node **np, NodeList **init)
case OCONV:
case OCONVNOP:
if(thechar == '5') {
- if(isfloat[n->left->type->etype] && (n->type->etype == TINT64 || n->type->etype == TUINT64)) {
+ if(isfloat[n->left->type->etype] &&
+ (n->type->etype == TINT64 || n->type->etype == TUINT64)) {
n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
goto ret;
}
- if((n->left->type->etype == TINT64 || n->left->type->etype == TUINT64) && isfloat[n->type->etype]) {
+ if((n->left->type->etype == TINT64 || n->left->type->etype == TUINT64) &&
+ isfloat[n->type->etype]) {
n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64]));
goto ret;
}
@@ -1727,7 +1729,7 @@ walkprint(Node *nn, NodeList **init, int defer)
} else if(iscomplex[et]) {
if(defer) {
fmtprint(&fmt, "%%f");
- t = types[TFLOAT64];
+ t = types[TCOMPLEX128];
} else
on = syslook("printcomplex", 0);
} else if(et == TBOOL) {
@@ -2036,8 +2038,10 @@ convas(Node *n, NodeList **init)
if(lt == T || rt == T)
goto out;
- if(isblank(n->left))
+ if(isblank(n->left)) {
+ defaultlit(&n->right, T);
goto out;
+ }
if(n->left->op == OINDEXMAP) {
n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init,