# Translated to Limbo by Eric Grosse <ehg@netlib.bell-labs.com> 3/96# Translated to Java by Reed Wade (wade@cs.utk.edu) 2/96# Translated to C by Bonnie Toy 5/88# Will Menninger, 10/93# Jack Dongarra, linpack, 3/11/78.# Cleve Moler, linpack, 08/14/78 implement linbench; include "sys.m"; sys: Sys; print: import sys;include "math.m"; math: Math; dot, fabs, gemm, iamax: import math;include "draw.m"; draw: Draw; Rect, Screen, Display, Image: import draw;include "tk.m"; tk: Tk; Toplevel: import tk;include "tkclient.m"; tkclient: Tkclient;include "bufio.m"; bufio: Bufio; Iobuf: import bufio;include "linalg.m"; linalg: LinAlg; dgefa, dgesl, printmat: import linalg; ctxt: ref Draw->Context;top: ref Tk->Toplevel;buttonlist: string; linbench: module{ init: fn(nil: ref Draw->Context, argv: list of string);}; tkcmd(arg: string): string{ rv := tk->cmd(top,arg); if(rv!=nil && rv[0]=='!') print("tk->cmd(%s): %s\n",arg,rv); return rv;} init(xctxt: ref Draw->Context, nil: list of string){ sys = load Sys Sys->PATH; math = load Math Math->PATH; draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; tkclient = load Tkclient Tkclient->PATH; linalg = load LinAlg LinAlg->PATH; if(linalg==nil) print("couldn't load LinAlg\n"); sys->pctl(Sys->NEWPGRP, nil); tkclient->init(); ctxt = xctxt; menubut: chan of string; (top, menubut) = tkclient->toplevel(ctxt, "", "Linpack in Limbo", Tkclient->Appl); cmd := chan of string; tk->namechan(top, cmd, "cmd"); tkcmd("pack .Wm_t -fill x"); tkcmd("frame .b"); tkcmd("button .b.Run -text Run -command {send cmd run}"); tkcmd("entry .b.N -width 10w"); tkcmd(".b.N insert 0 200"); tkcmd("pack .b.Run .b.N -side left"); tkcmd("pack .b -anchor w"); tkcmd("frame .d"); tkcmd("listbox .d.f -width 35w -height 150 -selectmode single -yscrollcommand {.d.fscr set}"); tkcmd("scrollbar .d.fscr -command {.d.f yview}"); tkcmd("pack .d.f .d.fscr -expand 1 -fill y -side right"); tkcmd("pack .d -side top"); tkcmd("focus .b.N"); tkcmd("pack propagate . 0;update"); tkclient->onscreen(top, nil); tkclient->startinput(top, "kbd"::"ptr"::nil); for(;;) alt { s := <-top.ctxt.kbd => tk->keyboard(top, s); s := <-top.ctxt.ptr => tk->pointer(top, *s); s := <-top.ctxt.ctl or s = <-top.wreq or s = <-menubut => tkclient->wmctl(top, s); press := <-cmd => case press { "run" => tkcmd("cursor -bitmap cursor.wait; update"); nstr := tkcmd(".b.N get"); n := int nstr; (mflops,secs) := benchmark(n); result := sys->sprint("%8.2f Mflops %8.1f secs",mflops,secs); tkcmd("cursor -default"); tkcmd(".d.f insert end {" + result + "}"); tkcmd(".d.f yview moveto 1; update"); } }} benchmark(n: int): (real,real){ math = load Math Math->PATH; time := array [2] of real; lda := 201; if(n>lda) lda = n; a := array [lda*n] of real; b := array [n] of real; x := array [n] of real; ipvt := array [n] of int; ops := (2*n*n*n)/3 + 2*n*n; norma := matgen(a,lda,n,b); printmat("a",a,lda,n,n); printmat("b",b,lda,n,1); t1 := second(); dgefa(a,lda,n,ipvt); time[0] = second() - t1; printmat("a",a,lda,n,n); t1 = second(); dgesl(a,lda,n,ipvt,b,0); time[1] = second() - t1; total := time[0] + time[1]; for(i := 0; i < n; i++) { x[i] = b[i]; } printmat("x",x,lda,n,1); norma = matgen(a,lda,n,b); for(i = 0; i < n; i++) { b[i] = -b[i]; } dmxpy(b,x,a,lda); resid := 0.; normx := 0.; for(i = 0; i < n; i++){ if(resid<fabs(b[i])) resid = fabs(b[i]); if(normx<fabs(x[i])) normx = fabs(x[i]); } eps_result := math->MachEps; residn_result := (real n)*norma*normx*eps_result; if(residn_result!=0.) residn_result = resid/residn_result; else print("can't scale residual."); if(residn_result>math->sqrt(real n)) print("resid/MachEps=%.3g\n",residn_result); time_result := total; mflops_result := 0.; if(total!=0.) mflops_result = real ops/(1e6*total); else print("can't measure time\n"); return (mflops_result,time_result);} # multiply matrix m times vector x and add the r_result to vector y.dmxpy(y, x, m:array of real, ldm: int){ n1 := len y; n2 := len x; gemm('N','N',n1,1,n2,1.,m,ldm,x,n2,1.,y,n1);} second(): real{ return(real sys->millisec()/1000.);} # generate a (fixed) random matrix and right hand side# a[i][j] => a[lda*i+j]matgen(a: array of real, lda, n: int, b: array of real): real{ seed := 1325; norma := 0.; for(j := 0; j < n; j++) for(i := 0; i < n; i++){ seed = 3125*seed % 65536; a[lda*j+i] = (real seed - 32768.0)/16384.0; if(norma < a[lda*j+i]) norma = a[lda*j+i]; } for (i = 0; i < n; i++) b[i] = 0.; for (j = 0; j < n; j++) for (i = 0; i < n; i++) b[i] += a[lda*j+i]; return norma;}
# Translated to Limbo by Eric Grosse <ehg@netlib.bell-labs.com> 3/96
# Translated to Java by Reed Wade (wade@cs.utk.edu) 2/96
# Translated to C by Bonnie Toy 5/88
# Will Menninger, 10/93
# Jack Dongarra, linpack, 3/11/78.
# Cleve Moler, linpack, 08/14/78
implement linbench;
include "sys.m";
sys: Sys;
print: import sys;
include "math.m";
math: Math;
dot, fabs, gemm, iamax: import math;
include "draw.m";
draw: Draw;
Rect, Screen, Display, Image: import draw;
include "tk.m";
tk: Tk;
Toplevel: import tk;
include "tkclient.m";
tkclient: Tkclient;
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "linalg.m";
linalg: LinAlg;
dgefa, dgesl, printmat: import linalg;
ctxt: ref Draw->Context;
top: ref Tk->Toplevel;
buttonlist: string;
linbench: module
{
init: fn(nil: ref Draw->Context, argv: list of string);
};
tkcmd(arg: string): string{
rv := tk->cmd(top,arg);
if(rv!=nil && rv[0]=='!')
print("tk->cmd(%s): %s\n",arg,rv);
return rv;
}
init(xctxt: ref Draw->Context, nil: list of string)
{
sys = load Sys Sys->PATH;
math = load Math Math->PATH;
draw = load Draw Draw->PATH;
tk = load Tk Tk->PATH;
tkclient = load Tkclient Tkclient->PATH;
linalg = load LinAlg LinAlg->PATH;
if(linalg==nil) print("couldn't load LinAlg\n");
sys->pctl(Sys->NEWPGRP, nil);
tkclient->init();
ctxt = xctxt;
menubut: chan of string;
(top, menubut) = tkclient->toplevel(ctxt, "",
"Linpack in Limbo", Tkclient->Appl);
cmd := chan of string;
tk->namechan(top, cmd, "cmd");
tkcmd("pack .Wm_t -fill x");
tkcmd("frame .b");
tkcmd("button .b.Run -text Run -command {send cmd run}");
tkcmd("entry .b.N -width 10w"); tkcmd(".b.N insert 0 200");
tkcmd("pack .b.Run .b.N -side left");
tkcmd("pack .b -anchor w");
tkcmd("frame .d");
tkcmd("listbox .d.f -width 35w -height 150 -selectmode single -yscrollcommand {.d.fscr set}");
tkcmd("scrollbar .d.fscr -command {.d.f yview}");
tkcmd("pack .d.f .d.fscr -expand 1 -fill y -side right");
tkcmd("pack .d -side top");
tkcmd("focus .b.N");
tkcmd("pack propagate . 0;update");
tkclient->onscreen(top, nil);
tkclient->startinput(top, "kbd"::"ptr"::nil);
for(;;) alt {
s := <-top.ctxt.kbd =>
tk->keyboard(top, s);
s := <-top.ctxt.ptr =>
tk->pointer(top, *s);
s := <-top.ctxt.ctl or
s = <-top.wreq or
s = <-menubut =>
tkclient->wmctl(top, s);
press := <-cmd =>
case press {
"run" =>
tkcmd("cursor -bitmap cursor.wait; update");
nstr := tkcmd(".b.N get");
n := int nstr;
(mflops,secs) := benchmark(n);
result := sys->sprint("%8.2f Mflops %8.1f secs",mflops,secs);
tkcmd("cursor -default");
tkcmd(".d.f insert end {" + result + "}");
tkcmd(".d.f yview moveto 1; update");
}
}
}
benchmark(n: int): (real,real)
{
math = load Math Math->PATH;
time := array [2] of real;
lda := 201;
if(n>lda) lda = n;
a := array [lda*n] of real;
b := array [n] of real;
x := array [n] of real;
ipvt := array [n] of int;
ops := (2*n*n*n)/3 + 2*n*n;
norma := matgen(a,lda,n,b);
printmat("a",a,lda,n,n);
printmat("b",b,lda,n,1);
t1 := second();
dgefa(a,lda,n,ipvt);
time[0] = second() - t1;
printmat("a",a,lda,n,n);
t1 = second();
dgesl(a,lda,n,ipvt,b,0);
time[1] = second() - t1;
total := time[0] + time[1];
for(i := 0; i < n; i++) {
x[i] = b[i];
}
printmat("x",x,lda,n,1);
norma = matgen(a,lda,n,b);
for(i = 0; i < n; i++) {
b[i] = -b[i];
}
dmxpy(b,x,a,lda);
resid := 0.;
normx := 0.;
for(i = 0; i < n; i++){
if(resid<fabs(b[i])) resid = fabs(b[i]);
if(normx<fabs(x[i])) normx = fabs(x[i]);
}
eps_result := math->MachEps;
residn_result := (real n)*norma*normx*eps_result;
if(residn_result!=0.)
residn_result = resid/residn_result;
else
print("can't scale residual.");
if(residn_result>math->sqrt(real n))
print("resid/MachEps=%.3g\n",residn_result);
time_result := total;
mflops_result := 0.;
if(total!=0.)
mflops_result = real ops/(1e6*total);
else
print("can't measure time\n");
return (mflops_result,time_result);
}
# multiply matrix m times vector x and add the r_result to vector y.
dmxpy(y, x, m:array of real, ldm: int)
{
n1 := len y;
n2 := len x;
gemm('N','N',n1,1,n2,1.,m,ldm,x,n2,1.,y,n1);
}
second(): real
{
return(real sys->millisec()/1000.);
}
# generate a (fixed) random matrix and right hand side
# a[i][j] => a[lda*i+j]
matgen(a: array of real, lda, n: int, b: array of real): real
{
seed := 1325;
norma := 0.;
for(j := 0; j < n; j++)
for(i := 0; i < n; i++){
seed = 3125*seed % 65536;
a[lda*j+i] = (real seed - 32768.0)/16384.0;
if(norma < a[lda*j+i]) norma = a[lda*j+i];
}
for (i = 0; i < n; i++)
b[i] = 0.;
for (j = 0; j < n; j++)
for (i = 0; i < n; i++)
b[i] += a[lda*j+i];
return norma;
}