1
0
mirror of https://github.com/golang/go synced 2024-11-22 01:54:42 -07:00

complex constant multiply and divide

R=rsc
CC=golang-dev
https://golang.org/cl/217041
This commit is contained in:
Ken Thompson 2010-02-18 17:55:11 -08:00
parent d17ffb9753
commit fc010adcd7
5 changed files with 92 additions and 10 deletions

View File

@ -9,6 +9,7 @@ char *runtimeimport =
"func \"\".printfloat (? float64)\n" "func \"\".printfloat (? float64)\n"
"func \"\".printint (? int64)\n" "func \"\".printint (? int64)\n"
"func \"\".printuint (? uint64)\n" "func \"\".printuint (? uint64)\n"
"func \"\".printcomplex (? complex128)\n"
"func \"\".printstring (? string)\n" "func \"\".printstring (? string)\n"
"func \"\".printpointer (? any)\n" "func \"\".printpointer (? any)\n"
"func \"\".printiface (? any)\n" "func \"\".printiface (? any)\n"

View File

@ -5,10 +5,12 @@
#include "go.h" #include "go.h"
#define TUP(x,y) (((x)<<16)|(y)) #define TUP(x,y) (((x)<<16)|(y))
static Val tocplx(Val); static Val tocplx(Val);
static Val toflt(Val); static Val toflt(Val);
static Val tostr(Val); static Val tostr(Val);
static Val copyval(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 * 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); mpsubfltflt(&v.u.cval->imag, &rv.u.cval->imag);
break; break;
case TUP(OMUL, CTCPLX): case TUP(OMUL, CTCPLX):
goto illegal; // TODO cmplxmpy(v.u.cval, rv.u.cval);
break;
case TUP(ODIV, CTCPLX): case TUP(ODIV, CTCPLX):
goto illegal; // TODO cmplxdiv(v.u.cval, rv.u.cval);
break; break;
case TUP(OEQ, CTNIL): case TUP(OEQ, CTNIL):
@ -793,6 +796,13 @@ unary:
mpnegflt(v.u.fval); mpnegflt(v.u.fval);
break; 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): case TUP(ONOT, CTBOOL):
if(!v.u.bval) if(!v.u.bval)
goto settrue; goto settrue;
@ -1187,3 +1197,65 @@ convconst(Node *con, Type *t, Val *val)
fatal("convconst %lT constant", t); 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)
}

View File

@ -20,6 +20,7 @@ func printbool(bool)
func printfloat(float64) func printfloat(float64)
func printint(int64) func printint(int64)
func printuint(uint64) func printuint(uint64)
func printcomplex(complex128)
func printstring(string) func printstring(string)
func printpointer(any) func printpointer(any)
func printiface(any) func printiface(any)

View File

@ -1370,6 +1370,10 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et, char *desc)
if(isint[nt->etype] || isfloat[nt->etype]) if(isint[nt->etype] || isfloat[nt->etype])
return 1; return 1;
// between versions of complex
if(iscomplex[t->etype] || iscomplex[nt->etype])
return 1;
// to string // to string
if(istype(t, TSTRING)) { if(istype(t, TSTRING)) {
// integer rune // integer rune

View File

@ -794,11 +794,13 @@ walkexpr(Node **np, NodeList **init)
case OCONV: case OCONV:
case OCONVNOP: case OCONVNOP:
if(thechar == '5') { 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])); n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
goto ret; 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])); n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64]));
goto ret; goto ret;
} }
@ -1727,7 +1729,7 @@ walkprint(Node *nn, NodeList **init, int defer)
} else if(iscomplex[et]) { } else if(iscomplex[et]) {
if(defer) { if(defer) {
fmtprint(&fmt, "%%f"); fmtprint(&fmt, "%%f");
t = types[TFLOAT64]; t = types[TCOMPLEX128];
} else } else
on = syslook("printcomplex", 0); on = syslook("printcomplex", 0);
} else if(et == TBOOL) { } else if(et == TBOOL) {
@ -2036,8 +2038,10 @@ convas(Node *n, NodeList **init)
if(lt == T || rt == T) if(lt == T || rt == T)
goto out; goto out;
if(isblank(n->left)) if(isblank(n->left)) {
defaultlit(&n->right, T);
goto out; goto out;
}
if(n->left->op == OINDEXMAP) { if(n->left->op == OINDEXMAP) {
n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init, n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init,