ref: 2183f9eaeca9fb5d57b637c15707e663caf33575
dir: /appl/math/linbench.b/
# 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;
}