/* * Euler - a numerical laboratory * * file : stack.c -- numerical stack management * */ #include #include #include #include #include "stack.h" #include "output.h" #include "command.h" #include "builtin.h" #include "interval.h" #include "funcs.h" #include "udf.h" #include "express.h" #include "mainloop.h" extern int nosubmref; /* * stack variables */ char *ramstart,*ramend,*udfend,*startlocal,*endlocal,*newram, *varstart,*udframend,*startglobal,*endglobal; /* functions that manipulate the stack */ #define superalign(n) ((((n)-1)/ALIGNMENT+1)*ALIGNMENT) int xor (char *n) /***** xor compute a hashcode for the name n. *****/ { int r=0; while (*n) r^=*n++; return r; } static void *make_header (stacktyp type, unsigned long size, char *name) /***** make_header pushes a new element on the stack. return the position after the header. ******/ { header *hd; char *erg; size=(((size-1)/ALIGNMENT)+1)*ALIGNMENT; hd=(header *)(newram); if (!freeram(size)) { output("Stack overflow!\n"); error=2; hd->size=sizeof(hd); hd->type=(stacktyp)1000; hd->flags=0; strcpy(hd->name,""); hd->xor=0; return 0; } hd->size=size; hd->type=type; hd->flags=0; if (*name) { strcpy(hd->name,name); hd->xor=xor(name); } else { *(hd->name)=0; hd->xor=0; } erg=newram+sizeof(header); newram+=size; return erg; } header *new_matrix (int rows, int columns, char *name) /***** new_matrix pops a new matrix on the stack. *****/ { unsigned long size; dims *d; header *hd=(header *)newram; size=matrixsize(rows,columns); d=(dims *)make_header(s_matrix,size,name); if (d) { d->c=columns; d->r=rows; } return hd; } header *new_cmatrix (int rows, int columns, char *name) /***** new_matrix pops a new matrix on the stack. *****/ { unsigned long size; dims *d; header *hd=(header *)newram; size=matrixsize(rows,2*columns); d=(dims *)make_header(s_cmatrix,size,name); if (d) { d->c=columns; d->r=rows; } return hd; } header *new_imatrix (int rows, int columns, char *name) /***** new_matrix pops a new interval matrix on the stack. *****/ { unsigned long size; dims *d; header *hd=(header *)newram; size=matrixsize(rows,2*columns); d=(dims *)make_header(s_imatrix,size,name); if (d) { d->c=columns; d->r=rows; } return hd; } header *new_command (int no) /***** new_command pops a command on stack. *****/ { unsigned long size; int *d; header *hd=(header *)newram; size=sizeof(header)+sizeof(int); d=(int *)make_header(s_command,size,""); if (d) *d=no; return hd; } header *new_real (double x, char *name) /***** new real pops a double on stack. *****/ { unsigned long size; double *d; header *hd=(header *)newram; size=sizeof(header)+sizeof(double); d=(double *)make_header(s_real,size,name); if (d) *d=x; return hd; } header *new_string (char *s, unsigned long length, char *name) /***** new real pops a string on stack. *****/ { unsigned long size; char *d; header *hd=(header *)newram; size=sizeof(header)+((int)(length+1)/ALIGNMENT+1)*ALIGNMENT; d=(char *)make_header(s_string,size,name); if (d) strncpy(d,s,length); d[length]=0; return hd; } header *new_udf (char *name) /***** new real pops a udf on stack. *****/ { unsigned long size; unsigned long *d; header *hd=(header *)newram; size=sizeof(header)+sizeof(inttyp)+ALIGNMENT; d=(unsigned long *)make_header(s_udf,size,name); if (d) { *d=sizeof(header)+sizeof(unsigned long); *((char *)(d+1))=0; } return hd; } header *new_complex (double x, double y, char *name) /***** new real pushes a complex on stack. *****/ { unsigned long size; double *d; header *hd=(header *)newram; size=sizeof(header)+2*sizeof(double); d=(double *)make_header(s_complex,size,name); if (d) { *d=x; *(d+1)=y; } return hd; } header *new_interval (double x, double y, char *name) { unsigned long size; double *d; header *hd=(header *)newram; size=sizeof(header)+2*sizeof(double); d=(double *)make_header(s_interval,size,name); if (d) { *d=x; *(d+1)=y; } return hd; } header *new_reference (header *ref, char *name) { unsigned long size; header **d; header *hd=(header *)newram; size=sizeof(header)+sizeof(header *); d=(header **)make_header(s_reference,size,name); if (d) *d=ref; return hd; } header *new_subm (header *var, long l, char *name) /* makes a new submatrix, which is a single element */ { unsigned long size; header **d,*hd=(header *)newram; dims *dim; int *n,r,c; size=sizeof(header)+sizeof(header *)+sizeof(dims)+2*sizeof(int); d=(header **)make_header(s_submatrix,size,name); if (d) *d=var; else return hd; dim=(dims *)(d+1); dim->r=1; dim->c=1; n=(int *)(dim+1); c=dimsof(var)->c; if (c==0 || dimsof(var)->r==0) { output("Matrix is empty!\n"); error=1031; return hd; } else r=(int)(l/c); *n++=r; *n=(int)(l-(long)r*c-1); return hd; } header *new_csubm (header *var, long l, char *name) /* makes a new submatrix, which is a single element */ { unsigned long size; header **d,*hd=(header *)newram; dims *dim; int *n,r,c; size=sizeof(header)+sizeof(header *)+ sizeof(dims)+2*sizeof(int); d=(header **)make_header(s_csubmatrix,size,name); if (d) *d=var; else return hd; dim=(dims *)(d+1); dim->r=1; dim->c=1; n=(int *)(dim+1); c=dimsof(var)->c; if (c==0 || dimsof(var)->r==0) { output("Matrix is empty!\n"); error=1031; return hd; } else r=(int)(l/c); *n++=r; *n=(int)(l-r*c-1); return hd; } header *new_isubm (header *var, long l, char *name) /* makes a new submatrix, which is a single element */ { unsigned long size; header **d,*hd=(header *)newram; dims *dim; int *n,r,c; size=sizeof(header)+sizeof(header *)+ sizeof(dims)+2*sizeof(int); d=(header **)make_header(s_isubmatrix,size,name); if (d) *d=var; else return hd; dim=(dims *)(d+1); dim->r=1; dim->c=1; n=(int *)(dim+1); c=dimsof(var)->c; if (c==0 || dimsof(var)->r==0) { output("Matrix is empty!\n"); error=1031; return hd; } else r=(int)(l/c); *n++=r; *n=(int)(l-r*c-1); return hd; } static header *hnew_submatrix (header *var, header *rows, header *cols, char *name, int type) { unsigned long size; header **d; double *mr=0,*mc=0,x,*mvar; dims *dim; int c,r,*n,i,c0,r0,cvar,rvar,allc=0,allr=0; header *hd=(header *)newram; getmatrix(var,&rvar,&cvar,&mvar); if (rows->type==s_matrix) { if (dimsof(rows)->r==1) r=dimsof(rows)->c; else if (dimsof(rows)->c==1) r=dimsof(rows)->r; else { output("Illegal index!\n"); error=41; return 0; } mr=matrixof(rows); } else if (rows->type==s_real) { r=1; mr=realof(rows); } else if (rows->type==s_command && *commandof(rows)==c_allv) { allr=1; r=rvar; } else { output("Illegal index!\n"); error=41; return 0; } if (cols->type==s_matrix) { if (dimsof(cols)->r==1) c=dimsof(cols)->c; else if (dimsof(cols)->c==1) c=dimsof(cols)->r; else { output("Illegal index!\n"); error=41; return 0; } mc=matrixof(cols); } else if (cols->type==s_real) { c=1; mc=realof(cols); } else if (cols->type==s_command && *commandof(cols)==c_allv) { allc=1; c=cvar; } else { output("Illegal index!\n"); error=41; return 0; } size=sizeof(header)+sizeof(header *)+ sizeof(dims)+((long)r+c)*sizeof(int); d=(header **)make_header((stacktyp)type,size,name); if (d) *d=var; else return hd; dim = (dims *)(d+1); n=(int *)(dim+1); r0=0; if (allr) { for (i=0; i=rvar)) ) { *n++=(int)x; r0++; } } c0=0; if (allc) { for (i=0; i=cvar))) { *n++=(int)x; c0++; } } dim->r=r0; dim->c=c0; size=(char *)n-(char *)hd; size=((size-1)/ALIGNMENT+1)*ALIGNMENT; newram=(char *)hd+size; hd->size=size; return hd; } static header *built_smatrix (header *var, header *rows, header *cols) /***** built_smatrix built a submatrix from the matrix hd on the stack. *****/ { double *mr=0,*mc=0,*mvar,*m; int n,c,r,c0,r0,i,j,cvar,rvar,allc=0,allr=0,*pr,*pc,*nc,*nr; header *hd; char *ram; long size; getmatrix(var,&rvar,&cvar,&mvar); if (rows->type==s_matrix) { if (dimsof(rows)->r==1) r=dimsof(rows)->c; else if (dimsof(rows)->c==1) r=dimsof(rows)->r; else { output("Illegal index!\n"); error=41; return 0; } mr=matrixof(rows); } else if (rows->type==s_real) { r=1; mr=realof(rows); } else if (rows->type==s_command && *commandof(rows)==c_allv) { allr=1; r=rvar; } else { output("Illegal index!\n"); error=41; return 0; } if (cols->type==s_matrix) { if (dimsof(cols)->r==1) c=dimsof(cols)->c; else if (dimsof(cols)->c==1) c=dimsof(cols)->r; else { output("Illegal index!\n"); error=41; return 0; } mc=matrixof(cols); } else if (cols->type==s_real) { c=1; mc=realof(cols); } else if (cols->type==s_command && *commandof(cols)==c_allv) { allc=1; c=cvar; } else { output("Illegal index!\n"); error=41; return 0; } ram=newram; size=superalign(((long)c+(long)r)*sizeof(int)); if (!freeram(size)) { output("Out of memory!\n"); error=710; return 0; } nr=pr=(int *)ram; nc=pc=pr+r; newram=ram+size; c0=0; r0=0; if (allc) { for (i=0; i=0 && n=0 && ntype==s_matrix) { if (dimsof(rows)->r==1) r=dimsof(rows)->c; else if (dimsof(rows)->c==1) r=dimsof(rows)->r; else { output("Illegal index!\n"); error=41; return 0; } mr=matrixof(rows); } else if (rows->type==s_real) { r=1; mr=realof(rows); } else if (rows->type==s_command && *commandof(rows)==c_allv) { allr=1; r=rvar; } else { output("Illegal index!\n"); error=41; return 0; } if (cols->type==s_matrix) { if (dimsof(cols)->r==1) c=dimsof(cols)->c; else if (dimsof(cols)->c==1) c=dimsof(cols)->r; else { output("Illegal index!\n"); error=41; return 0; } mc=matrixof(cols); } else if (cols->type==s_real) { c=1; mc=realof(cols); } else if (cols->type==s_command && *commandof(cols)==c_allv) { allc=1; c=cvar; } else { output("Illegal index!\n"); error=41; return 0; } ram=newram; size=superalign(((long)c+(long)r)*sizeof(int)); if (!freeram(size)) { output("Out of memory!\n"); error=710; return 0; } nr=pr=(int *)ram; nc=pc=pr+r; newram=ram+size; c0=0; r0=0; if (allc) { for (i=0; i=0 && n=0 && ntype==s_matrix) { if (dimsof(rows)->r==1) r=dimsof(rows)->c; else if (dimsof(rows)->c==1) r=dimsof(rows)->r; else { output("Illegal index!\n"); error=41; return 0; } mr=matrixof(rows); } else if (rows->type==s_real) { r=1; mr=realof(rows); } else if (rows->type==s_command && *commandof(rows)==c_allv) { allr=1; r=rvar; } else { output("Illegal index!\n"); error=41; return 0; } if (cols->type==s_matrix) { if (dimsof(cols)->r==1) c=dimsof(cols)->c; else if (dimsof(cols)->c==1) c=dimsof(cols)->r; else { output("Illegal index!\n"); error=41; return 0; } mc=matrixof(cols); } else if (cols->type==s_real) { c=1; mc=realof(cols); } else if (cols->type==s_command && *commandof(cols)==c_allv) { allc=1; c=cvar; } else { output("Illegal index!\n"); error=41; return 0; } ram=newram; size=superalign(((long)c+(long)r)*sizeof(int)); if (!freeram(size)) { output("Out of memory!\n"); error=710; return 0; } nr=pr=(int *)ram; nc=pc=pr+r; newram=ram+size; c0=0; r0=0; if (allc) { for (i=0; i=0 && n=0 && ntype==s_real) { size=sizeof(header)+2*sizeof(double); nextarg=nextof(old); if (!freeram((size-old->size))) { output("Memory overflow!\n"); error=180; return; } if (newram>(char *)nextarg) memmove((char *)old+size,(char *)nextarg, newram-(char *)nextarg); newram+=size-old->size; *(old->name)=0; old->size=size; old->type=s_complex; *realof(old)=*realof(hd); *imagof(old)=0.0; } else if (hd->type==s_matrix) { getmatrix(hd,&r,&c,&m); size=cmatrixsize(r,c); nextarg=nextof(old); if (!freeram(size-old->size)) { output("Memory overflow!\n"); error=180; return; } if (newram>(char *)nextarg) memmove((char *)old+size,(char *)nextarg, newram-(char *)nextarg); newram+=size-old->size; *(old->name)=0; old->size=size; old->type=s_cmatrix; dimsof(old)->r=r; dimsof(old)->c=c; m1=matrixof(old); for (i=r-1; i>=0; i--) for (j=c-1; j>=0; j--) { *cmat(m1,c,i,j)=*mat(m,c,i,j); *(cmat(m1,c,i,j)+1)=0.0; } } else wrong_arg(); } void getmatrix (header *hd, int *r, int *c, double **m) /***** getmatrix get rows and columns from a matrix. *****/ { dims *d; if (hd->type==s_real || hd->type==s_complex || hd->type==s_interval) { *r=*c=1; *m=realof(hd); } else if (hd->type==s_matrix || hd->type==s_cmatrix || hd->type==s_imatrix) { d=dimsof(hd); *m=matrixof(hd); *r=d->r; *c=d->c; } else error=1; } #ifdef DLL int exec_dll (char *name, int n, header *hd); #endif void get_element (int nargs, header *var, header *hd) /***** get_elements get the element of the matrix. *****/ { header *st=hd,*result,*hd1; var=getvalue(var); if (error) return; if (var->type==s_string) /* interpret the string as a function */ { hd1=searchudf(stringof(var)); if (hd1) interpret_udf(hd1,hd,nargs,0); else if (exec_builtin(stringof(var),nargs,hd)); #ifdef DLL else if (exec_dll(stringof(var),nargs,hd)); #endif else { output1("%s is no function name!\n",stringof(var)); error=2020; return; } return; } hd=getvalue(hd); if (error) return; if (nargs<1 || nargs>2) { error=30; output("Illegal matrix reference!\n"); return; } if (nargs==2) { hd1=getvalue(next_param(st)); if (error) return; } else { if (dimsof(var)->r==1) { hd1=hd; hd=new_real(1.0,""); } else hd1=new_command(c_allv); if (error) return; } if (var->type==s_matrix || var->type==s_real) { result=new_submatrix(var,hd,hd1,""); } else if (var->type==s_cmatrix || var->type==s_complex) { result=new_csubmatrix(var,hd,hd1,""); } else if (var->type==s_imatrix || var->type==s_interval) { result=new_isubmatrix(var,hd,hd1,""); } else { error=31; output1("Not a matrix %s!\n",var->name); return; } if (error) return; moveresult(st,result); } void get_element1 (char *name, header *hd) /* get an element of a matrix, referenced by *realof(hd), where the matrix is dentified with a vector of same length */ { header *st=hd,*result,*var; long n,l; int r,c; double *m; hd=getvalue(hd); var=searchvar(name); if (!var) { output1("%s not a variable!\n",name); error=1012; return; } var=getvalue(var); if (error) return; if (hd->type!=s_real) { output("Index must be a number!\n"); error=1013; return; } if (error) return; if (var->type==s_real) { result=new_reference(var,""); } else if (var->type==s_complex) { result=new_reference(var,""); } else if (var->type==s_matrix) { getmatrix(var,&r,&c,&m); l=(long)(*realof(hd)); n=(long)r*c; if (l>n) l=n; if (l<1) l=1; if (nosubmref) result=new_real(*(m+l-1),""); else result=new_subm(var,l,""); } else if (var->type==s_cmatrix) { getmatrix(var,&r,&c,&m); l=(long)(*realof(hd)); n=(long)r*c; if (n==0) { output("Matrix is empty!\n"); error=1030; return; } if (l>n) l=n; if (l<1) l=1; if (nosubmref) { m+=(long)2*(l-1); result=new_complex(*m,*(m+1),""); } else result=new_csubm(var,l,""); } else if (var->type==s_imatrix) { getmatrix(var,&r,&c,&m); l=(long)(*realof(hd)); n=(long)r*c; if (n==0) { output("Matrix is empty!\n"); error=1030; return; } if (l>n) l=n; if (l<1) l=1; if (nosubmref) { m+=(long)2*(l-1); result=new_interval(*m,*(m+1),""); } else result=new_isubm(var,l,""); } else { output1("%s not a variable of proper type for {}!\n", name); error=1011; return; } moveresult(st,result); } header *searchvar (char *name) /***** searchvar search a local variable, named "name". return 0, if not found. *****/ { int r; header *hd=(header *)startlocal; r=xor(name); while ((char *)hdxor && !strcmp(hd->name,name)) return hd; hd=nextof(hd); } if (startglobal!=startlocal && searchglobal) { hd=(header *)startglobal; while ((char *)hdxor && !strcmp(hd->name,name)) return hd; hd=nextof(hd); } } return 0; } header *getvalue (header *hd) /***** getvalue get an actual value of a reference. *****/ { header *old=hd,*mhd,*result; dims *d; double *m,*mr,*m1,*m2,*m3; int r,c,*rind,*cind,*cind1,i,j; while (hd && hd->type==s_reference) hd=referenceof(hd); if (!hd) { mhd=(header *)newram; if (exec_builtin(old->name,0,mhd)) { return mhd; } hd=searchudf(old->name); if (hd) { interpret_udf(hd,mhd,0,0); return mhd; } output1("Variable %s not defined!\n",old->name); error=10; return new_string("Fehler",6,""); } if (hd->type==s_submatrix) { mhd=submrefof(hd); d=submdimsof(hd); rind=rowsof(hd); cind=colsof(hd); getmatrix(mhd,&r,&c,&m); if (d->r==1 && d->c==1) return new_real(*mat(m,c,*rind,*cind),""); result=new_matrix(d->r,d->c,""); mr=matrixof(result); for (i=0; ir; i++) { cind1=cind; m1=mat(mr,d->c,i,0); m2=mat(m,c,*rind,0); for (j=0; jc; j++) { m1[j]=m2[*cind1]; cind1++; } rind++; } return result; } if (hd->type==s_csubmatrix) { mhd=submrefof(hd); d=submdimsof(hd); rind=rowsof(hd); cind=colsof(hd); getmatrix(mhd,&r,&c,&m); if (d->r==1 && d->c==1) { m=cmat(m,c,*rind,*cind); return new_complex(*m,*(m+1),""); } result=new_cmatrix(d->r,d->c,""); mr=matrixof(result); for (i=0; ir; i++) { cind1=cind; m1=cmat(mr,d->c,i,0); m2=cmat(m,c,*rind,0); for (j=0; jc; j++) { m3=m2+(long)2*(*cind1); *m1++=*m3++; *m1++=*m3; cind1++; } rind++; } return result; } if (hd->type==s_isubmatrix) { mhd=submrefof(hd); d=submdimsof(hd); rind=rowsof(hd); cind=colsof(hd); getmatrix(mhd,&r,&c,&m); if (d->r==1 && d->c==1) { m=cmat(m,c,*rind,*cind); return new_interval(*m,*(m+1),""); } result=new_imatrix(d->r,d->c,""); mr=matrixof(result); for (i=0; ir; i++) { cind1=cind; m1=imat(mr,d->c,i,0); m2=imat(m,c,*rind,0); for (j=0; jc; j++) { m3=m2+(long)2*(*cind1); *m1++=*m3++; *m1++=*m3; cind1++; } rind++; } return result; } if (hd->type==s_matrix && dimsof(hd)->c==1 && dimsof(hd)->r==1) { return new_real(*matrixof(hd),""); } if (hd->type==s_cmatrix && dimsof(hd)->c==1 && dimsof(hd)->r==1) { return new_complex(*matrixof(hd),*(matrixof(hd)+1),""); } return hd; } header *getvariable (header *hd) /***** getvariable get an actual variable of a reference. *****/ { header *hd1; while (hd->type==s_reference) { if ((hd1=referenceof(hd))!=0) hd=hd1; else break; } return hd; } header *getvariablesub (header *hd) /***** getvariable get an actual variable of a reference. *****/ { header *old=hd; while (hd && hd->type==s_reference) hd=referenceof(hd); if (!hd) { output1("Variable %s not defined!\n",old->name); error=10; return new_string("Fehler",6,""); } if (hd->type==s_submatrix || hd->type==s_csubmatrix || hd->type==s_isubmatrix) { hd=submrefof(hd); } return hd; } void kill_local (char *name) /***** kill_local kill a loal variable name, if there is one. *****/ { unsigned long size,rest; header *hd=(header *)startlocal; while ((char *)hdname,name)) /* found! */ { size=hd->size; rest=newram-(char *)hd-size; if (size) memmove((char *)hd,(char *)hd+size,rest); endlocal-=size; newram-=size; return; } hd=(header *)((char *)hd+hd->size); } } header *next_param (header *hd) /***** next_param get the next value on stack, if there is one *****/ { hd=(header *)((char *)hd+hd->size); if ((char *)hd>=newram) return 0; else return hd; } void equal_params_3 (header **hd1, header **hd2, header **hd3) /* Make parameter values of equal type (real, complex, interval) */ { header *h1,*h2,*h3; h1=getvariablesub(*hd1); if (error) return; h2=getvariablesub(*hd2); if (error) return; h3=getvariablesub(*hd3); if (error) return; if (iscomplex(h1) || iscomplex(h2) || iscomplex (h3)) { make_complex(*hd1); *hd2=nextof(*hd1); make_complex(*hd2); *hd3=nextof(*hd2); make_complex(*hd3); } else if (isinterval(h1) || isinterval(h2) || isinterval(h3)) { make_interval(*hd1); *hd2=nextof(*hd1); make_interval(*hd2); *hd3=nextof(*hd2); make_interval(*hd3); } if (error) return; *hd1=getvalue(*hd1); if (error) return; *hd2=getvalue(*hd2); if (error) return; *hd3=getvalue(*hd3); if (error) return; } void equal_params_2 (header **hd1, header **hd2) /* Make parameter values of equal type (real, complex, interval) */ { header *h1,*h2; h1=getvariablesub(*hd1); if (error) return; h2=getvariablesub(*hd2); if (error) return; if (iscomplex(h1) || iscomplex(h2)) { make_complex(*hd1); *hd2=nextof(*hd1); make_complex(*hd2); } else if (isinterval(h1) || isinterval(h2)) { make_interval(*hd1); *hd2=nextof(*hd1); make_interval(*hd2); } if (error) return; *hd1=getvalue(*hd1); if (error) return; *hd2=getvalue(*hd2); if (error) return; } void kill_udf (char *name) /***** kill_udf kill a local variable name, if there is one. *****/ { unsigned long size,rest; header *hd=(header *)ramstart; while ((char *)hdname,name)) /* found! */ { size=hd->size; #ifndef SPLIT_MEM rest=newram-(char *)hd-size; if (size && rest) memmove((char *)hd,(char *)hd+size,rest); endlocal-=size; startlocal-=size; newram-=size; #else rest=udfend-(char *)hd-size; if (size && rest) memmove((char *)hd,(char *)hd+size,rest); #endif udfend-=size; return; } hd=(header *)((char *)hd+hd->size); } } void moveresult (header *stack, header *result) /***** moveresult move the result to the start of stack. *****/ { if (stack==result) return; memmove((char *)stack,(char *)result,result->size); newram=(char *)stack+stack->size; } void moveresult1 (header *stack, header *result) /***** moveresult move several results to the start of stack. *****/ { unsigned long size; if (stack==result) return; size=newram-(char *)result; memmove((char *)stack,(char *)result,size); newram=(char *)stack+size; } static int sametype (header *hd1, header *hd2) /***** sametype returns true, if hd1 and hd2 have the same type and dimensions. *****/ { dims *d1,*d2; if (hd1->type==s_string && hd2->type==s_string) return hd1->size>=hd2->size; if (hd1->type!=hd2->type || hd1->size!=hd2->size) return 0; if (hd1->type==s_matrix || hd1->type==s_cmatrix || hd1->type==s_imatrix) { d1=dimsof(hd1); d2=dimsof(hd2); if (d1->r!=d2->r) return 0; } return 1; } header *assign (header *var, header *value) /***** assign assign the value to the variable. *****/ { char name[16],*nextvar; unsigned long size; long dif; double *m,*mv,*m1,*m2; int i,j,c,r,cv,rv,*rind,*cind; dims *d; header *help,*orig; if (error) return 0; size=value->size; if (var->type==s_reference && !referenceof(var)) /* seems to be a new variable */ { strcpy(name,var->name); if (value->type==s_udf) { strcpy(value->name,name); value->xor=xor(name); #ifndef SPLIT_MEM if (!freeram(size)) { output("Memory overflow.\n"); error=500; return value; } memmove(ramstart+size,ramstart,newram-ramstart); newram+=size; endlocal+=size; startlocal+=size; value=(header *)((char *)value+size); #else if ((long)udfend+size>(long)udframend) { output1("Not enough memory for function %s!\n",name); error=500; return value; } memmove(ramstart+size,ramstart,udfend-ramstart); #endif udfend+=size; memmove(ramstart,(char *)value,size); return (header *)ramstart; } if (!freeram(size)) { output("Memory overflow.\n"); error=500; return value; } memmove(endlocal+size,endlocal,newram-endlocal); value=(header *)((char *)value+size); newram+=size; memmove(endlocal,(char *)value,size); strcpy(((header *)endlocal)->name,name); ((header *)endlocal)->xor=xor(name); value=(header *)endlocal; endlocal+=size; return value; } else { while (var && var->type==s_reference) var=referenceof(var); if (!var) { error=43; output("Internal variable error!\n"); return 0; } if (var->type!=s_udf && value->type==s_udf) { output("Cannot assign a UDF to a variable!\n"); error=320; return var; } if (var->type==s_submatrix) { d=submdimsof(var); if (value->type==s_complex || value->type==s_cmatrix) { orig=submrefof(var); help=new_reference(orig,""); if (error) return 0; mcomplex(help); if (error) return 0; var->type=s_csubmatrix; submrefof(var)=help; assign(var,value); if (error) return 0; submrefof(var)=orig; assign(orig,help); return orig; } else if (value->type==s_interval || value->type==s_imatrix) { orig=submrefof(var); help=new_reference(orig,""); if (error) return 0; minterval1(help); if (error) return 0; var->type=s_isubmatrix; submrefof(var)=help; assign(var,value); if (error) return 0; submrefof(var)=orig; assign(orig,help); return orig; } else if (value->type!=s_real && value->type!=s_matrix) { output("Cannot assign this type!\n"); error=45; return 0; } getmatrix(value,&rv,&cv,&mv); getmatrix(submrefof(var),&r,&c,&m); if (d->r!=rv || d->c!=cv) { if (rv==1 && cv==1) { rind=rowsof(var); cind=colsof(var); for (i=0; ir; i++) { m1=mat(m,c,rind[i],0); for (j=0; jc; j++) { m1[cind[j]]=*mv; } } return submrefof(var); } output("Illegal assignment!\n" "Row or column numbers do not agree!\n"); error=45; return 0; } rind=rowsof(var); cind=colsof(var); for (i=0; ir; i++) { m1=mat(m,c,rind[i],0); m2=mat(mv,cv,i,0); for (j=0; jc; j++) { m1[cind[j]]=*m2++; } } return submrefof(var); } else if (var->type==s_csubmatrix) { d=submdimsof(var); if (value->type==s_real || value->type==s_matrix) { help=new_reference(value,""); if (error) return 0; mcomplex(help); if (error) return 0; assign(var,help); return submrefof(var); } if (value->type!=s_complex && value->type!=s_cmatrix) { output("Illegal assignment!\n"); error=45; return 0; } getmatrix(value,&rv,&cv,&mv); getmatrix(submrefof(var),&r,&c,&m); if (d->r!=rv || d->c!=cv) { if (rv==1 && cv==1) { rind=rowsof(var); cind=colsof(var); for (i=0; ir; i++) { m1=cmat(m,c,rind[i],0); for (j=0; jc; j++) { copy_complex(m1+(long)2*cind[j],mv); } } return submrefof(var); } output("Illegal assignment!\n" "Row or column numbers do not agree!\n"); error=45; return 0; } rind=rowsof(var); cind=colsof(var); for (i=0; ir; i++) { m1=cmat(m,c,rind[i],0); m2=cmat(mv,cv,i,0); for (j=0; jc; j++) { copy_complex(m1+(long)2*cind[j],m2); m2+=2; } } return submrefof(var); } else if (var->type==s_isubmatrix) { d=submdimsof(var); if (value->type==s_real || value->type==s_matrix) { help=new_reference(value,""); if (error) return 0; minterval1(help); if (error) return 0; assign(var,help); return submrefof(var); } if (value->type!=s_interval && value->type!=s_imatrix) { output("Cannot assign this type to intervals!\n"); error=45; return 0; } getmatrix(value,&rv,&cv,&mv); getmatrix(submrefof(var),&r,&c,&m); if (d->r!=rv || d->c!=cv) { if (rv==1 && cv==1) { rind=rowsof(var); cind=colsof(var); for (i=0; ir; i++) { m1=imat(m,c,rind[i],0); for (j=0; jc; j++) { copy_interval(m1+(long)2*cind[j],mv); } } return submrefof(var); } output("Illegal assignment!\n" "Row or column numbers do not agree!\n"); error=45; return 0; } rind=rowsof(var); cind=colsof(var); for (i=0; ir; i++) { m1=imat(m,c,rind[i],0); m2=imat(mv,cv,i,0); for (j=0; jc; j++) { copy_interval(m1+(long)2*cind[j],m2); m2+=2; } } return submrefof(var); } else { if ((char *)varendlocal) /* its not a local variable! */ { if (!sametype(var,value)) { output1("Cannot change type of non-local variable %s!\n", var->name); error=12; return 0; } memcpy((char *)(var+1),(char *)(value+1), value->size-sizeof(header)); return var; } dif=(long)value->size-var->size; if (dif>0 && !freeram(dif)) { output("Memory overflow in assignment.\n"); error=501; return value; } nextvar=(char *)var+var->size; if (dif!=0) memmove(nextvar+dif,nextvar,newram-nextvar); newram+=dif; endlocal+=dif; value=(header *)((char *)value+dif); strcpy(value->name,var->name); value->xor=var->xor; memmove((char *)var,(char *)value,value->size); } } return var; } #ifndef SPLIT_MEM typedef struct { size_t udfend,startlocal,endlocal,newram; } ptyp; void mstore (header *hd) { FILE *file; ptyp p; hd=getvalue(hd); if (error) return; if (hd->type!=s_string) { output("Expect file name.\n"); error=1100; return; } p.udfend=udfend-ramstart; p.startlocal=startlocal-ramstart; p.endlocal=endlocal-ramstart; p.newram=newram-ramstart; file=fopen(stringof(hd),"wb"); if (!file) { output1("Could not open %s.\n",stringof(hd)); error=1101; return; } fwrite(&p,sizeof(ptyp),1,file); fwrite(ramstart,1,newram-ramstart,file); if (ferror(file)) { output("Write error.\n"); error=1102; return; } fclose(file); } void mrestore (header *hd) { FILE *file; ptyp p; if (udfon) { output("Cannot restore inside a UDF.\n"); error=1; return; } hd=getvalue(hd); if (error) return; if (hd->type!=s_string) { output("Expect file name.\n"); error=1100; return; } file=fopen(stringof(hd),"rb"); if (!file) { output1("Could not open %s.\n",stringof(hd)); error=1103; return; } fread(&p,sizeof(ptyp),1,file); if (ferror(file)) { output("Read error.\n"); error=1104; return; } fread(ramstart,1,p.newram,file); if (ferror(file)) { output("Read error (fatal for EULER).\n"); error=1104; return; } fclose(file); udfend=ramstart+p.udfend; startlocal=ramstart+p.startlocal; endlocal=ramstart+p.endlocal; newram=ramstart+p.newram; next=input_line; *next=0; } #endif