/*
 *	Euler - a numerical lab
 *
 *	platform : neutral
 *
 *	file : stack.h -- numerical stack management
 */

#ifndef _STACK_H_
#define _STACK_H_

#include "sysdep.h"

extern int error;
extern char *ramstart,*ramend,*startlocal,*endlocal,*newram,*udfend,*varstart,*udframend,*startglobal,*endglobal;

#define freeram(n) (((unsigned long)(newram)+(unsigned long)(n))<=(unsigned long)ramend)
#define freeramfrom(r,n) (((unsigned long)(r)+(unsigned long)(n))<=(unsigned long)ramend)

typedef enum {
	s_real,
	s_complex,
	s_matrix,
	s_cmatrix,
	s_reference,
	s_command,
	s_submatrix,
	s_csubmatrix,
	s_string,
	s_udf,
	s_interval,
	s_imatrix,
	s_isubmatrix
} stacktyp;

typedef struct {
	long size;
	char name[16];
	int xor;
	stacktyp type;
	int flags;
} headertest;

typedef struct{
	long size;
	char name[16];
	int xor;
	stacktyp type;
	int flags;
#ifdef HEADER_ALIGNMENT
	char dummy[((sizeof(headertest)-1)/HEADER_ALIGNMENT+1)*HEADER_ALIGNMENT-sizeof(headertest)];
#endif
} header;

typedef struct {
	int c,r;
} dimstest;

typedef struct {
	int c,r;
#ifdef DIMS_ALIGNMENT
	char dummy[((sizeof(dimstest)-1)/DIMS_ALIGNMENT+1)*DIMS_ALIGNMENT-sizeof(dimstest)];
#endif
} dims;

typedef struct { unsigned long s; } inttyp;

typedef struct { header hd; double val; } realtyp;

/*
 *	new stack objects
 */
header *new_matrix (int c, int r, char *name);
header *new_cmatrix (int c, int r, char *name);
header *new_imatrix (int c, int r, char *name);
header *new_real (double x, char *name);
header *new_complex (double x, double y, char *name);
header *new_reference (header *hd, char *name);
header *new_submatrix (header *hd, header *cols, header *rows, char *name);
header *new_csubmatrix (header *hd, header *cols, header *rows,	char *name);
header *new_isubmatrix (header *hd, header *cols, header *rows,	char *name);
header *new_command (int no);
header *new_string (char *s, unsigned long size, char *name);
header *new_udf (char *name);
header *new_subm (header *var, long l, char *name);
header *new_csubm (header *var, long l, char *name);
header *new_isubm (header *var, long l, char *name);
header *new_interval (double x, double y, char *name);

/*
 *	macros for object handling
 */
#define realof(hd) ((double *)((hd)+1))
#define matrixof(hd) ((double *)((char *)((hd)+1)+sizeof(dims)))
#define dimsof(hd) ((dims *)((hd)+1))
#define commandof(hd) ((int *)((hd)+1))
#define referenceof(hd) (*((header **)((hd)+1)))
#define imagof(hd) ((double *)((hd)+1)+1)
#define rowsof(hd) ((int *)((dims *)((header **)((hd)+1)+1)+1))
#define colsof(hd) ((int *)((dims *)((header **)((hd)+1)+1)+1)+submdimsof((hd))->r)
#define submrefof(hd) (*((header **)((hd)+1)))
#define submdimsof(hd) ((dims *)((header **)((hd)+1)+1))
#define stringof(hd) ((char *)((hd)+1))
#define udfof(hd) ((char *)(hd)+(*((unsigned long *)((hd)+1))))
#define udfstartof(hd) ((unsigned long *)((hd)+1))
#define helpof(hd) ((char *)(hd)+sizeof(header)+sizeof(unsigned long))
#define nextof(hd) ((header *)((char *)(hd)+(hd)->size))

#define mat(m,c,i,j) (m+(((long)(c))*(i)+(j)))
#define cmat(m,c,i,j) (m+(2*(((long)(c))*(i)+(j))))
#define imat(m,c,i,j) (m+(2*(((long)(c))*(i)+(j))))

#define matrixsize(c,r) (sizeof(header)+sizeof(dims)+(c)*(long)(r)*sizeof(double))
#define cmatrixsize(c,r) (sizeof(header)+sizeof(dims)+2l*(c)*(long)(r)*sizeof(double))
#define imatrixsize(c,r) (sizeof(header)+sizeof(dims)+2l*(c)*(long)(r)*sizeof(double))

#define aof(hd) ((double *)((hd)+1))
#define bof(hd) ((double *)((hd)+1)+1)

#define isreal(hd) (((hd)->type==s_real || (hd)->type==s_matrix))
#define isinterval(hd) (((hd)->type==s_interval || (hd)->type==s_imatrix))
#define iscomplex(hd) (((hd)->type==s_complex || (hd)->type==s_cmatrix))

int xor (char *n);

void make_complex (header *hd);

void getmatrix (header *hd, int *r, int *c, double **x);
void get_element (int nargs, header *var, header *hd);
void get_element1 (char *name, header *hd);


header *searchvar (char *name);
header *searchudf (char *name);

header *getvalue (header *);
header *getvariable (header *);
header *getvariablesub (header *);

header *next_param (header *hd);
void equal_params_3 (header **hd1, header **hd2, header **hd3);
void equal_params_2 (header **hd1, header **hd2);

void moveresult (header *stack, header *result);
void moveresult1 (header *stack, header *result);

header *assign (header *var, header *value);

void kill_local (char *name);
void kill_udf (char *name);

/*
 *	strore /restore the whole stack to / from a file
 */
#ifndef SPLIT_MEM
void mstore (header *hd);
void mrestore (header *hd);
#endif

#endif
