From fc010adcd7005f6eaf646b6edde50d09cac69fc1 Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Thu, 18 Feb 2010 17:55:11 -0800 Subject: [PATCH] complex constant multiply and divide R=rsc CC=golang-dev https://golang.org/cl/217041 --- src/cmd/gc/builtin.c.boot | 1 + src/cmd/gc/const.c | 84 ++++++++++++++++++++++++++++++++++++--- src/cmd/gc/runtime.go | 1 + src/cmd/gc/typecheck.c | 4 ++ src/cmd/gc/walk.c | 12 ++++-- 5 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index 1d881c9d8ea..6eed40230d4 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 1727e775a2b..f16c52d58cf 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 4b9b97136b3..e350c282dd0 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 d36775b0285..9804220d1d4 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 e528e3f6c00..e28cf288fc1 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,