summaryrefslogtreecommitdiff
path: root/appl/math/linbench.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/math/linbench.b')
-rw-r--r--appl/math/linbench.b197
1 files changed, 197 insertions, 0 deletions
diff --git a/appl/math/linbench.b b/appl/math/linbench.b
new file mode 100644
index 00000000..1857093a
--- /dev/null
+++ b/appl/math/linbench.b
@@ -0,0 +1,197 @@
+# 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;
+}