mulfit_optimizers_append("Praxis", "MulfitPraxWrap")

begintemplate MulfitPraxWrap
// public functions
public prun, praxis_efun, after_quad, nquad, showopt, save_optimizer
// public variables
public saveflag, minerr, nstep

objref savepath, tl, pf, tobj, opt
objref start
objref prin_origargs, prin_val, prin_fac, prin_ax
strdef tstr

proc init() {
	nstep = 0
	pf = $o1
	start = new Vector()
	savepath = new File()
	nquad = 0
	st = 0
	currenterr = 1e9
	attr_praxis(1e-4, .5, 0)
	saveflag = 0
	e = 0
}

proc after_quad() {
	if (savepath.isopen) {
		lines += 1
		savepath.printf("%d %d %d %-12.8g ", nquad, opt.nefun, opt.time, opt.minerr)
		saveval()
	}
	printf("nquad=%d nefun=%d time=%d e=%-12.8g\n", nquad, opt.nefun, opt.time, opt.minerr)
	nquad += 1
}

proc saveval() {
	if (numarg() == 1) savepath.printf("%s", $s1)
	tl = pf.parmlist
	for i=0, tl.count-1 {
		savepath.printf("%-12.8g ", tl.object(i).val)
	}
	savepath.printf("\n")
}

func call_opt_efun() {
	return opt.optwrap_efun($1, &$&2)
}

func prun() {
	opt = $o1
	if (saveflag) {
		savepath.wopen("savepath.tmp") // need to put in rank later
		lines = 0
	}
	nquad = 0
	stop_praxis(nstep)
	after_quad()
	minerr = fit_praxis(opt.start.size, "call_opt_efun", &opt.start.x[0],"after_quad()\n")
	if (savepath.isopen) {
		savepath.close
		savepath.aopen("savepath.fit")
		savepath.printf("start\n")
		savepath.printf("%d %d\n", lines, pf.parmlist.count + 2)
		savepath.close
		system("cat savepath.tmp >> savepath.fit")
	}
	return minerr
}

proc showopt() {
	xlabel("quad forms = 0 means praxis returns by itself")
	xpvalue("# quad forms before return", &nstep, 1)
	xbutton("Principal axis variation", "prin_panel()")
}

proc prin_panel() {local i, narg
	prin_origargs = new Vector()//TODO
	narg = pf.doarg_get(prin_origargs)
	prin_val = new Vector(narg)
	prin_fac = new Vector(narg)
	prin_ax = new Matrix(narg, narg)
	for i=0, narg-1 {
		prin_val.x[i] = pval_praxis(i, &prin_ax.x[i][0])
	}
	prin_ax = prin_ax.transpose
	xpanel("Principal Axis Variation")
	for i=0, narg-1 {
		sprint(tstr, "%d %g", i, prin_val.x[i])
		xpvalue(tstr, &prin_fac.x[i], 1, "prin_dovar()")
	}
	xpanel()
}

proc prin_dovar() { local i, narg
	narg = prin_val.size
	tobj = prin_origargs.c
	tobj.add(prin_ax.mulv(prin_fac))
	pf.efun(narg, &tobj.x[0])
	print "prin_val"
	prin_val.printf
	print "prin_ax"
	prin_ax.printf
	print "prin_ax.mulv(prin_fac)"
	prin_ax.mulv(prin_fac).printf
}

proc save_optimizer() {localobj vbox
	vbox = $o1
	sprint(tstr, "nstep = %d", nstep)
	vbox.save(tstr)

}

endtemplate MulfitPraxWrap
