/* Steven Andrews, 9/98; updated 3/02	*//* Basis functions for spectral fitting *//* See documentation called BasisFn doc *//* Copyright 2003 by Steven Andrews.  Permission is granted   for non-commercial use of and modifications to the code. */#include <string.h>#include <float.h>#include <math.h>#include <stdio.h>#include <limits.h>#include "string2.h"#include "math2.h"#include "Set.h"#include "Spectra.h"#include "BasisFn.h"#include "BasisFns.h"#include "Rn.h"#include "Plot.h"#include "random.h"#include "RnLU.h"#include "RnSort.h"#include "Utility.h"#include "SpectFit.h"#include "DiskIO.h"#include "VoidComp.h"#define CHECK(A) {if(!(A)) goto failure;}set basisfns=NULL;basisptr BasisAlloc(int n) {	basisptr b;	int i;	if(n<1) return NULL;	CHECK(b=(basisptr) malloc(sizeof(struct basisfn)));	b->name[0]='\0';	b->proc[0]='\0';	b->color[0]='g';	b->color[1]='\0';	b->desc[0]='\0';	b->addr=NULL;	b->model=NULL;	b->n=n;	b->param=b->pold=b->paramlo=b->paramhi=b->scratch=NULL;	b->eqn=b->pname=NULL;	b->freeze=NULL;	b->isspec=0;	b->spec=NULL;	CHECK(b->param=allocV(n));	CHECK(b->pold=allocV(n));	CHECK(b->paramlo=allocV(n));	CHECK(b->paramhi=allocV(n));	CHECK(b->eqn=(char **) calloc(n,sizeof(char *)));	for(i=0;i<n;i++) b->eqn[i]=NULL;	CHECK(b->pname=(char **) calloc(n,sizeof(char *)));	for(i=0;i<n;i++) b->pname[i]=NULL;	CHECK(b->freeze=(int *) calloc(n,sizeof(int)));	CHECK(b->scratch=allocV(n));	for(i=0;i<n;i++)	{		b->param[i]=b->pold[i]=0;		b->paramlo[i]=-FLT_MAX;		b->paramhi[i]=FLT_MAX;		CHECK(b->eqn[i]=EmptyString());		CHECK(b->pname[i]=EmptyString());		b->freeze[i]=0;		b->scratch[i]=0; }	return b; failure: 	BasisFree(b); 	return NULL; }void BasisFree(basisptr b) {	int i;		if(!b) return;	if(b->param) freeV(b->param);	if(b->pold) freeV(b->pold);	if(b->paramlo) freeV(b->paramlo);	if(b->paramhi) freeV(b->paramhi);	if(b->eqn) {		for(i=0;i<b->n;i++)	if(b->eqn[i]) free(b->eqn[i]);		free(b->eqn); }	if(b->pname) {		for(i=0;i<b->n;i++)	if(b->pname[i]) free(b->pname[i]);		free(b->pname); }	if(b->freeze)	free(b->freeze);	return; }modelptr ModelAlloc(sptr s) {	modelptr m;	m=(modelptr) malloc(sizeof(struct modeltype));	if(!m) return NULL;	m->name[0]='\0';	m->file[0]='\0';	m->color[0]='r';	m->color[1]='\0';	m->spec=s;	m->uncert=NULL;	m->basis=NULL;	m->np=0;	m->sigma=0;	if(s) {		m->xmin=minV(s->x,s->n);		m->xmax=maxV(s->x,s->n);		m->dx=(m->xmax-m->xmin)/(s->n>20?s->n-1:20); }	else {		m->xmin=0;		m->xmax=10;		m->dx=0.5; }	m->covar=NULL;	m->basis=SetAlloc(&StringCmp,NULL);	if(!m->basis) {ModelFree(m);return NULL;}	return m; }void ModelFree(modelptr m) {	void *x,*k;	struct scell *trace;	if(!m) return;	if(m->basis)		for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis))			BasisFree((basisptr)x);	SetFree(m->basis,0,0);	if(m->covar) freeM(m->covar);	free(m);	return; }int CheckBasis(basisptr b,modelptr m) {	void *x,*k;	struct scell *trace;	int i,er;	er=0;	if(b) {		if(!b->isspec) er=0;		else if(b->isspec==1&&b->spec&&!b->spec->cmplx) er=0;		else if(!b->spec) er=16;		else if(b->isspec==1&&b->spec->cmplx) er=8;		else if(b->isspec==2&&!b->spec->cmplx) er=12;		for(i=0;i<b->n&&!er;i++) er=(b->paramlo[i]<=b->paramhi[i])?0:45; }	if(m)		for(trace=SetNext(NULL,&k,&x,m->basis);trace&&!er;trace=SetNext(trace,&k,&x,m->basis)) {			b=(basisptr)x;			if(!b->isspec) er=0;			else if(b->isspec==1&&b->spec&&!b->spec->cmplx) er=0;			else if(!b->spec) er=16;			else if(b->isspec==1&&b->spec->cmplx) er=8;			else if(b->isspec==2&&!b->spec->cmplx) er=12;			for(i=0;i<b->n&&!er;i++) er=(b->paramlo[i]<=b->paramhi[i])?0:45; }	return er; }int CheckMSpec(modelptr m) {	if(!m||!m->spec) return 0;	if(m->spec->cmplx) return 8;	return 0; }int CheckUncert(modelptr m) {	if(!m||!m->uncert) return 0;	if(!m->spec) return 16;	if(m->spec->n!=m->uncert->n) return 11;	if(!equalV(m->spec->x,m->uncert->x,m->spec->n)) return 11;	if(m->spec->cmplx) return 8;	if(minV(m->uncert->y,m->uncert->n)<=0) return 14;		return 0; }int setupbasis() {	set bset;	bset=basisfns=SetAlloc(&StringCmp,NULL);	if(!bset) return 1;	return getbasis(bset); }void PlotBasis(basisptr b) {	float xa,xb,ya,yb,x,dx;	if(!b->model) return;	if(CheckBasis(b,NULL)) return;	GetScales(&xa,&xb,&ya,&yb);	if(b->model->xmin>xa)	xa=b->model->xmin;	if(b->model->xmax<xb)	xb=b->model->xmax;	dx=b->model->dx;	SetColor(b->color[0]);	PlotPt(xa,(b->addr)(xa,b->param,b->spec,NULL));	for(x=xa;x<xb;x+=dx)		PlotLine(x,(b->addr)(x,b->param,b->spec,NULL));	PlotLine(xb,(b->addr)(xb,b->param,b->spec,NULL));	SetColor('0');	return; }void PlotModel(modelptr m) {	float xa,xb,ya,yb,x,dx;	if(CheckBasis(NULL,m)) return;	GetScales(&xa,&xb,&ya,&yb);	if(m->xmin>xa)	xa=m->xmin;	if(m->xmax<xb)	xb=m->xmax;	dx=m->dx;	SetColor(m->color[0]);	PlotPt(xa,ModelValue(xa,m));	for(x=xa;x<xb;x+=dx)		PlotLine(x,ModelValue(x,m));	PlotLine(xb,ModelValue(xb,m));		SetColor('0');	return; }void BasisRange(basisptr b,float *xa,float *xb,float *ya,float *yb,int fn) {	float y,ylo,yhi,xlo,xhi,x;		if(!b->model) return;	if(CheckBasis(b,NULL)) return;	xlo=b->model->xmin;	if(!fn||fn<0&&*xa<xlo||fn>0&&*xa>xlo) *xa=xlo;	xhi=b->model->xmax;	if(!fn||fn<0&&*xb>xhi||fn>0&&*xb<xhi) *xb=xhi;	if(xlo<*xa) xlo=*xa;	if(xhi>*xb) xhi=*xb;	ylo=yhi=(b->addr)(xlo,b->param,b->spec,NULL);	for(x=xlo;x<xhi;x+=b->model->dx)	{		y=(b->addr)(x,b->param,b->spec,NULL);		if(y<ylo) ylo=y;		else if(y>yhi) yhi=y; }	if(!fn||fn<0&&*ya<ylo||fn>0&&*ya>ylo) *ya=ylo;	if(!fn||fn<0&&*yb>yhi||fn>0&&*yb<yhi) *yb=yhi;	return; }void ModelRange(modelptr m,float *xa,float *xb,float *ya,float *yb,int fn) {	float y,ylo,yhi,xlo,xhi,x;		if(CheckBasis(NULL,m)) return;	xlo=m->xmin;	if(!fn||fn<0&&*xa<xlo||fn>0&&*xa>xlo) *xa=xlo;	xhi=m->xmax;	if(!fn||fn<0&&*xb>xhi||fn>0&&*xb<xhi) *xb=xhi;	if(xlo<*xa) xlo=*xa;	if(xhi>*xb) xhi=*xb;	ylo=yhi=ModelValue(xlo,m);	for(x=xlo;x<xhi;x+=m->dx)	{		y=ModelValue(x,m);		if(y<ylo) ylo=y;		else if(y>yhi) yhi=y; }	if(!fn||fn<0&&*ya<ylo||fn>0&&*ya>ylo) *ya=ylo;	if(!fn||fn<0&&*yb>yhi||fn>0&&*yb<yhi) *yb=yhi;	return; }int CountFreParam(modelptr m,int **frzptr) {	int i,j,nfre;	void *k,*item;	struct scell *trace;	basisptr b;	nfre=0;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{		b=(basisptr)item;		for(i=0;i<b->n;i++) if(!b->freeze[i]) nfre++; }	if(frzptr) {		*frzptr=(int *)calloc(m->np,sizeof(int));		if(!*frzptr) return -1;		j=0;		for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{			b=(basisptr)item;			for(i=0;i<b->n;i++) (*frzptr)[j++]=b->freeze[i]; }}	return nfre; }int FindBasisParam(basisptr *bptr,modelptr m,char* str) {	int i;	basisptr b;	void *k,*item;	struct scell *trace;	b=*bptr;	if(b)	{		for(i=0;i<b->n;i++) if(!strcmp(b->pname[i],str)) return i;		return -1; }	if(!m) return -1;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{		b=*bptr=(basisptr)item;		for(i=0;i<b->n;i++) if(!strcmp(b->pname[i],str)) return i; }	*bptr=NULL;	return -1; }int FindBasisParam2(basisptr *bptr,modelptr m,float* fltptr) {	int i;	basisptr b;	void *k,*item;	struct scell *trace;	if(!m) return -1;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{		b=*bptr=(basisptr)item;		for(i=0;i<b->n;i++) if(&(b->param[i])==fltptr) return i; }	*bptr=NULL;	return -1; }float ModelValue(float x,modelptr m) {	float y=0;	void *k,*item;	struct scell *trace;	basisptr b;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{		b=(basisptr)item;		y+=(b->addr)(x,b->param,b->spec,NULL); }	return y; }float ModelValueD(float x,modelptr m,float *d) {	float y=0;	int i,j;	void *k,*item;	struct scell *trace;	basisptr b;		j=0;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{		b=(basisptr)item;		y+=(b->addr)(x,b->param,b->spec,b->scratch);		for(i=0;i<b->n;i++)			if(!b->freeze[i]) d[j++]=b->scratch[i]; }	return y; }void TypeBasis(basisptr b) {	int i;	if(!b) {		printf("NULL basis function.\n");		return; }	if(b->model) printf("%s is a basis function in model %s\n",b->name,b->model->name);	else printf("%s is a basis function without a model\n",b->name);	printf(" procedure: %s, color: %s, %i parameters\n",b->proc,b->color,b->n);	printf(" description: %s\n",b->desc);	for(i=0;i<b->n;i++)	{		printf("\t%s=%f\t%s\n",b->pname[i],b->param[i],b->freeze[i]?"fix":"free");		if(strlen(b->eqn[i])) printf("\t\teqn %sactive: %s\n",b->freeze[i]?"":"in",b->eqn[i]);		if(b->paramlo[i]>-FLT_MAX&&b->paramhi[i]<FLT_MAX)			printf("\t\t%f ² %s ² %f\n",b->paramlo[i],b->pname[i],b->paramhi[i]);		else if(b->paramlo[i]>-FLT_MAX)			printf("\t\t%f ² %s\n",b->paramlo[i],b->pname[i]);		else if(b->paramhi[i]<FLT_MAX)			printf("\t\t%s ² %f\n",b->pname[i],b->paramhi[i]); }	if(b->isspec&&!b->spec)		printf(" spectrum required, none assigned.\n");	else if(b->isspec==1&&!b->spec->cmplx)		printf(" spectrum: %s\n",b->spec);	else if(b->isspec==1&&b->spec->cmplx)		printf(" complex spectrum should be real: %s\n",b->spec);	else if(b->isspec==2&&b->spec->cmplx)		printf(" complex spectrum: %s\n",b->spec);	else if(b->isspec==2&&!b->spec->cmplx)		printf(" real spectrum should be complex: %s\n",b->spec);	else if(b->isspec)		printf(" spectrum: %s\n",b->spec);	printf("\n"); }void TypeAllBasis() {	struct scell *trace;	void *k,*x;		if(!basisfns) {		printf("Set of basis functions not loaded in.\n");		return; }	printf("%i basis functions loaded.\n",SetCard(basisfns));	for(trace=SetNext(NULL,&k,&x,basisfns);trace;trace=SetNext(trace,&k,&x,basisfns))		printf(" %s\t%s\n",(char *) k,((basisptr)x)->desc);	return; }void TypeModel(modelptr m) {	struct scell *trace;	void *k,*x;	int n,nfre,i,j,npts;	basisptr b;	sptr s;	if(!m) {		printf("No model.\n");		return; }	if(m->spec) printf("Model: %s for spectrum %s\n",m->name,m->spec->name);	else printf("Model: %s, no spectrum\n",m->name);	if(strlen(m->file)) printf(" model file: %s\n",m->file);	printf(" domain: %f to %f, color: %s\n",m->xmin,m->xmax,m->color);	if(CheckUncert(m)) printf(" invalid uncertainties\n");	else if(m->sigma>0&&m->uncert)		printf(" sigma: %f, uncertainties in: %s\n",m->sigma,m->uncert->name);	else if(m->sigma>0) printf(" sigma: %f\n",m->sigma);	else if(m->uncert) printf(" uncertainties in: %s\n",m->uncert->name);	if(m->spec) {		s=m->spec;		if(s->x[0]>=m->xmin) i=0;		else {			i=locateV(s->x,m->xmin,s->n);			if(i<0) i=0;			else if(s->x[i]<m->xmin) i++; }		if(s->x[s->n-1]<=m->xmax) j=s->n-1;		else j=locateV(s->x,m->xmax,s->n);		npts=j-i+1;		printf(" points: %i, params: %i with %i free\n",npts,m->np,CountFreParam(m,NULL));		if(CheckBasis(NULL,m))			printf(" a basis set is missing numerical data.\n");		else if(m->uncert||m->sigma>0)			printf(" chi^2: %e, rms error: %e\n",chisq(m,-1),rmserror(m));		else printf(" rms error: %e\n",rmserror(m)); }	else {		npts=0;		printf(" no spectrum\n",m->name); }	n=m->np;	j=0;	for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis))	{		b=(basisptr)x;		printf(" %s\n",b->name);		for(i=0;i<b->n;i++)	{			if(m->covar&&!b->freeze[i])				printf("  %s= %f ± %f\tfree\n",b->pname[i],b->param[i],sqrt(m->covar[n*j+j]));			else				printf("  %s= %f\t\t\t%s\n",b->pname[i],b->param[i],b->freeze[i]?"fix":"free");			if(b->eqn[i]&&strlen(b->eqn[i]))				printf("\t\t%sactive eqn:%s\n",b->freeze[i]?"":"in",b->eqn[i]);			if(b->paramlo[i]>-FLT_MAX&&b->paramhi[i]<FLT_MAX)				printf("   %f ² %s ² %f\n",b->paramlo[i],b->pname[i],b->paramhi[i]);			else if(b->paramlo[i]>-FLT_MAX)				printf("   %f ² %s\n",b->paramlo[i],b->pname[i]);			else if(b->paramhi[i]<FLT_MAX)				printf("   %s ² %f\n",b->pname[i],b->paramhi[i]);			j++; }}	printf("\n");	return; }basisptr BasisCopy(basisptr b) {	basisptr a;	int i;		if(!b) return NULL;	a=BasisAlloc(b->n);   // *****************	if(!a) return NULL;	strcpy(a->name,b->name);	strcpy(a->proc,b->proc);	strcpy(a->color,b->color);	strcpy(a->desc,b->desc);	a->model=b->model;	a->addr=b->addr;	for(i=0;i<a->n;i++)	{		a->param[i]=b->param[i];		a->pold[i]=b->pold[i];		a->paramlo[i]=b->paramlo[i];		a->paramhi[i]=b->paramhi[i];		strcpy(a->pname[i],b->pname[i]);		strcpy(a->eqn[i],b->eqn[i]);		a->freeze[i]=b->freeze[i];		a->scratch[i]=b->scratch[i]; }	a->isspec=b->isspec;	a->spec=b->spec;	return a; }modelptr ModelCopy(modelptr m) {	modelptr a;	basisptr b;	struct scell *trace;	void *key,*item;	int ok;	if(!m) return NULL;	a=ModelAlloc(m->spec);	if(!a) return NULL;	a->uncert=m->uncert;	strcpy(a->name,m->name);	strcpy(a->file,m->file);	strcpy(a->color,m->color);	a->sigma=m->sigma;	a->np=m->np;	a->xmin=m->xmin;	a->xmax=m->xmax;	a->dx=m->dx;	if(m->covar) {		a->covar=allocM(a->np,a->np);		if(!a->covar) {ModelFree(a);return NULL;}		copyM(m->covar,a->covar,m->np,m->np); }	for(trace=SetNext(NULL,&key,&item,m->basis);trace;trace=SetNext(trace,&key,&item,m->basis))	{		b=BasisCopy((basisptr)item);		if(b)	{			b->model=a;			ok=SetInsert((void *)b->name,(void *)b,a->basis);			if(!ok) {ModelFree(a);return NULL;}}}	return a; }basisptr AddBasis(basisptr b,char *bproc,sptr s,modelptr m) {	void *x;	basisptr b2;	int i,ok;	if(b)	b=BasisCopy(b);	else if(bproc) b=BasisCopy((basisptr)SetItem((void *)bproc,basisfns));	if(!b) return NULL;	if(!strchr(b->name,':'))		sprintf(b->name+strlen(b->name),":");	i=0;	sprintf(strchr(b->name,':')+1,"%i",i++);	for(x=SetItem((void *)b->name,m->basis);x;x=SetItem((void *)b->name,m->basis))		sprintf(strchr(b->name,':')+1,"%i",i++);	b->model=m;	b->spec=s;	if(!b->addr)	{		b2=SetItem((void *)b->proc,basisfns);		if(b2) b->addr=b2->addr;		else {BasisFree(b);return NULL;}}	ok=SetInsert((void *)b->name,(void *)b,m->basis);	if(!ok) {BasisFree(b);return NULL;}	m->np+=b->n;	if(m->covar) {		freeM(m->covar);		m->covar=NULL; }	return b; }void RemoveBasis(basisptr b) {	modelptr m;	if(!b) return;	m=b->model;	if(!m) return;	if(SetDelete((void*)b->name,(void*)b,b->model->basis,0,0)) {		m->np-=b->n;		if(m->covar) {			freeM(m->covar);			m->covar=NULL; }}	b->model=NULL;	return; }int SaveModel(modelptr m) {	FILE *fptr;	char *name;	int nmfre,er,i,j;	char str[STRCHAR];	struct scell *trace;	void *k,*x;	basisptr b;	name=m->file;	er=GetName(&name,&nmfre);	if(er) {m->file[0]='\0';return er;}	if(!strcmp(name,"stdout")) fptr=stdout;	else {		fptr=fopen(name,"r");		if(fptr) {			fclose(fptr);			fprintf(stderr,"File exists. Do you want to overwrite it? ");			scanf("%s",str);			if(str[0]!='y'&&str[0]!='Y') {				if(nmfre) free(name);				m->file[0]='\0';				return 2; }}		fptr=fopen(name,"w"); }	if(nmfre) free(name);	if(!fptr) return 3;	er=0;	er=er||fprintf(fptr,"# Model saved by SpectFit 2.0.\n\n")<0;	er=er||fprintf(fptr,"name: %s\n",m->name)<0;	er=er||fprintf(fptr,"file: %s\n",m->file)<0;	er=er||fprintf(fptr,"color: %s\n",m->color)<0;	er=er||fprintf(fptr,"# data modeled: %s\n",m->spec?m->spec->name:"none")<0;	er=er||fprintf(fptr,"# uncertainties: %s\n",m->uncert?m->uncert->name:"none")<0;	er=er||fprintf(fptr,"sigma: %f\n",m->sigma)<0;	er=er||fprintf(fptr,"xmin: %f\n",m->xmin)<0;	er=er||fprintf(fptr,"xmax: %f\n",m->xmax)<0;	er=er||fprintf(fptr,"dx: %f\n",m->dx)<0;	if(CheckBasis(NULL,m))		er=er||fprintf(fptr,"# a basis set is missing numerical data.\n")<0;	else if(m->uncert||m->sigma>0)		er=er||fprintf(fptr,"# chi^2: %e, rms error: %e\n",chisq(m,-1),rmserror(m))<0;	else		er=er||fprintf(fptr,"# rms error: %e\n",rmserror(m))<0;	j=0;	for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis))	{		b=(basisptr)x;		er=er||fprintf(fptr,"basis: %s\n",b->proc)<0;		er=er||fprintf(fptr," name: %s\n",b->name)<0;		er=er||fprintf(fptr," color: %s\n",b->color)<0;		er=er||fprintf(fptr," desc: %s\n",b->desc)<0;		if(b->spec)			er=er||fprintf(fptr," spec: %s\n",b->spec->name)<0;		for(i=0;i<b->n;i++)	{			er=er||fprintf(fptr," param: %s\n",b->pname[i])<0;			if(m->covar&&!b->freeze[i])				er=er||fprintf(fptr,"  value: %f ± %f\n",b->param[i],sqrt(m->covar[m->np*j+j]))<0;			else				er=er||fprintf(fptr,"  value: %f\n",b->param[i])<0;			j++;			if(b->freeze[i])				er=er||fprintf(fptr,"  fix\n")<0;			if(strlen(b->eqn[i]))				er=er||fprintf(fptr,"  eqn: %s\n",b->eqn[i])<0;			if(b->paramlo[i]>-FLT_MAX)				er=er||fprintf(fptr,"  min: %f\n",b->paramlo[i])<0;			if(b->paramhi[i]<FLT_MAX)				er=er||fprintf(fptr,"  max: %f\n",b->paramhi[i])<0; }		er=er||fprintf(fptr," endbasis\n")<0; }	if(er) er=3;	fclose(fptr);	return er; }int LoadModel(modelptr *mptr,char *name,sptr s) {	FILE *fptr;	modelptr m;	basisptr b;	char line[STRCHAR],word[STRCHAR],word2[STRCHAR],*line2;	int i,er,nmfre,itct,endflag;	if(!mptr) return 6;	m=*mptr=NULL;	er=GetName(&name,&nmfre);	if(er) return er;	if(!strcmp(name,"stdin")) fptr=stdin;	else fptr=fopen(name,"r");	if(nmfre) free(name);	if(!fptr) return 5;	m=ModelAlloc(s);	if(!m) {er=1;goto failure;}		endflag=0;	er=1000;	while(!endflag&&fgets(line,STRCHAR,fptr)) {		er++;		if(strlen(line)<STRCHAR-1) line[strlen(line)-1]='\0';		itct=sscanf(line,"%s",word);		line2=strnword(line,2);		if(line2) sscanf(line2,"%s",word2);		if(itct<=0);		else if(line[0]=='#');		else if(!strcmp(word,"end"))			endflag=1;		else if(!line2) goto failure;		else if(!strcmp(word,"name:"))			strncpy(m->name,word2,STRCHAR);		else if(!strcmp(word,"file:"))			strncpy(m->file,word2,STRCHAR);		else if(!strcmp(word,"color:"))			strncpy(m->color,word2,STRCHAR);		else if(!strcmp(word,"sigma:")) {			CHECK(sscanf(line2,"%f",&m->sigma)==1); }		else if(!strcmp(word,"xmin:")) {			CHECK(sscanf(line2,"%f",&m->xmin)==1); }		else if(!strcmp(word,"xmax:")) {			CHECK(sscanf(line2,"%f",&m->xmax)==1); }		else if(!strcmp(word,"dx:")) {			CHECK(sscanf(line2,"%f",&m->dx)==1); }		else if(!strcmp(word,"basis:")) {			CHECK(b=AddBasis(NULL,word2,NULL,m));			i=-1;			while(!endflag&&fgets(line,STRCHAR,fptr)) {				er++;				if(strlen(line)<STRCHAR-1) line[strlen(line)-1]='\0';				itct=sscanf(line,"%s",word);				line2=strnword(line,2);				if(line2) sscanf(line2,"%s",word2);				if(itct<=0);				else if(line[0]=='#');				else if(!strcmp(word,"endbasis")) {					for(i=0;i<b->n;i++) {						CHECK(b->paramlo[i]<=b->paramhi[i]); }					CHECK(!b->isspec||b->spec);					endflag=1; }				else if(!strcmp(word,"fix")&&i>-1)					b->freeze[i]=1;				else if(!strcmp(word,"free")&&i>-1)					b->freeze[i]=0;				else if(!line2) goto failure;				else if(!strcmp(word,"name:")) {					if(!SetItem((void *)word2,m->basis))						strncpy(b->name,word2,STRCHAR); }				else if(!strcmp(word,"color:"))					strncpy(b->color,word2,STRCHAR);				else if(!strcmp(word,"desc:"))					strncpy(b->desc,line2,STRCHAR);				else if(!strcmp(word,"spec:")) {					CHECK(b->spec=Name2Spec(word2)); }				else if(!strcmp(word,"param:")) {					for(i=0;i<b->n&&strcmp(b->pname[i],word2);i++)					CHECK(i<b->n); }				else if(!strcmp(word,"value:")&&i>-1) {					CHECK(sscanf(line2,"%f",&b->param[i])==1); }				else if(!strcmp(word,"min:")&&i>-1) {					CHECK(sscanf(line2,"%f",&b->paramlo[i])==1); }				else if(!strcmp(word,"max:")&&i>-1) {					CHECK(sscanf(line2,"%f",&b->paramhi[i])==1); }				else if(!strcmp(word,"eqn:")&&i>-1)					strncpy(b->eqn[i],line2,STRCHAR);				else goto failure; } 			endflag=0; }		else goto failure; }	if(fptr!=stdin) fclose(fptr);	fptr=NULL;	CHECK(m->xmin<m->xmax&&m->dx>0);	*mptr=m;	return 0; failure:	if(fptr&&fptr!=stdin) fclose(fptr);	ModelFree(m);	*mptr=NULL;	return er; }int BasisMath(basisptr b,void *v,sptr *ansptr,float k,char *fn) {	float dx,y,xlo,*param,*s3x,*s3y;	int i,j,n,er;	sptr s,s3,bspec;	basisptr b2;	if(!b||!ansptr||!fn||!b->model||!b->model->spec) return 6;	if((er=CheckBasis(b,NULL))) return er;	if(*ansptr) SpectFree(*ansptr);	*ansptr=NULL;	s3=SpectAlloc(b->name,NULL,fn,b->model->spec->xunit,b->model->spec->yunit);	if(!s3) return 1;	strncat(s3->name,"s",STRCHAR-strlen(s3->name));	strncat(s3->desc,b->name,STRCHAR-strlen(s3->desc));	strncat(s3->desc," ",STRCHAR-strlen(s3->desc));	strncat(s3->desc,fn,STRCHAR-strlen(s3->desc));	dx=b->model->dx;	xlo=b->model->xmin;	n=s3->n=(b->model->xmax-xlo)/dx+1;	s3x=s3->x=allocV(n);	s3y=s3->y=allocV(n);	if(!s3->x||!s3->y) {SpectFree(s3);return 1;}	for(i=0;i<n;i++) s3->x[i]=xlo+i*dx;	param=b->param;	bspec=b->spec;	if(!strcmp(fn,"exp b"))		for(i=0;i<n;i++) {			y=exp((b->addr)(s3x[i],param,bspec,NULL));			s3y[i]=y<=FLT_MAX?y:0; }	else if(!strcmp(fn,"ln b"))		for(i=0;i<n;i++) {			y=(b->addr)(s3x[i],param,bspec,NULL);			s3y[i]=y>0?log(y):0; }	else if(!strcmp(fn,"10^b"))		for(i=0;i<n;i++) {			y=pow(10,(b->addr)(s3x[i],param,bspec,NULL));			s3y[i]=y<=FLT_MAX?y:0; }	else if(!strcmp(fn,"log b"))		for(i=0;i<n;i++) {			y=(b->addr)(s3x[i],param,bspec,NULL);			s3y[i]=y>0?log10(y):0; }	else if(!strcmp(fn,"sqrt b"))		for(i=0;i<n;i++) {			y=(b->addr)(s3x[i],param,bspec,NULL);			s3y[i]=y>0?sqrt(y):0; }	else if(!strcmp(fn,"b+s")||!strcmp(fn,"s+b"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3->y[i]=interpolate1(s->x,s->y,s->n,&j,s3x[i])+(b->addr)(s3x[i],param,bspec,NULL); }	else if(!strcmp(fn,"b-s"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)-interpolate1(s->x,s->y,s->n,&j,s3x[i]); }	else if(!strcmp(fn,"b*s")||!strcmp(fn,"s*b"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3y[i]=interpolate1(s->x,s->y,s->n,&j,s3x[i])*(b->addr)(s3x[i],param,bspec,NULL); }	else if(!strcmp(fn,"b/s"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++) {			y=interpolate1(s->x,s->y,s->n,&j,s3x[i]);			s3y[i]=(y<0||y>0)?(b->addr)(s3x[i],param,bspec,NULL)/y:0; }}	else if(!strcmp(fn,"s-b"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3y[i]=interpolate1(s->x,s->y,s->n,&j,s3x[i])-(b->addr)(s3x[i],param,bspec,NULL); }	else if(!strcmp(fn,"s/b"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++) {			y=(b->addr)(s3x[i],param,bspec,NULL);			s3y[i]=(y<0||y>0)?interpolate1(s->x,s->y,s->n,&j,s3x[i])/y:0; }}	else if(!strcmp(fn,"b+b"))	{		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)+(b2->addr)(s3x[i],b2->param,b2->spec,NULL); }	else if(!strcmp(fn,"b-b")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)-(b2->addr)(s3x[i],b2->param,b2->spec,NULL); }	else if(!strcmp(fn,"b*b"))	{		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)*(b2->addr)(s3x[i],b2->param,b2->spec,NULL); }	else if(!strcmp(fn,"b/b")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++) {			y=(b2->addr)(s3x[i],b2->param,b2->spec,NULL);			s3y[i]=(y<0||y>0)?(b->addr)(s3x[i],b->param,b->spec,NULL)/y:0; }}	else if(!strcmp(fn,"b+k")||!strcmp(fn,"k+b"))		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)+k;	else if(!strcmp(fn,"b*k")||!strcmp(fn,"k*b"))		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)*k;	else if(!strcmp(fn,"k-b"))		for(i=0;i<n;i++)			s3y[i]=k-(b->addr)(s3x[i],param,bspec,NULL);	else if(!strcmp(fn,"k/b"))		for(i=0;i<n;i++) {			y=(b->addr)(s3x[i],param,bspec,NULL);			s3y[i]=(y<0||y>0)?k/y:0; }	else if(!strcmp(fn,"b-k"))		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)-k;	else if(!strcmp(fn,"b/k")) {		if(!(k<0||k>0)) {SpectFree(s3);return 9;}		for(i=0;i<n;i++)			s3y[i]=(b->addr)(s3x[i],param,bspec,NULL)/k; }	else if(!strcmp(fn,"b^k"))		if(k>0) for(i=0;i<n;i++)				s3y[i]=pow((b->addr)(s3x[i],param,bspec,NULL),k);		else if(k==floor(k)) for(i=0;i<n;i++) {				y=(b->addr)(s3x[i],param,bspec,NULL);				s3y[i]=(y<0||y>0)?pow(y,k):0; }		else for(i=0;i<n;i++) {				y=(b->addr)(s3x[i],param,bspec,NULL);				s3y[i]=y>0?pow(y,k):0; }	else {		SpectFree(s3);		return 7; }	*ansptr=s3;	return 0; }int ModelMath(modelptr m,void *v,sptr *ansptr,float k,char *fn) {	float dx,y,*s3x,*s3y;	int i,j,n,er;	basisptr b2;	modelptr m2;	sptr s3,s;	if(!m||!ansptr||!fn) return 6;	if((er=CheckBasis(NULL,m))) return er;	if(*ansptr) SpectFree(*ansptr);	*ansptr=NULL;	if(m->spec) s3=SpectAlloc(m->name,NULL,fn,m->spec->xunit,m->spec->yunit);	else s3=SpectAlloc(m->name,NULL,fn,"x","y");	if(!s3) return 1;	strncat(s3->name,"s",STRCHAR-strlen(s3->name));	strncat(s3->desc,m->name,STRCHAR-strlen(s3->desc));	strncat(s3->desc," ",STRCHAR-strlen(s3->desc));	strncat(s3->desc,fn,STRCHAR-strlen(s3->desc));	dx=m->dx;	n=s3->n=(m->xmax-m->xmin)/dx+1;	s3x=s3->x=allocV(n);	s3y=s3->y=allocV(n);	if(!s3x||!s3y) {SpectFree(s3);return 1;}	for(i=0;i<n;i++) s3x[i]=m->xmin+i*dx;	if(!strcmp(fn,"exp m"))		for(i=0;i<n;i++) {			y=exp(ModelValue(s3x[i],m));			s3y[i]=y<=FLT_MAX?y:0; }	else if(!strcmp(fn,"ln m"))		for(i=0;i<n;i++) {			y=ModelValue(s3x[i],m);			s3y[i]=y>0?log(y):0; }	else if(!strcmp(fn,"10^m"))		for(i=0;i<n;i++) {			y=pow(10,ModelValue(s3x[i],m));			s3y[i]=y<=FLT_MAX?y:0; }	else if(!strcmp(fn,"log m"))		for(i=0;i<n;i++) {			y=ModelValue(s3x[i],m);			s3y[i]=y>0?log10(y):0; }	else if(!strcmp(fn,"sqrt m"))		for(i=0;i<n;i++) {			y=ModelValue(s3x[i],m);			s3y[i]=y>0?sqrt(y):0; }	else if(!strcmp(fn,"m+s")||!strcmp(fn,"s+m"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3y[i]=interpolate1(s->x,s->y,s->n,&j,s3x[i])+ModelValue(s3x[i],m); }	else if(!strcmp(fn,"m-s")) {		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)-interpolate1(s->x,s->y,s->n,&j,s3x[i]); }	else if(!strcmp(fn,"m*s")||!strcmp(fn,"s*m"))	{		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3y[i]=interpolate1(s->x,s->y,s->n,&j,s3x[i])*ModelValue(s3x[i],m); }	else if(!strcmp(fn,"m/s")) {		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++) {			y=interpolate1(s->x,s->y,s->n,&j,s3x[i]);			s3y[i]=(y<0||y>0)?ModelValue(s3x[i],m)/y:0; }}	else if(!strcmp(fn,"s-m")) {		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++)			s3y[i]=interpolate1(s->x,s->y,s->n,&j,s3x[i])-ModelValue(s3x[i],m); }	else if(!strcmp(fn,"s/m")) {		s=(sptr) v;		if(!s) {SpectFree(s3);return 6;}		if(s->cmplx) {SpectFree(s3);return 8;}		j=-2;		for(i=0;i<n;i++) {			y=ModelValue(s3x[i],m);			s3y[i]=(y<0||y>0)?interpolate1(s->x,s->y,s->n,&j,s3x[i])/y:0; }}	else if(!strcmp(fn,"m+b")||!strcmp(fn,"b+m")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)+(b2->addr)(s3x[i],b2->param,b2->spec,NULL); }	else if(!strcmp(fn,"m-b")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)-(b2->addr)(s3x[i],b2->param,b2->spec,NULL); }	else if(!strcmp(fn,"m*b")||!strcmp(fn,"b*m")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)*(b2->addr)(s3x[i],b2->param,b2->spec,NULL); }	else if(!strcmp(fn,"m/b")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++) {			y=(b2->addr)(s3x[i],b2->param,b2->spec,NULL);			s3y[i]=(y<0||y>0)?ModelValue(s3x[i],m)/y:0; }}	else if(!strcmp(fn,"b-m")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=(b2->addr)(s3x[i],b2->param,b2->spec,NULL)-ModelValue(s3x[i],m); }	else if(!strcmp(fn,"b/m")) {		b2=(basisptr) v;		if(!b2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++) {			y=ModelValue(s3x[i],m);			s3y[i]=(y<0||y>0)?(b2->addr)(s3x[i],b2->param,b2->spec,NULL)/y:0; }}	else if(!strcmp(fn,"m+m")) {		m2=(modelptr) v;		if(!m2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)+ModelValue(s3x[i],m2); }	else if(!strcmp(fn,"m-m")) {		m2=(modelptr) v;		if(!m2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)-ModelValue(s3x[i],m2); }	else if(!strcmp(fn,"m*m")) {		m2=(modelptr) v;		if(!m2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)*ModelValue(s3x[i],m2); }	else if(!strcmp(fn,"m/m")) {		m2=(modelptr) v;		if(!m2) {SpectFree(s3);return 6;}		for(i=0;i<n;i++) {			y=ModelValue(s3x[i],m2);			s3y[i]=(y<0||y>0)?ModelValue(s3x[i],m)/y:0; }}	else if(!strcmp(fn,"m+k")||!strcmp(fn,"k+m"))		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)+k;	else if(!strcmp(fn,"m*k")||!strcmp(fn,"k*m"))		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)*k;	else if(!strcmp(fn,"k-m"))		for(i=0;i<n;i++)			s3y[i]=k-ModelValue(s3x[i],m);	else if(!strcmp(fn,"k/m"))		for(i=0;i<n;i++) {			y=ModelValue(s3x[i],m);			s3y[i]=(y<0||y>0)?k/y:0; }	else if(!strcmp(fn,"m-k"))		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)-k;	else if(!strcmp(fn,"m/k")) {		if(!(k<0||k>0)) {SpectFree(s3);return 9;}		for(i=0;i<n;i++)			s3y[i]=ModelValue(s3x[i],m)/k; }	else if(!strcmp(fn,"m^k"))		if(k>0) for(i=0;i<n;i++)				s3y[i]=pow(ModelValue(s3x[i],m),k);		else if(k==floor(k)) for(i=0;i<n;i++) {				y=ModelValue(s3x[i],m);				s3y[i]=(y<0||y>0)?pow(y,k):0; }		else for(i=0;i<n;i++) {				y=ModelValue(s3x[i],m);				s3y[i]=y>0?pow(y,k):0; }	else {		SpectFree(s3);		return 7; }	*ansptr=s3;	return 0; }void endbasis() {	struct scell *trace,*trace2;	void *k,*x;	for(trace=SetNext(NULL,&k,&x,basisfns);trace;trace=trace2) {		trace2=SetNext(trace,&k,&x,basisfns);		BasisFree((basisptr) x); }	SetFree(basisfns,0,0);	basisfns=NULL;	return; }float rmserror(modelptr m) {	float diff,ch2,siginv,*sx,*sy,*uy;	int lo,hi,er;	int i;	sptr s;	if(!m) return -6;	if(!m->spec) return -16;	if(m->spec->cmplx) return -8;	if((er=CheckBasis(NULL,m))) return -er;	s=m->spec;	sx=s->x;	sy=s->y;	if(sx[0]>=m->xmin) lo=0;	else {		lo=locateV(sx,m->xmin,s->n);		if(lo<0) lo=0;		else if(sx[lo]<m->xmin) lo++; }	if(sx[s->n-1]<=m->xmax) hi=s->n-1;	else hi=locateV(sx,m->xmax,s->n);	ch2=0;	for(i=lo;i<=hi;i++)	{		diff=(sy[i]-ModelValue(sx[i],m));		ch2+=diff*diff; }	return sqrt(ch2/(hi-lo+1)); }float chisq(modelptr m,float ch2max) {	float diff,ch2,siginv,*sx,*sy,*uy;	int lo,hi;	int i;	sptr s;	if(ch2max<0) ch2max=FLT_MAX;	s=m->spec;	if(m->sigma>0) siginv=1.0/m->sigma;	else siginv=1;	sx=s->x;	sy=s->y;	if(m->uncert) uy=m->uncert->y;	if(sx[0]>=m->xmin) lo=0;	else {		lo=locateV(sx,m->xmin,s->n);		if(lo<0) lo=0;		else if(sx[lo]<m->xmin) lo++; }	if(sx[s->n-1]<=m->xmax) hi=s->n-1;	else hi=locateV(sx,m->xmax,s->n);	ch2=0;	if(!m->uncert)		for(i=lo;i<=hi&&ch2<ch2max;i++)	{			diff=(sy[i]-ModelValue(sx[i],m))*siginv;			ch2+=diff*diff; }	else		for(i=lo;i<=hi&&ch2<ch2max;i++)	{			diff=(sy[i]-ModelValue(sx[i],m))*siginv/uy[i];			ch2+=diff*diff; }	return ch2<ch2max?ch2:ch2max; }float ChiSqD(modelptr m,float ch2max,float *alpha,float *beta,int np) {	float diff,ch2,siginv,*sx,*sy,*uy;	float *deriv;	int lo,hi;	int i,k,k2;	sptr s;	if(ch2max<0) ch2max=FLT_MAX;	s=m->spec;	if(m->sigma>0) siginv=1.0/m->sigma;	else siginv=1;	sx=s->x;	sy=s->y;	if(m->uncert) uy=m->uncert->y;	deriv=allocV(np);	if(!deriv) return -1;	if(sx[0]>=m->xmin) lo=0;	else {		lo=locateV(sx,m->xmin,s->n);		if(lo<0) lo=0;		else if(sx[lo]<m->xmin) lo++; }	if(sx[s->n-1]<=m->xmax) hi=s->n-1;	else hi=locateV(sx,m->xmax,s->n);	setstdV(beta,np,0);	setstdM(alpha,np,np,0);		ch2=0;	if(!m->uncert)		for(i=lo;i<=hi&&ch2<ch2max;i++)	{			diff=(sy[i]-ModelValueD(sx[i],m,deriv))*siginv;			ch2+=diff*diff;			multKV(siginv,deriv,deriv,np);			for(k=0;k<np;k++)	{				beta[k]+=diff*deriv[k];				for(k2=0;k2<np;k2++) alpha[np*k+k2]+=deriv[k]*deriv[k2]; }}	else if(m->uncert)		for(i=lo;i<=hi&&ch2<ch2max;i++)	{			diff=(sy[i]-ModelValueD(sx[i],m,deriv))*siginv/uy[i];			ch2+=diff*diff;			for(k=0;k<np;k++) deriv[k]*=siginv/uy[i];			for(k=0;k<np;k++)	{				beta[k]+=diff*deriv[k];				for(k2=0;k2<np;k2++) alpha[np*k+k2]+=deriv[k]*deriv[k2]; }}	freeV(deriv);	for(k=0;k<np;k++) {		if(!(beta[k]<FLT_MAX&&beta[k]>-FLT_MAX)) beta[k]=0;		for(k2=0;k2<np;k2++)			if(!(alpha[np*k+k2]<FLT_MAX&&alpha[np*k+k2]>-FLT_MAX)) alpha[np*k+k2]=0; }	return ch2<ch2max?ch2:ch2max; }int prefit(modelptr m,float ***pptr,float **ploptr,float **phiptr) {	int nfre,ntot,i,jfre,er;	float **p;	void *k,*item;	struct scell *trace;	basisptr b;	if(!m) return -6;	if(!m->spec) return -16;	if(m->spec->cmplx) return -8;	if((er=CheckBasis(NULL,m))) return -er;	if((er=CheckUncert(m))) return -er;	p=*pptr=NULL;	*ploptr=NULL;	*phiptr=NULL;	nfre=CountFreParam(m,NULL);	if(!nfre) return 0;	ntot=m->np;	p=(float **) calloc(nfre,sizeof(float *));							/* pointers to parameters */	*ploptr=allocV(nfre);	*phiptr=allocV(nfre);	if(!p||!*ploptr||!*phiptr) {		if(p) free(p);		if(*ploptr) freeV(*ploptr);		if(*phiptr) freeV(*phiptr);		return -1; }	jfre=0;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{		b=(basisptr)item;		for(i=0;i<b->n;i++) {			b->pold[i]=b->param[i];			if(!b->freeze[i]) {				if(b->param[i]<b->paramlo[i]) b->param[i]=b->paramlo[i];				else if(b->param[i]>b->paramhi[i]) b->param[i]=b->paramhi[i];				p[jfre]=&b->param[i];				(*ploptr)[jfre]=b->paramlo[i];				(*phiptr)[jfre]=b->paramhi[i];				jfre++; }}}	*pptr=p;	return nfre; }int ModelCovar(modelptr m) {	int rmssig,er,jfre,nfre,itot,jtot,ntot,*frz,*luindx;	float det,*alpha,*alphalu,*covar,*ident,*beta;	if(!m) return 6;	if(!m->spec) return 16;	if(m->spec->cmplx) return 8;	if((er=CheckBasis(NULL,m))) return er;	if((er=CheckUncert(m))) return er;	nfre=CountFreParam(m,&frz);	if(nfre<0) return -nfre;	else if(!nfre) return 0;	er=0;	rmssig=0;	alpha=allocM(nfre,nfre);	alphalu=allocM(nfre,nfre);	covar=allocM(nfre,nfre);	ident=allocM(nfre,nfre);	beta=allocV(nfre);	luindx=NULL;	if(!alpha||!alphalu||!covar||!ident||!beta)	{er=1;goto endfunction;}	if(m->sigma<=0&&!m->uncert) {		rmssig=1;		m->sigma=rmserror(m); }	ChiSqD(m,-1,alpha,beta,nfre);	copyM(alpha,alphalu,nfre,nfre);	det=LUdecomp(alphalu,nfre,&luindx);	if(det==0) {er=9;goto endfunction;}	setstdM(covar,nfre,nfre,1);	LUsolveM(alphalu,luindx,covar,nfre,nfre);	setstdM(ident,nfre,nfre,1);	LUimprM(alpha,alphalu,luindx,covar,ident,nfre,nfre);	ntot=m->np;	if(!m->covar) m->covar=allocM(ntot,ntot);	if(!m->covar)	{er=1;goto endfunction;}	setstdM(m->covar,ntot,ntot,0);	jfre=0;	for(itot=0;itot<ntot;itot++)		for(jtot=0;jtot<ntot;jtot++)			if(!frz[itot]&&!frz[jtot]) m->covar[ntot*itot+jtot]=covar[jfre++]; endfunction:	if(rmssig) m->sigma=0;	if(frz) free(frz);	if(alpha) freeM(alpha);	if(alphalu) freeM(alphalu);	if(covar) freeM(covar);	if(ident) freeM(ident);	if(beta) freeV(beta);	if(luindx) free(luindx);	if(er&&m->covar) {		freeM(m->covar);		m->covar=NULL; }	return er; }void unfit(modelptr m) {	int i;	float f1;	void *k,*item;	struct scell *trace;	basisptr b;	for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis))	{		b=(basisptr)item;		for(i=0;i<b->n;i++) {			f1=b->param[i];			b->param[i]=b->pold[i];			b->pold[i]=f1; }}	if(m->covar) {		freeM(m->covar);		m->covar=NULL; }	return; }int RandomFit(modelptr m) {	float ch2,f,f2;	float **p,*plo,*phi,*step;	int i,j,np,er;	np=prefit(m,&p,&plo,&phi);	if(np<0) return -np;	else if(!np) return 0;	step=allocV(np);	if(!step) {free(p);freeV(plo);freeV(phi);return 1;}	for(j=0;j<np;j++)	step[j]=fabs(*p[j]/50)+0.001;	ch2=chisq(m,-1);	for(i=0;i<np*30&&!inkey();i++) {		j=intrand(np);		f=*p[j];		*p[j]+=binomrand(3,0,step[j]);		if(*p[j]<plo[j]) *p[j]=plo[j];		else if(*p[j]>phi[j]) *p[j]=phi[j];		UpdateModel(m);		if((f2=chisq(m,ch2))<ch2)	{			i=0;			step[j]*=1.2;			ch2=f2; }		else {			*p[j]=f;			UpdateModel(m);			step[j]*=0.9; }}	er=ModelCovar(m);	freeV(step);	free(p);	freeV(plo);	freeV(phi);	return er; }int LinearFit(modelptr m) {	float *A,*Atrans,*alpha,*alphalu,*beta,*ans,*b;	float **p,det,*plo,*phi,ch2,siginv,*uy;	int i,j,lo,hi,np,n,er;	int *luindx;	sptr s;	er=0;	np=prefit(m,&p,&plo,&phi);	if(np<0) return -np;	else if(!np) return 0;	s=m->spec;	if(m->sigma>0) siginv=1.0/m->sigma;	else siginv=1;	if(m->uncert) uy=m->uncert->y;	if(s->x[0]>=m->xmin) lo=0;	else {		lo=locateV(s->x,m->xmin,s->n);		if(lo<0) lo=0;		else if(s->x[lo]<m->xmin) lo++; }	if(s->x[s->n-1]<=m->xmax) hi=s->n-1;	else hi=locateV(s->x,m->xmax,s->n);	n=hi-lo+1;	A=allocM(n,np);	Atrans=allocM(np,n);	alpha=allocM(np,np);	alphalu=allocM(np,np);	beta=allocV(np);	ans=allocV(np);	b=allocV(n);	luindx=NULL;	if(!A||!Atrans||!alpha||!beta||!alphalu||!ans||!b) {er=1;goto endfunction; }	ch2=chisq(m,-1);	if(!m->uncert)		for(i=lo;i<=hi;i++) {			b[i-lo]=(s->y[i]-ModelValueD(s->x[i],m,ans))*siginv;			for(j=0;j<np;j++) A[np*(i-lo)+j]=ans[j]*siginv; }	else		for(i=lo;i<=hi;i++) {			b[i-lo]=(s->y[i]-ModelValueD(s->x[i],m,ans))*siginv/uy[i];			for(j=0;j<np;j++) A[np*(i-lo)+j]=ans[j]*siginv/uy[i]; }	transM(A,Atrans,n,np);	dotMM(Atrans,A,alpha,np,n,np);	dotMV(Atrans,b,beta,np,n);	copyM(alpha,alphalu,np,np);	det=LUdecomp(alphalu,np,&luindx);	if(det)	{		copyV(beta,ans,np);		LUsolveV(alphalu,luindx,ans,np);		LUimprV(alpha,alphalu,luindx,ans,beta,np);		for(i=0;i<np;i++) {			beta[i]=*p[i];			ans[i]+=*p[i];			if(ans[i]<plo[i]) *p[i]=plo[i];			else if(ans[i]>phi[i]) *p[i]=phi[i];			else *p[i]=ans[i]; }		UpdateModel(m);		if(!(chisq(m,ch2)<ch2))			for(i=0;i<np;i++) *p[i]=beta[i];		er=ModelCovar(m); }	else er=9; endfunction:	if(A) freeM(A);	if(Atrans) freeM(Atrans);	if(alpha) freeM(alpha);	if(alphalu) freeM(alphalu);	if(beta) freeV(beta);	if(ans) freeV(ans);	if(b) freeV(b);	if(luindx) free(luindx);	free(p);	freeV(plo);	freeV(phi);	return er; }int LMFit(modelptr m) {	float *alpha,*beta,*alphab,*betab,*pwas,ch2,ch2b,lambda;	float **p,det,*plo,*phi;	int np,it,j,*luindx,er;	er=0;	np=prefit(m,&p,&plo,&phi);	if(np<0) return -np;	else if(!np) return 0;	alpha=allocM(np,np);	beta=allocV(np);	alphab=allocM(np,np);	betab=allocV(np);	pwas=allocV(np);	luindx=NULL;	if(!alpha||!alphab||!beta||!betab||!pwas) {er=1;goto endfunction;}	ch2=ChiSqD(m,-1,alpha,beta,np);	copyM(alpha,alphab,np,np);	copyV(beta,betab,np);	lambda=0.001;	for(it=0;it<np*10&&!inkey();it++) {		for(j=0;j<np;j++)	alphab[np*j+j]*=(1.0+lambda);		det=LUdecomp(alphab,np,&luindx);		if(det==0) goto endfunction;		LUsolveV(alphab,luindx,betab,np);		free(luindx);		luindx=NULL;		for(j=0;j<np;j++) {			pwas[j]=*p[j];			if(betab[j]<FLT_MAX&&betab[j]>-FLT_MAX) {				*p[j]+=betab[j];				if(*p[j]<plo[j]) *p[j]=plo[j];				else if(*p[j]>phi[j])	*p[j]=phi[j]; }}		UpdateModel(m);		if((ch2b=ChiSqD(m,ch2,alphab,betab,np))>=0&&ch2b<ch2) {			lambda*=0.1;			it=0;			ch2=ch2b;			copyM(alphab,alpha,np,np);			copyV(betab,beta,np); }		else {			for(j=0;j<np;j++)	*p[j]=pwas[j];			UpdateModel(m);			lambda*=10;			copyM(alpha,alphab,np,np);			copyV(beta,betab,np); }}	er=ModelCovar(m); endfunction:	free(p);	freeV(plo);	freeV(phi);	if(alpha) freeM(alpha);	if(alphab) freeM(alphab);	if(beta) freeV(beta);	if(betab) freeV(betab);	if(pwas) freeV(pwas);	if(luindx) free(luindx);	return er; }int RandMultiFit(set s) {	float ch2,f,f2;	float **p,**pm,*plo,*phi,*plom,*phim,*step;	int ntotal,np,npm,it,j,i;	struct scell *trace;	void *key,*item;	modelptr m;	if(!s) return 6;	ntotal=0;	for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s)) {		m=(modelptr)item;		if(!m) return 6;		ntotal+=m->np; }	if(!ntotal) return 0;	p=(float **) calloc(ntotal,sizeof(float *));	plo=allocV(ntotal);	phi=allocV(ntotal);	step=allocV(ntotal);	if(!p||!plo||!phi||!step) {		if(p) free(p);		if(plo) freeV(plo);		if(phi) freeV(phi);		if(step) freeV(step);		return 1; }	np=0;	for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s))	{		m=(modelptr)item;		npm=prefit(m,&pm,&plom,&phim);		if(npm<0) {free(p);freeV(step);freeV(plo);freeV(phi);return -npm;}		if(npm>0)	{			for(i=0;i<npm;i++)	{				p[np+i]=pm[i];				plo[np+i]=plom[i];				phi[np+i]=phim[i];				step[np+i]=fabs(*pm[i]/100)+0.001; }			free(pm);			freeV(plom);			freeV(phim);			np+=npm; }		if(m->covar) {			freeM(m->covar);			m->covar=NULL; }}	ch2=0;	for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s))		ch2+=chisq((modelptr)item,-1);	if(np)		for(it=0;it<np*20&&!inkey();it++)	{			j=intrand(np);			f=*p[j];			*p[j]+=binomrand(3,0,step[j]);			if(*p[j]<plo[j]) *p[j]=plo[j];			else if(*p[j]>phi[j]) *p[j]=phi[j];			for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s))				UpdateModel((modelptr)item);			f2=0;			for(trace=SetNext(NULL,&key,&item,s);trace&&ch2>f2;trace=SetNext(trace,&key,&item,s))				f2+=chisq((modelptr)item,ch2-f2);			if(f2<ch2) {				it=0;				step[j]*=1.2;				ch2=f2; }			else {				*p[j]=f;				for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s))					UpdateModel((modelptr)item);				step[j]*=0.9; }}	free(p);	freeV(step);	freeV(plo);	freeV(phi);	return 0; }
