code: purgatorio

ref: 354b56d6bfdca067a6f04a39c4ce4bc9c0160861
dir: /appl/math/linbench.b/

View raw version
# 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;
}