/*
 * matrix program copyright (C) 2009 - 2010 H.Niwa
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <errno.h>
#include <setjmp.h>
#include <sys/time.h>
#include <math.h>
#include <libgen.h>
#include <setjmp.h>

#include <string>
#include <complex>

#include "syserr.h"

#include "bin_node.h"
#include "gc.h"
#include "var.h"
#include "pred.h"
#include "context.h"
#include "unify.h"
#include "builtin.h"
#include "sysmodule.h"
#include "func.h"
#include "matrix.h"

extern void PushStack(Context* cx, Node* goals, Node* md, Node* env);
extern int PopStack(Context* cx, Node* &goals, Node* &md, Node* &env);

int matrix_zero(Context* cx, Node* goalscar, List* module);
int matrix_unit(Context* cx, Node* goalscar, List* module);
int matrix_set(Context* cx, Node* goalscar, List* module);
int matrix_display(Context* cx, Node* goalscar, List* module);
int matrix_add(Context* cx, Node* goalscar, List* module);
int matrix_sub(Context* cx, Node* goalscar, List* module);
int matrix_mul(Context* cx, Node* goalscar, List* module);
int matrix_mulscalar(Context* cx, Node* goalscar, List* module);
int matrix_divscalar(Context* cx, Node* goalscar, List* module);
int matrix_det(Context* cx, Node* goalscar, List* module);
int matrix_inv(Context* cx, Node* goalscar, List* module);
int matrix_tra(Context* cx, Node* goalscar, List* module);
int matrix_solve(Context* cx, Node* goalscar, List* module);
int matrix_eigen(Context* cx, Node* goalscar, List* module);
int matrix_dimentions(Context* cx, Node* goalscar, List* module);
int matrix_getrow(Context* cx, Node* goalscar, List* module);
int matrix_getcolumn(Context* cx, Node* goalscar, List* module);
int matrix_getrow_column(Context* cx, Node* goalscar, List* module);
int matrix_setrow_column(Context* cx, Node* goalscar, List* module);
int matrix_swaprow(Context* cx, Node* goalscar, List* module);
int matrix_swapcolumn(Context* cx, Node* goalscar, List* module);
int matrix_rangerow(Context* cx, Node* goalscar, List* module);
int matrix_rangecolumn(Context* cx, Node* goalscar, List* module);
int matrix_range(Context* cx, Node* goalscar, List* module);
int matrix_random(Context* cx, Node* goalscar, List* module);
int matrix_fourier(Context* cx, Node* goalscar, List* module);
int matrix_invfourier(Context* cx, Node* goalscar, List* module);
int matrix_row_sort_ascending(Context* cx, Node* goalscar, List* module);
int matrix_row_sort_descending(Context* cx, Node* goalscar, List* module);
int matrix_column_sort_ascending(Context* cx, Node* goalscar, List* module);
int matrix_column_sort_descending(Context* cx, Node* goalscar, List* module);

int matrix_equal(Context* cx, Node* goalscar, List* module);
int matrix_notequal(Context* cx, Node* goalscar, List* module);

int matrix_ismatrix(Context* cx, Node* goalscar, List* module);
int matrix_isvector(Context* cx, Node* goalscar, List* module);
int matrix_issquare(Context* cx, Node* goalscar, List* module);
int matrix_isnull(Context* cx, Node* goalscar, List* module);
int matrix_isdiagonal(Context* cx, Node* goalscar, List* module);
int matrix_issymmetric(Context* cx, Node* goalscar, List* module);
int matrix_isregular(Context* cx, Node* goalscar, List* module);
int matrix_issingular(Context* cx, Node* goalscar, List* module);
int matrix_expr(Context* cx, Node* goalscar, List* module);
int matrix_norm(Context* cx, Node* goalscar, List* module);
int matrix_cofact(Context* cx, Node* goalscar, List* module);
int matrix_adj(Context* cx, Node* goalscar, List* module);

int matrix_copy(Context* cx, Node* goalscar, List* module);

#ifdef __CYGWIN__
long double fabsl(long double x)
{
	if (x < 0.0L) {
		x = -x;
	}
	return x;
}

#endif


#define	EPS	(1E-18)

int CheckMatrix(Node* mat, int& row, int& column, long double*& d)
{
	Node* n;
	if (mat->kind() != LIST) {
		return 0;
	}
	row = ListLength(mat);
	if (mat->Car()->kind() != LIST) {
		return 0;
	}
	column = ListLength(mat->Car());
	d = new long double[column*row];

	int i,j;
	for (i=0, n=mat->Car(); i < row; i++, mat=mat->Cdr(), n=mat->Car()) {
		if (ListLength(n) != column) {
			delete [] d;
			return 0;
		}
		for (j=0; j < column; j++, n=n->Cdr()) {
			if (n->Car()->kind() != ATOM) {
				delete [] d;
				return 0;
			}
			long double	dn;
			if (!((Atom*)n->Car())->toFloat(dn)) {
				delete [] d;
				return 0;
			}
			d[i*column+j] = dn;
		}
	}
	return 1;
}

int pivot(long double* d, int t, int row, int column, int* piv)
{
	int i;
	long double dn = fabsl(d[t*column+t]);

	int u = t;
	for (i = t+1; i < row; i++) {
		if (fabsl(d[i*column+t]) > dn) {
			u = i;
			dn = fabsl(d[i*column+t]);
			
		}
	}
	if (u == t) {
		return 0;
	}

	for (i = 0; i < column; i++) {
		dn = d[t*column+i];
		d[t*column+i] = d[u*column+i];
		d[u*column+i] = dn;
	}
	
	int tmp = piv[t];
	piv[t] = piv[u];
	piv[u] = tmp;
			
	return 1;
}

int pivot(long double* d, int t, int row, int column)
{
	int* piv = new int[row];
	int r = pivot(d, t, row, column, piv);
	delete [] piv;
	return r;
}

static int LU(long double* dl, long double* du, long double* dlu,
					int row, int column, int* piv)
{
	if (row != column) {
		syserr("not a square matrix\n");
		return 0;
	}
	
	int i,j,t;
	for (i = 0; i < row; i++) {
		for (j = 0; j < column; j++) {
			du[i*column+j] = dlu[i*column+j];
		}
		piv[i] = i;
	}

	for (t = 0; t < row; t++ ){
		if (pivot(du, t, row, column, piv)) {
			if (fabsl(du[t*column+t]) < EPS) {
				syserr("zero divide");
				return 0;
			}
		}
				
		for (i = t+1; i < row; i++){
			du[i*column+t] /= du[t*column+t];
			for (j=t+1; j < column; j++) {
				du[i*column+j] -= du[i*column+t]*du[t*column+j];
			}
		}
	}

	for (i = 0; i < row; i++) {
		for (j = 0; j < column; j++) {
			if (i == j) {
				dl[i*column+j] = 1.0L;
			} else if ( i < j) {
				dl[i*column+j] = 0.0L;
			} else {
				dl[i*column+j] = du[i*column+j];
				du[i*column+j] = 0.0L;
			}
		}
	}

	return 1;
}

static int inv(long double* d1, int row, int column)
{
	if (row != column) {
		syserr("not a square matrix\n");
		return 0;
	}

	long double dn;
	long double* d2 = new long double[row*column];
	int i,j,k;
	
	for (i = 0; i < row; i++) {
	    for (j = 0; j < column; j++) {
	    	if (i == j) {
			d2[i*column+j] = 1.0L;
		} else {
			d2[i*column+j] = 0.0L;
		}
	    }
	}

	for (i = 0; i < row; i++) {
		dn = d1[i*column+i];
		if (fabsl(dn) < EPS) {
			delete [] d2;
			syserr("zero divide\n");
			return 0;
		}

		for (j = 0; j < column; j++) {
			d1[i*column+j] /= dn;
			d2[i*column+j] /= dn;
		}
		for (j = 0; j < column; j++) {
			if (i != j) {
				dn = d1[j*column+i];
				for (k = 0; k < column; k++) {
					d1[j*column+k] -= d1[i*column+k]*dn;
					d2[j*column+k] -= d2[i*column+k]*dn;
				}
			}
		}
	}

	for (i = 0; i < row; i++) {
		for (j = 0; j < column; j++) {
			d1[i*column+j] = d2[i*column+j];
		}
	}

	return 1;	
}

static int solve(long double* x, long double* d, int row, int column, long double* c)
{
	long double* dl = new long double[row*column];
	long double* du = new long double[row*column];
	int* piv = new int[row];

	if (!LU(dl, du, d, row, column, piv)) {
		delete [] dl;
		delete [] du;
		delete [] piv;
		return 0;
	}


	if (!inv(dl, row, column)) {
		delete [] dl;
		delete [] du;
		delete [] piv;
		return 0;
	}

		
	if (!inv(du, row, column)) {
		delete [] dl;
		delete [] du;
		delete [] piv;
		return 0;
	}
		
	int i, j;
	long double* c2 = new long double[row*column];
	for (i = 0; i < row; i++) {
		c2[i] = 0.0L;
		for (j = 0; j < column; j++) {
			c2[i] += dl[i*column+j]*c[piv[j]];
		}
	}

	for (i = 0; i < row; i++) {
		x[i] = 0;
		for (j = 0; j < column; j++) {
			x[i] += du[i*column+j]*c2[j];
		}
	}

	delete [] dl;
	delete [] du;
	delete [] piv;
	delete [] c2;

	return 1;
}

int eigenvalue(long double* x, long double& eval, long double* d, int row)
{
	int i, j;
	int maxi = 0;
	long double max;
	long double sum;
	long double* y = new long double[row];
	int n;

	for (i = 0; i < row; i++) {
		x[i] = 1.0L;
	}

	for (n = 0; n <= 1000; n++){
		for(i = 0; i < row; i++){
			sum = 0.0L;
			for (j = 0; j < row; j++) {
				 sum += d[i*row+j] * x[j];
			}
			y[i] = sum;
		}

		long double oldmax = max;
		int oldi = maxi;
		max = 0.0L; 
		for (i = 0; i < row; i++){
			if(fabsl(y[i]) > fabsl(max)){
				max = y[i];  
				maxi = i;  
			}
		}
		if (fabsl(max) < EPS) {
			continue;
		}

		for(i = 0; i < row; i++){
			x[i] = y[i] / max; 
		}

		if ((fabsl(max-oldmax) <= EPS) && 
					(maxi == oldi)) {
			break;
		}
	}
	eval = max;

	delete [] y;

	return 1;
}

#if defined(__CYGWIN__) && !defined(__MINGW32__)
#define atanl(x)        atan(x)
#endif

void fourier(int n, long double* f_r, long double* f_i, 
				long double* newf_r, long double* newf_i) 
{
	long double t_r;
	long double t_i;

	long double c_r;
	long double c_i;

	long double PI = atanl(1.0)*4.0L;
	
	int	i, j, k;

	t_r = f_r[0];
	t_i = f_i[0];

	for(i = 0; i < n; i++) {
		newf_r[i] = 0.0L;
		newf_i[i] = 0.0L;
		for(k = 0; k < n; k++) {
			int	a = -i*k+n*n;

			// times by
			c_r = cos(2.0L * PI * a / n);
			c_i = sin(2.0L * PI * a / n);
			t_r = f_r[k] * c_r - f_i[k] * c_i;
			t_i = f_i[k] * c_r + f_r[k] * c_i;

			newf_r[i] += t_r;
			newf_i[i] += t_i;
		}
	}

	for(i = 0; i < n; i++) {
		newf_r[i] /= n;
		newf_i[i] /= n;
	}

}

void inverse_fourier(int n, long double* f_r, long double* f_i, 
				long double* newf_r, long double* newf_i) 
{
	long double t_r;
	long double t_i;

	long double c_r;
	long double c_i;

	long double PI = atanl(1.0)*4.0L;

	int	i, j, k;

	t_r = f_r[0];
	t_i = f_i[0];

	for(i = 0; i < n; i++) {
		newf_r[i] = 0.0L;
		newf_i[i] = 0.0L;
		for(k = 0; k < n; k++) {
			int	a = i * k;

			// times by
			c_r = cos(2.0L * PI * a / n);
			c_i = sin(2.0L * PI * a / n);
			t_r = f_r[k] * c_r - f_i[k] * c_i;
			t_i = f_i[k] * c_r + f_r[k] * c_i;

			newf_r[i] += t_r;
			newf_i[i] += t_i;
		}
	}

}

/* ---------------------------------------------------------------*/
int matrixmodule(Context* cx, Node* goalscar, Node* goalscdr, 
				Node* goals, List* module, int& r)
{
	Node* retn;
	int	rn;

	std::string	s;

	if (goalscar->Val()->Car()->kind() == ATOM) {
		((Atom*)(goalscar->Val()->Car()))->toString(s);

		if (s == "zero") {
			r = matrix_zero(cx, goalscar, module);
			return 1;
		} else if (s == "identity") {
			r = matrix_unit(cx, goalscar, module);
			return 1;
		} else if (s == "i") {
			r = matrix_unit(cx, goalscar, module);
			return 1;
		} else if (s == "set") {
			r = matrix_set(cx, goalscar, module);
			return 1;
		} else if (s == "add") {
			r = matrix_add(cx, goalscar, module);
			return 1;
		} else if (s == "sub") {
			r = matrix_sub(cx, goalscar, module);
			return 1;
		} else if (s == "mul") {
			r = matrix_mul(cx, goalscar, module);
			return 1;
		} else if (s == "mulscalar") {
			r = matrix_mulscalar(cx, goalscar, module);
			return 1;
		} else if (s == "divscalar") {
			r = matrix_divscalar(cx, goalscar, module);
			return 1;
		} else if (s == "mulscalar") {
			r = matrix_mulscalar(cx, goalscar, module);
			return 1;
		} else if (s == "divscalar") {
			r = matrix_divscalar(cx, goalscar, module);
			return 1;
		} else if (s == "transposed") {
			r = matrix_tra(cx, goalscar, module);
			return 1;
		} else if (s == "t") {
			r = matrix_tra(cx, goalscar, module);
			return 1;
		} else if (s == "size") {
			r = matrix_dimentions(cx, goalscar, module);
			return 1;
		} else if (s == "getval") {
			r = matrix_getrow_column(cx, goalscar, module);
			return 1;
		} else if (s == "setval") {
			r = matrix_setrow_column(cx, goalscar, module);
			return 1;
		} else if (s == "getrow") {
			r = matrix_getrow(cx, goalscar, module);
			return 1;
		} else if (s == "getcolumn") {
			r = matrix_getcolumn(cx, goalscar, module);
			return 1;
		} else if (s == "swaprow") {
			r = matrix_swaprow(cx, goalscar, module);
			return 1;
		} else if (s == "swapcolumn") {
			r = matrix_swapcolumn(cx, goalscar, module);
			return 1;
		} else if (s == "rangerow") {
			r = matrix_rangerow(cx, goalscar, module);
			return 1;
		} else if (s == "rangecolumn") {
			r = matrix_rangecolumn(cx, goalscar, module);
			return 1;
		} else if (s == "range") {
			r = matrix_range(cx, goalscar, module);
			return 1;
		} else if (s == "equal") {
			r = matrix_equal(cx, goalscar, module);
			return 1;
		} else if (s == "notequal") {
			r = matrix_notequal(cx, goalscar, module);
			return 1;
		} else if (s == "ismatrix") {
			r = matrix_ismatrix(cx, goalscar, module);
			return 1;
		} else if (s == "isvector") {
			r = matrix_isvector(cx, goalscar, module);
			return 1;
		} else if (s == "issquare") {
			r = matrix_issquare(cx, goalscar, module);
			return 1;
		} else if (s == "isnull") {
			r = matrix_isnull(cx, goalscar, module);
			return 1;
		} else if (s == "isdiagonal") {
			r = matrix_isdiagonal(cx, goalscar, module);
			return 1;
		} else if (s == "issymmetric") {
			r = matrix_issymmetric(cx, goalscar, module);
			return 1;
		} else if (s == "isregular") {
			r = matrix_isregular(cx, goalscar, module);
			return 1;
		} else if (s == "issingular") {
			r = matrix_issingular(cx, goalscar, module);
			return 1;
		} else if (s == "det") {
			r = matrix_det(cx, goalscar, module);
			return 1;
		} else if (s == "inv") {
			r = matrix_inv(cx, goalscar, module);
			return 1;
		} else if (s == "random") {
			r = matrix_random(cx, goalscar, module);
			return 1;
		} else if (s == "solve") {
			r = matrix_solve(cx, goalscar, module);
			return 1;
		} else if (s == "eigen") {
			r = matrix_eigen(cx, goalscar, module);
			return 1;
		} else if (s == "fourier") {
			r = matrix_fourier(cx, goalscar, module);
			return 1;
		} else if (s == "invfourier") {
			r = matrix_invfourier(cx, goalscar, module);
			return 1;
		} else if (s == "RowSortAscend") {
			r = matrix_row_sort_ascending(cx, goalscar, module);
			return 1;
		} else if (s == "RowSortDescend") {
			r = matrix_row_sort_descending(cx, goalscar, module);
			return 1;
		} else if (s == "ColumnSortAscend") {
			r = matrix_column_sort_ascending(cx, goalscar, module);
			return 1;
		} else if (s == "ColumnSortDescend") {
			r = matrix_column_sort_descending(cx, goalscar, module);
			return 1;
		} else if (s == "copy") {
			r = matrix_copy(cx, goalscar, module);
			return 1;
		}
	}

	r = -1;
	syserr("The predicate that did not exist in the matrix module is used. \n");
	return 1;
}

int matrix_zero(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <zero VAR ROW COLUMN>\n");
		return 0;
	}

	Node* g    = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("zero: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <zero VAR ROW COLUMN>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrow = g->Car()->Val();
	if ((rn = FuncArg(cx, nrow, goalscar, module)) <= 0) {
		syserr("zero: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrow->kind() != ATOM) {
		syserr("usage: ::matrix <zero VAR ROW COLUMN>\n");
		return 0;
	}

	long long row;
	((Atom*)nrow)->toInt(row);
	if (row <= 0) {
		syserr("usage: ::matrix <zero VAR ROW COLUMN>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumn = g->Car()->Val();

	if ((rn = FuncArg(cx, ncolumn, goalscar, module)) <= 0) {
		syserr("zero: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumn->kind() != ATOM) {
		syserr("usage: ::matrix <zero VAR ROW COLUMN>\n");
		return 0;
	}

	long long column;
	((Atom*)ncolumn)->toInt(column);
	if (row <= 0) {
		syserr("usage: ::matrix <zero VAR ROW COLUMN>\n");
		return 0;
	}

	int	i, j;
	Node*	nmat=Nil;
	
	for (i=0; i < row; i++) {
		Node* nlist = Nil;
		for (j=0; j < column; j++) {
			nlist = Append(nlist, MkList(mka((long double)0.0L)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);
	return 1;

}

int matrix_unit(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <unit VAR ROW>\n");
		return 0;
	}

	Node* g    = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("unit: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <unit VAR ROW>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrow = g->Car()->Val();
	if ((rn = FuncArg(cx, nrow, goalscar, module)) <= 0) {
		syserr("unit: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrow->kind() != ATOM) {
		syserr("usage: ::matrix <unit VAR ROW>\n");
		return 0;
	}

	long long row;
	((Atom*)nrow)->toInt(row);
	if (row <= 0) {
		syserr("usage: ::matrix <unit VAR ROW>\n");
		return 0;
	}

	int	i, j;
	Node*	nmat=Nil;
	
	for (i=0; i < row; i++) {
		Node* nlist = Nil;
		for (j=0; j < row; j++) {
			if (i == j) {
				nlist = Append(nlist, MkList(mka((long double)1.0L)));
			} else {
				nlist = Append(nlist, MkList(mka((long double)0.0L)));
			}
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);
	return 1;

}

int matrix_set(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 4) {
		syserr("usage: ::matrix <set VAR ROW COLUMN LIST>\n");
		return 0;
	}

	Node* g    = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <set VAR ROW COLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrow = g->Car()->Val();
	if ((rn = FuncArg(cx, nrow, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrow->kind() != ATOM) {
		syserr("usage: ::matrix <set VAR ROW COLUMN LIST>\n");
		return 0;
	}

	long long row;
	((Atom*)nrow)->toInt(row);
	if (row <= 0) {
		syserr("usage: ::matrix <set VAR ROW COLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumn = g->Car()->Val();

	if ((rn = FuncArg(cx, ncolumn, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumn->kind() != ATOM) {
		syserr("usage: ::matrix <set VAR ROW COLUMN LIST>\n");
		return 0;
	}

	long long column;
	((Atom*)ncolumn)->toInt(column);
	if (row <= 0) {
		syserr("usage: ::matrix <set VAR ROW COLUMN LIST>\n");
		return 0;
	}


	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <set VAR ROW COLUMN LIST>\n");
		return 0;
	}

	if (ListLength(nlist) != row*column) {
		syserr("set: LIST length error \n");
		return 0;
	}
	
	int i,j;
	Node*	nmat = Nil;
	Node*	nlist2 = Nil;
	for (i = 0; i < row; i++) {
		nlist2 = Nil;
		for (j = 0; j < column; j++) {
			long double dn;
			if (nlist->Car()->kind() != ATOM) {
				syserr("set: element of LIST is not a number.\n");
				return 0;
			}
			if (!((Atom*)nlist->Car())->toFloat(dn)) {
				syserr("set: element of LIST is not a number.\n");
				return 0;
			}
			nlist2 = Append(nlist2, MkList(mka(dn)));
			nlist = nlist->Cdr();
		}
		nmat = Append(nmat, MkList(nlist2));
	}


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);
	return 1;
}

int matrix_display(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <display LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("display: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		nlist->print(cx->ioout);
		fprintf(cx->ioout, "\n");
		return 1;
	}

	for ( ; nlist->kind() != ATOM; nlist = nlist->Cdr()) {
		Node* nlist2 = nlist->Car();
		for ( ; nlist2->kind() != ATOM; nlist2=nlist2->Cdr()) {
			long double dn;
			if (nlist2->Car()->kind() != ATOM) {
				syserr("display: element of LIST is not a number.\n");
				return 0;
			}
			if (!((Atom*)nlist2->Car())->toFloat(dn)) {
				syserr("display: element of LIST is not a number.\n");
				return 0;
			}

			printf("\t%Lg", dn);
		}
		printf("\n");
	}
	return 1;
}


int matrix_add(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <add VAR LIST1 LIST2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("add: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <add VAR LIST1 LIST2>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nmat1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat1, goalscar, module)) <= 0) {
		syserr("add: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat1->kind() != LIST) {
		syserr("usage: ::matrix <add VAR LIST1 LIST2>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nmat1, row1, column1, d1)) {
		syserr("usage: ::matrix <add VAR LIST1 LIST2>\n");
		return 0;
	}

	g=g->Cdr();
	Node* nmat2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
		delete [] d1;
		syserr("add: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat2->kind() != LIST) {
		delete [] d1;
		syserr("usage: ::matrix <add VAR LIST1 LIST2>\n");
		return 0;
	}

	int row2, column2;
	long double* d2;
	if (!CheckMatrix(nmat2, row2, column2, d2)) {
		delete [] d1;
		syserr("usage: ::matrix <add VAR LIST1 LIST2>\n");
		return 0;
	}

	if ((row1 != row2) || (column1 != column2)) {
		delete [] d1;
		delete [] d2;
		syserr("add: size of matrix is not corresponding\n");
		return 0;
	}

	Node* nmat=Nil;
	int i,j;
	long double dn;

	for (i=0; i < row1; i++) {
		Node* nlist = Nil;
		for (j=0; j < column1; j++) {
			dn = d1[i*column1+j]+d2[i*column1+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] d2;
	return 1;
}

int matrix_sub(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <sub VAR LIST1 LIST2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("sub: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <sub VAR LIST1 LIST2>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nmat1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat1, goalscar, module)) <= 0) {
		syserr("sub: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat1->kind() != LIST) {
		syserr("usage: ::matrix <sub VAR LIST1 LIST2>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nmat1, row1, column1, d1)) {
		syserr("usage: ::matrix <sub VAR LIST1 LIST2>\n");
		return 0;
	}

	g=g->Cdr();
	Node* nmat2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
		delete [] d1;
		syserr("sub: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat2->kind() != LIST) {
		delete [] d1;
		syserr("usage: ::matrix <sub VAR LIST1 LIST2>\n");
		return 0;
	}

	int row2, column2;
	long double* d2;
	if (!CheckMatrix(nmat2, row2, column2, d2)) {
		delete [] d1;
		syserr("usage: ::matrix <sub VAR LIST1 LIST2>\n");
		return 0;
	}

	if ((row1 != row2) || (column1 != column2)) {
		delete [] d1;
		delete [] d2;
		syserr("sub: size of matrix is not corresponding\n");
		return 0;
	}

	Node* nmat=Nil;
	int i,j;
	long double dn;

	for (i=0; i < row1; i++) {
		Node* nlist = Nil;
		for (j=0; j < column1; j++) {
			dn = d1[i*column1+j]-d2[i*column1+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] d2;
	return 1;
}


int matrix_mul(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("mul: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nmat1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat1, goalscar, module)) <= 0) {
		syserr("mul: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat1->kind() == ATOM) {
		long double dn1;
		if (!((Atom*)nmat1)->toFloat(dn1)) {
			syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
			return 0;
		}

		g=g->Cdr();
		Node* nmat2 = g->Car()->Val();
		if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
			syserr("mul: failed in the evaluation of the argument. \n");
			return 0;
		}

		if (nmat2->kind() == ATOM) {
			long double dn2;
			if (!((Atom*)nmat2)->toFloat(dn2)) {
				syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
				return 0;
			}

			Node* env = Nil->Cons(Nil);

			SetEnv(env, nvar);
			((Undef*)(nvar->Val()))->Set(mka(dn1*dn2));

			PushStack(cx, Nil, Nil, env);

			return 1;
			
		}

		if (nmat2->kind() != LIST) {
			syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
			return 0;
		}

		int row2, column2;
		long double* d2;
		if (!CheckMatrix(nmat2, row2, column2, d2)) {
			syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
			return 0;
		}

		Node* nmat=Nil;
		int i,j;
		long double dn;

		for (i=0; i < row2; i++) {
			Node* nlist = Nil;
			for (j=0; j < column2; j++) {
				dn = dn1*d2[i*column2+j];
				nlist = Append(nlist, MkList(mka(dn)));
			}
			nmat = Append(nmat, MkList(nlist));
		}			


		Node* env = Nil->Cons(Nil);

		SetEnv(env, nvar);
		((Undef*)(nvar->Val()))->Set(nmat);

		PushStack(cx, Nil, Nil, env);

		delete [] d2;
		return 1;

	}

	if (nmat1->kind() != LIST) {
		syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nmat1, row1, column1, d1)) {
		syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
		return 0;
	}

	g=g->Cdr();
	Node* nmat2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
		delete [] d1;
		syserr("mul: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat2->kind() == ATOM) {
		long double dn2;
		if (!((Atom*)nmat2)->toFloat(dn2)) {
			delete [] d1;
			syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
			return 0;
		}

		int row1, column1;
		long double* d1;
		if (!CheckMatrix(nmat1, row1, column1, d1)) {
			delete [] d1;
			syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
			return 0;
		}

		Node* nmat=Nil;
		int i,j;
		long double dn;

		for (i=0; i < row1; i++) {
			Node* nlist = Nil;
			for (j=0; j < column1; j++) {
				dn = dn2*d1[i*column1+j];
				nlist = Append(nlist, MkList(mka(dn)));
			}
			nmat = Append(nmat, MkList(nlist));
		}			


		Node* env = Nil->Cons(Nil);

		SetEnv(env, nvar);
		((Undef*)(nvar->Val()))->Set(nmat);

		PushStack(cx, Nil, Nil, env);

		delete [] d1;
		return 1;

	}

	if (nmat2->kind() != LIST) {
		delete [] d1;
		syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
		return 0;
	}

	int row2, column2;
	long double* d2;
	if (!CheckMatrix(nmat2, row2, column2, d2)) {
		delete [] d1;
		syserr("usage: ::matrix <mul VAR LIST1 LIST2>\n");
		return 0;
	}

	if (column1 != row2) {
		delete [] d1;
		delete [] d2;
		syserr("mul: size of matrix is not corresponding\n");
		return 0;
	}

	Node* nmat=Nil;
	int i,j,k;
	long double* dn = new long double [row1*column2];

	for (i=0; i < row1; i++) {
		Node* nlist = Nil;
		for (j=0; j < column2; j++) {
			dn[i*column2+j] = 0.0L;
			for (k=0; k < column1; k++) {
				dn[i*column2+j] += d1[i*column1+k]
							*d2[k*column2+j];
			}
			nlist = Append(nlist, MkList(mka(dn[i*column2+j])));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] d2;
	delete [] dn;
	return 1;
}

int matrix_mulscalar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <mulscalar VAR VAL1 LIST2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("mulscalar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <mulscalar VAR VAL1 LIST2>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nmat1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat1, goalscar, module)) <= 0) {
		syserr("mulscalar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat1->kind() == ATOM) {
		long double dn1;
		if (!((Atom*)nmat1)->toFloat(dn1)) {
			syserr("usage: ::matrix <mulscalar VAR VAL1 LIST2>\n");
			return 0;
		}

		g=g->Cdr();
		Node* nmat2 = g->Car()->Val();
		if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
			syserr("mulscalar: failed in the evaluation of the argument. \n");
			return 0;
		}

		if (nmat2->kind() == ATOM) {
			long double dn2;
			if (!((Atom*)nmat2)->toFloat(dn2)) {
				syserr("usage: ::matrix <mulscalar VAR VAL1 LIST2>\n");
				return 0;
			}

			Node* env = Nil->Cons(Nil);

			SetEnv(env, nvar);
			((Undef*)(nvar->Val()))->Set(mka(dn1*dn2));

			PushStack(cx, Nil, Nil, env);

			return 1;
			
		}

		if (nmat2->kind() != LIST) {
			syserr("usage: ::matrix <mulscalar VAR VAL1 LIST2>\n");
			return 0;
		}

		int row2, column2;
		long double* d2;
		if (!CheckMatrix(nmat2, row2, column2, d2)) {
			syserr("usage: ::matrix <mulscalar VAR VAL1 LIST2>\n");
			return 0;
		}

		Node* nmat=Nil;
		int i,j;
		long double dn;

		for (i=0; i < row2; i++) {
			Node* nlist = Nil;
			for (j=0; j < column2; j++) {
				dn = dn1*d2[i*column2+j];
				nlist = Append(nlist, MkList(mka(dn)));
			}
			nmat = Append(nmat, MkList(nlist));
		}			


		Node* env = Nil->Cons(Nil);

		SetEnv(env, nvar);
		((Undef*)(nvar->Val()))->Set(nmat);

		PushStack(cx, Nil, Nil, env);

		delete [] d2;
		return 1;

	}

	syserr("mulscalar: failed in the evaluation of the argument. \n");
	return 0;
}

int matrix_divscalar(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <divscalar VAR LIST1 VAL2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("divscalar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <divscalar VAR LIST1 VAL2>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nmat1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat1, goalscar, module)) <= 0) {
		syserr("divscalar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat1->kind() != LIST) {
		syserr("usage: ::matrix <divscalar VAR LIST1 VAL2>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nmat1, row1, column1, d1)) {
		syserr("usage: ::matrix <divscalar VAR LIST1 VAL2>\n");
		return 0;
	}

	g=g->Cdr();
	Node* nmat2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
		delete [] d1;
		syserr("divscalar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat2->kind() == ATOM) {
		long double dn2;
		if (!((Atom*)nmat2)->toFloat(dn2)) {
			delete [] d1;
			syserr("usage: ::matrix <divscalar VAR LIST1 VAL2>\n");
			return 0;
		}

		int row1, column1;
		long double* d1;
		if (!CheckMatrix(nmat1, row1, column1, d1)) {
			syserr("usage: ::matrix <divscalar VAR LIST1 VAL2>\n");
			return 0;
		}

		if (dn2 == 0.0L) {
			delete [] d1;
			syserr("divscalar: divided by zero \n");
			return 0;
		}
		
		Node* nmat=Nil;
		int i,j;
		long double dn;

		for (i=0; i < row1; i++) {
			Node* nlist = Nil;
			for (j=0; j < column1; j++) {
				dn = d1[i*column1+j]/dn2;
				nlist = Append(nlist, MkList(mka(dn)));
			}
			nmat = Append(nmat, MkList(nlist));
		}			


		Node* env = Nil->Cons(Nil);

		SetEnv(env, nvar);
		((Undef*)(nvar->Val()))->Set(nmat);

		PushStack(cx, Nil, Nil, env);

		delete [] d1;
		return 1;

	}

	syserr("divscalar: failed in the evaluation of the argument. \n");
	return 0;
}

int matrix_det(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <det VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("det: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <det VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("det: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <det VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <det VAR LIST>\n");
		return 0;
	}

	if (row != column) {
		delete [] d1;
		syserr("det: not a square matrix\n");
		return 0;
	}

	long double dn;
	int i,j,k;
	for (i = 0; i < column; i++) {
		for (j = 0; j < row; j++) {
			if (pivot(d1, i, row, column)) {
				if (fabsl(d1[i*column+i]) < EPS) {
					delete [] d1;
					syserr("det: zero divide\n");
					return 0;
				}
			}
				
			if (i < j) {
				dn = d1[j*column+i]/d1[i*column+i];
				for(k = 0; k < row; k++){
					d1[j*column+k] -= dn * d1[i*column+k];
				}
			}
		}
	}			

	long double det = 1;
	for(i=0; i < row; i++){
		det *= d1[i*column+i];
	}
	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(mka(det));

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}


int matrix_inv(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <inv VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("inv: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <inv VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("inv: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <inv VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <inv VAR LIST>\n");
		return 0;
	}

	if (row != column) {
		delete [] d1;
		syserr("inv: not a square matrix\n");
		return 0;
	}

	long double dn;
	long double* d2 = new long double[row*column];
	int i,j,k;
	
	for (i = 0; i < row; i++) {
	    for (j = 0; j < column; j++) {
	    	if (i == j) {
			d2[i*column+j] = 1.0L;
		} else {
			d2[i*column+j] = 0.0L;
		}
	    }
	}

	for (i = 0; i < row; i++) {
		dn = d1[i*column+i];
		if (fabsl(dn) < EPS) {
			delete [] d1;
			delete [] d2;
			syserr("inv: zero divide\n");
			return 0;
		}

		for (j = 0; j < column; j++) {
			d1[i*column+j] /= dn;
			d2[i*column+j] /= dn;
		}
		for (j = 0; j < column; j++) {
			if (i != j) {
				dn = d1[j*column+i];
				for (k = 0; k < column; k++) {
					d1[j*column+k] -= d1[i*column+k]*dn;
					d2[j*column+k] -= d2[i*column+k]*dn;
				}
			}
		}
	}

	Node* nmat2 = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d2[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat2 = Append(nmat2, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat2);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] d2;
	return 1;
}


int matrix_tra(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <transposed VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("transposed: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <transposed VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("transposed: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <transposed VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <transposed VAR LIST>\n");
		return 0;
	}

	long double dn;
	int i,j;
	Node* nmat = Nil;
	for (i = 0; i < column; i++) {
		Node* nlist = Nil;
		for (j = 0; j < row; j++) {
			dn = d1[j*column+i];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}


int matrix_solve(Context* cx, Node* goalscar, List* module) 
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <solve VAR LIST1 LIST2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar1, goalscar, module)) <= 0) {
		syserr("solve: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar1->kind() != UNDEF) {
		syserr("usage: ::matrix <solve VAR LIST1 LIST2>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist1, goalscar, module)) <= 0) {
		syserr("solve: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist1->kind() != LIST) {
		syserr("usage: ::matrix <solve VAR LIST1 LIST2>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist2, goalscar, module)) <= 0) {
		syserr("solve: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist2->kind() != LIST) {
		syserr("usage: ::matrix <solve VAR LIST1 LIST2>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nlist1, row1, column1, d1)) {
		syserr("usage: ::matrix <solve VAR LIST1 LIST2>\n");
		return 0;
	}

	if (row1 != column1) {
		delete [] d1;
		syserr("solve: not a square matrix \n");
		return 0;
	}
	
	int row2, column2;
	long double* d2;
	if (!CheckMatrix(nlist2, row2, column2, d2)) {
		delete [] d1;
		syserr("usage: ::matrix <solve VAR LIST1 LIST2>\n");
		return 0;
	}

	if ((column2 != 1) || (row1 != row2)) {
		delete [] d1;
		delete [] d2;
		syserr("solve: matrix error\n");
		return 0;
	}

	long double* x = new long double[row1*column1];
	if (!solve(x, d1, row1, column1, d2)) {
		delete [] d1;
		delete [] d2;
		delete [] x;
		syserr("solve: no solution\n");
		return 0;
	}

	long double dn;
	int i;

	Node* nmat = Nil;
	Node* nlist = Nil;
	for (i = 0; i < row2; i++) {
		dn = x[i];
		nlist = Append(nlist, MkList(mka(dn)));
	}			
	nmat = MkList(nlist);

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar1);
	((Undef*)(nvar1->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] d2;
	delete [] x;
	return 1;
}

int matrix_eigen(Context* cx, Node* goalscar, List* module) 
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <eigen VARLIST VARVAL LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar1, goalscar, module)) <= 0) {
		syserr("eigen: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar1->kind() != UNDEF) {
		syserr("usage: ::matrix <eigen VARLIST VARVAL LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nvar2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar2, goalscar, module)) <= 0) {
		syserr("eigen: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar2->kind() != UNDEF) {
		syserr("usage: ::matrix <eigen VARLIST VARVAL LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist1, goalscar, module)) <= 0) {
		syserr("eigen: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist1->kind() != LIST) {
		syserr("usage: ::matrix <eigen VARLIST VARVAL LIST>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nlist1, row1, column1, d1)) {
		syserr("usage: ::matrix <eigen VARLIST VARVAL LIST>\n");
		return 0;
	}

	if (row1 != column1) {
		delete [] d1;
		syserr("eigen: not a square matrix \n");
		return 0;
	}
	
	long double* x = new long double[row1];
	long double eval;

	if (!eigenvalue(x, eval, d1, row1)) {
		delete [] d1;
		delete [] x;
		syserr("eigen: no solution\n");
		return 0;
	}

	long double dn;
	int i;

	Node* nmat = Nil;
	Node* nlist = Nil;
	for (i = 0; i < row1; i++) {
		dn = x[i];
		nlist = Append(nlist, MkList(mka(dn)));
	}			
	nmat = MkList(nlist);

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar1);
	((Undef*)(nvar1->Val()))->Set(nmat);

	SetEnv(env, nvar2);
	((Undef*)(nvar2->Val()))->Set(mka(eval));

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] x;
	return 1;
}


int matrix_dimentions(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <size VARROW VARCOLUMN LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvarrow = g->Car()->Val();
	if ((rn = FuncArg(cx, nvarrow, goalscar, module)) <= 0) {
		syserr("divscalar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvarrow->kind() != UNDEF) {
		syserr("usage: ::matrix <size VARROW VARCOLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nvarcolumn = g->Car()->Val();
	if ((rn = FuncArg(cx, nvarcolumn, goalscar, module)) <= 0) {
		syserr("divscalar: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvarcolumn->kind() != UNDEF) {
		syserr("usage: ::matrix <size VARROW VARCOLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("size: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <size VARROW VARCOLUMN LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <size VARROW VARCOLUMN LIST>\n");
		return 0;
	}

	
	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvarrow);
	((Undef*)(nvarrow->Val()))->Set(mka((long long)row));

	SetEnv(env, nvarcolumn);
	((Undef*)(nvarcolumn->Val()))->Set(mka((long long)column));

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}

int matrix_getrow(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <getrow VAR ROW LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("getrow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <getrow VAR ROW LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum, goalscar, module)) <= 0) {
		syserr("getrow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum->kind() != ATOM) {
		syserr("usage: ::matrix <getrow VAR ROW LIST>\n");
		return 0;
	}

	long long rownum;
	if (!((Atom*)nrownum)->toInt(rownum)) {
		syserr("usage: ::matrix <getrow VAR ROW LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("getrow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <getrow VAR ROW LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <getrow VAR ROW LIST>\n");
		return 0;
	}

	if ((rownum < 0) || (rownum >= row)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	long double dn;
	int i;
	Node* nmat = Nil;
	for (i = 0; i < column; i++) {
		dn = d1[rownum*column+i];
		nmat = Append(nmat, MkList(mka(dn)));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}

int matrix_getcolumn(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <getcolumn VAR COLUMN LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("getcolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <getcolumn VAR COLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum, goalscar, module)) <= 0) {
		syserr("getcolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum->kind() != ATOM) {
		syserr("usage: ::matrix <getcolumn VAR COLUMN LIST>\n");
		return 0;
	}

	long long columnnum;
	if (!((Atom*)ncolumnnum)->toInt(columnnum)) {
		syserr("usage: ::matrix <getcolumn VAR COLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("getcolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <getcolumn VAR COLUMN LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <getcolumn VAR COLUMN LIST>\n");
		return 0;
	}

	if ((columnnum < 0) || (columnnum >= column)) {
		delete [] d1;
		syserr("The specification range of column is an error\n");
		return 0;
	}
	
	long double dn;
	int i;
	Node* nmat = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		dn = d1[i*column+columnnum];
		nlist = MkList(mka(dn));
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}

int matrix_getrow_column(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 4) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("get: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum, goalscar, module)) <= 0) {
		syserr("get: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum->kind() != ATOM) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	long long rownum;
	if (!((Atom*)nrownum)->toInt(rownum)) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum, goalscar, module)) <= 0) {
		syserr("get: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum->kind() != ATOM) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	long long columnnum;
	if (!((Atom*)ncolumnnum)->toInt(columnnum)) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("get: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <getval VAR ROW COLUMN LIST>\n");
		return 0;
	}

	if ((rownum < 0) || (rownum >= row)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	if ((columnnum < 0) || (columnnum >= column)) {
		delete [] d1;
		syserr("The specification range of column is an error\n");
		return 0;
	}
	
	long double dn;

	dn = d1[rownum*column+columnnum];

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(mka(dn));

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}

int matrix_setrow_column(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 5) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum->kind() != ATOM) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	long long rownum;
	if (!((Atom*)nrownum)->toInt(rownum)) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum->kind() != ATOM) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	long long columnnum;
	if (!((Atom*)ncolumnnum)->toInt(columnnum)) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nvalnum = g->Car()->Val();
	if ((rn = FuncArg(cx, nvalnum, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvalnum->kind() != ATOM) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	long long valnum;
	if (!((Atom*)nvalnum)->toInt(valnum)) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <setval VAR ROW COLUMN VAL LIST>\n");
		return 0;
	}

	if ((rownum < 0) || (rownum >= row)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	if ((columnnum < 0) || (columnnum >= column)) {
		delete [] d1;
		syserr("The specification range of column is an error\n");
		return 0;
	}
	
	d1[rownum*column+columnnum] = valnum;

	long double dn;
	int i,j;
	Node* nmat = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}



int matrix_swaprow(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 4) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("swaprow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum1, goalscar, module)) <= 0) {
		syserr("swaprow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum1->kind() != ATOM) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	long long rownum1;
	if (!((Atom*)nrownum1)->toInt(rownum1)) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum2, goalscar, module)) <= 0) {
		syserr("swaprow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum2->kind() != ATOM) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	long long rownum2;
	if (!((Atom*)nrownum2)->toInt(rownum2)) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("swaprow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <swaprow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	if ((rownum1 < 0) || (rownum1 >= row) || 
		(rownum2 < 0) || (rownum2 >= row)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	long double dn;
	int i, j;
	for (i = 0; i < column; i++) {
		dn = d1[rownum1*column+i];
		d1[rownum1*column+i] = d1[rownum2*column+i];
		d1[rownum2*column+i] = dn;
	}			

	Node* nmat = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}

int matrix_swapcolumn(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 4) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("swapcolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum1 = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum1, goalscar, module)) <= 0) {
		syserr("swapcolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum1->kind() != ATOM) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	long long columnnum1;
	if (!((Atom*)ncolumnnum1)->toInt(columnnum1)) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum2 = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum2, goalscar, module)) <= 0) {
		syserr("swapcolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum2->kind() != ATOM) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	long long columnnum2;
	if (!((Atom*)ncolumnnum2)->toInt(columnnum2)) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("swapcolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <swapcolumn VAR COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	if ((columnnum1 < 0) || (columnnum1 >= column) || 
		(columnnum2 < 0) || (columnnum2 >= column)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	long double dn;
	int i, j;
	for (i = 0; i < row; i++) {
		dn = d1[i*column+columnnum1];
		d1[i*column+columnnum1] = d1[i*column+columnnum2];
		d1[i*column+columnnum2] = dn;
	}			

	Node* nmat = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}




int matrix_rangerow(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 4) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("rangerow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum1, goalscar, module)) <= 0) {
		syserr("rangerow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum1->kind() != ATOM) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	long long rownum1;
	if (!((Atom*)nrownum1)->toInt(rownum1)) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum2, goalscar, module)) <= 0) {
		syserr("rangerow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum2->kind() != ATOM) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	long long rownum2;
	if (!((Atom*)nrownum2)->toInt(rownum2)) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("rangerow: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <rangerow VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	if ((rownum1 < 0) || (rownum1 >= row) || 
			(rownum2 < 0) || (rownum2 >= row)
			|| (rownum1 >= rownum2)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	long double dn;
	int i, j;

	Node* nmat = Nil;
	for (i = rownum1; i <= rownum2; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}

int matrix_rangecolumn(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 4) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("rangecolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum1 = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum1, goalscar, module)) <= 0) {
		syserr("rangecolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum1->kind() != ATOM) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	long long columnnum1;
	if (!((Atom*)ncolumnnum1)->toInt(columnnum1)) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum2 = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum2, goalscar, module)) <= 0) {
		syserr("rangecolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum2->kind() != ATOM) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	long long columnnum2;
	if (!((Atom*)ncolumnnum2)->toInt(columnnum2)) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("rangecolumn: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <rangecolumn VAR ROW1 ROW2 LIST>\n");
		return 0;
	}

	if ((columnnum1 < 0) || (columnnum1 >= row) || 
			(columnnum2 < 0) || (columnnum2 >= row)
			|| (columnnum1 >= columnnum2)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	long double dn;
	int i, j;

	Node* nmat = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = columnnum1; j <= columnnum2; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}


int matrix_range(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 6) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("range: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum1, goalscar, module)) <= 0) {
		syserr("range: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum1->kind() != ATOM) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	long long rownum1;
	if (!((Atom*)nrownum1)->toInt(rownum1)) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrownum2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nrownum2, goalscar, module)) <= 0) {
		syserr("range: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrownum2->kind() != ATOM) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	long long rownum2;
	if (!((Atom*)nrownum2)->toInt(rownum2)) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum1 = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum1, goalscar, module)) <= 0) {
		syserr("range: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum1->kind() != ATOM) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	long long columnnum1;
	if (!((Atom*)ncolumnnum1)->toInt(columnnum1)) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumnnum2 = g->Car()->Val();
	if ((rn = FuncArg(cx, ncolumnnum2, goalscar, module)) <= 0) {
		syserr("range: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumnnum2->kind() != ATOM) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	long long columnnum2;
	if (!((Atom*)ncolumnnum2)->toInt(columnnum2)) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("range: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <range VAR ROW1 ROW2 COLUMN1 COLUMN2 LIST>\n");
		return 0;
	}

	if ((rownum1 < 0) || (rownum1 >= row) || 
			(rownum2 < 0) || (rownum2 >= row)
			|| (rownum1 >= rownum2)) {
		delete [] d1;
		syserr("The specification range of row is an error\n");
		return 0;
	}
	
	if ((columnnum1 < 0) || (columnnum1 >= column) || 
			(columnnum2 < 0) || (columnnum2 >= column)
			|| (columnnum1 >= columnnum2)) {
		delete [] d1;
		syserr("The specification range of column is an error\n");
		return 0;
	}
	
	long double dn;
	int i, j;

	Node* nmat = Nil;
	for (i = rownum1; i <= rownum2; i++) {
		Node* nlist = Nil;
		for (j = columnnum1; j <= columnnum2; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			


	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	return 1;
}


int matrix_random(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 3) {
		syserr("usage: ::matrix <random VAR ROW COLUMN>\n");
		return 0;
	}

	Node* g    = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("random: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <random VAR ROW COLUMN>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nrow = g->Car()->Val();
	if ((rn = FuncArg(cx, nrow, goalscar, module)) <= 0) {
		syserr("random: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nrow->kind() != ATOM) {
		syserr("usage: ::matrix <random VAR ROW COLUMN>\n");
		return 0;
	}

	long long row;
	((Atom*)nrow)->toInt(row);
	if (row <= 0) {
		syserr("usage: ::matrix <random VAR ROW COLUMN>\n");
		return 0;
	}

	g = g->Cdr();
	Node* ncolumn = g->Car()->Val();

	if ((rn = FuncArg(cx, ncolumn, goalscar, module)) <= 0) {
		syserr("random: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (ncolumn->kind() != ATOM) {
		syserr("usage: ::matrix <random ROW COLUMN>\n");
		return 0;
	}

	long long column;
	((Atom*)ncolumn)->toInt(column);
	if (row <= 0) {
		syserr("usage: ::matrix <random VAR ROW COLUMN>\n");
		return 0;
	}

	int	i, j;
	Node*	nmat=Nil;
	
	for (i=0; i < row; i++) {
		Node* nlist = Nil;
		for (j=0; j < column; j++) {
			long long rd;
#ifndef __MINGW32__
			rd = (long long)random();
#else
			rd = (long long)rand();
#endif /* __MINGW32__ */

			nlist = Append(nlist, MkList(mka(rd)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);
	return 1;

}

int matrix_fourier(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <fourier VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("fourier: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <fourier VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("fourier: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <fourier VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <fourier VAR LIST>\n");
		return 0;
	}

	if (row != 2) {
		delete [] d1;
		syserr("row is not 2");
		return 0;
	}

	long double* d2 = new long double[column];
	long double* d3 = new long double[column];

	fourier(column, d1, d1+column, d2, d3);
	
	long double dn;
	int i;
	Node* nmat = Nil;
	Node* nresult = Nil;
	for (i = 0; i < column; i++) {
		dn = d2[i];
		nresult = Append(nresult, MkList(mka(dn)));
	}			

	nmat = Append(nmat, MkList(nresult));

	nresult = Nil;
	for (i = 0; i < column; i++) {
		dn = d3[i];
		nresult = Append(nresult, MkList(mka(dn)));
	}			

	nmat = Append(nmat, MkList(nresult));
	

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] d2;
	delete [] d3;
	return 1;
}

int matrix_invfourier(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <invfourier VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("invfourier: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <invfourier VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("invfourier: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <invfourier VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <invfourier VAR LIST>\n");
		return 0;
	}

	if (row != 2) {
		delete [] d1;
		syserr("row is not 2");
		return 0;
	}

	long double* d2 = new long double[column];
	long double* d3 = new long double[column];

	inverse_fourier(column, d1, d1+column, d2, d3);
	
	long double dn;
	int i;
	Node* nmat = Nil;
	Node* nresult = Nil;
	for (i = 0; i < column; i++) {
		dn = d2[i];
		nresult = Append(nresult, MkList(mka(dn)));
	}			

	nmat = Append(nmat, MkList(nresult));

	nresult = Nil;
	for (i = 0; i < column; i++) {
		dn = d3[i];
		nresult = Append(nresult, MkList(mka(dn)));
	}			

	nmat = Append(nmat, MkList(nresult));
	

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;
	delete [] d2;
	delete [] d3;
	return 1;
}


int matrix_row_sort_ascending(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	long double dn;
	int i, j, k;
	for (i=0; i < row-1; i++) {
		for (j = i+1; j < row; j++) {
			if (d1[i*column] > d1[j*column]) {
				for (k = 0; k < column; k++) {
					dn = d1[i*column+k];
					d1[i*column+k] = d1[j*column+k];
					d1[j*column+k] = dn;
				}
			}
		}
	}

	Node* nmat = Nil;

	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;

	return 1;
}

int matrix_row_sort_descending(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	long double dn;
	int i, j, k;
	for (i=0; i < row-1; i++) {
		for (j = i+1; j < row; j++) {
			if (d1[i*column] < d1[j*column]) {
				for (k = 0; k < column; k++) {
					dn = d1[i*column+k];
					d1[i*column+k] = d1[j*column+k];
					d1[j*column+k] = dn;
				}
			}
		}
	}

	Node* nmat = Nil;

	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;

	return 1;
}

int matrix_column_sort_ascending(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	long double dn;
	int i, j, k;
	for (i=0; i < column-1; i++) {
		for (j = i+1; j < column; j++) {
			if (d1[i] > d1[j]) {
				for (k = 0; k < row; k++) {
					dn = d1[k*column+i];
					d1[k*column+i] = d1[k*column+j];
					d1[k*column+j] = dn;
				}
			}
		}
	}

	Node* nmat = Nil;

	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;

	return 1;
}

int matrix_column_sort_descending(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("RowSortAscendig: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <RowSortAscendig VAR LIST>\n");
		return 0;
	}

	long double dn;
	int i, j, k;
	for (i=0; i < column-1; i++) {
		for (j = i+1; j < column; j++) {
			if (d1[i] < d1[j]) {
				for (k = 0; k < row; k++) {
					dn = d1[k*column+i];
					d1[k*column+i] = d1[k*column+j];
					d1[k*column+j] = dn;
				}
			}
		}
	}

	Node* nmat = Nil;

	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d1[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat = Append(nmat, MkList(nlist));
	}			

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat);

	PushStack(cx, Nil, Nil, env);

	delete [] d1;

	return 1;
}



int matrix_equal(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <equal LIST1 LIST2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nmat1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat1, goalscar, module)) <= 0) {
		syserr("equal: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat1->kind() != LIST) {
		syserr("usage: ::matrix <equal LIST1 LIST2>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nmat1, row1, column1, d1)) {
		syserr("usage: ::matrix <equal LIST1 LIST2>\n");
		return 0;
	}

	g=g->Cdr();
	Node* nmat2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
		delete [] d1;
		syserr("equal: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat2->kind() != LIST) {
		delete [] d1;
		syserr("usage: ::matrix <equal LIST1 LIST2>\n");
		return 0;
	}

	int row2, column2;
	long double* d2;
	if (!CheckMatrix(nmat2, row2, column2, d2)) {
		delete [] d1;
		syserr("usage: ::matrix <equal LIST1 LIST2>\n");
		return 0;
	}

	if ((row1 != row2) || (column1 != column2)) {
		delete [] d1;
		delete [] d2;
		return -1;
	}

	int i,j;

	for (i=0; i < row1; i++) {
		for (j=0; j < column1; j++) {
			if (d1[i*column1+j] != d2[i*column1+j]) {
				delete [] d1;
				delete [] d2;
				return -1;
			}
		}
	}			


	delete [] d1;
	delete [] d2;
	return 1;
}

int matrix_notequal(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <notequal LIST1 LIST2>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nmat1 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat1, goalscar, module)) <= 0) {
		syserr("notequalt: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat1->kind() != LIST) {
		syserr("usage: ::matrix <notequal LIST1 LIST2>\n");
		return 0;
	}

	int row1, column1;
	long double* d1;
	if (!CheckMatrix(nmat1, row1, column1, d1)) {
		syserr("usage: ::matrix <notequal LIST1 LIST2>\n");
		return 0;
	}

	g=g->Cdr();
	Node* nmat2 = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat2, goalscar, module)) <= 0) {
		delete [] d1;
		syserr("notequalt: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat2->kind() != LIST) {
		delete [] d1;
		syserr("usage: ::matrix <notequal LIST1 LIST2>\n");
		return 0;
	}

	int row2, column2;
	long double* d2;
	if (!CheckMatrix(nmat2, row2, column2, d2)) {
		delete [] d1;
		syserr("usage: ::matrix <notequal LIST1 LIST2>\n");
		return 0;
	}

	if ((row1 != row2) || (column1 != column2)) {
		delete [] d1;
		delete [] d2;
		return 1;
	}

	int i,j;

	for (i=0; i < row1; i++) {
		for (j=0; j < column1; j++) {
			if (d1[i*column1+j] != d2[i*column1+j]) {
				delete [] d1;
				delete [] d2;
				return 1;
			}
		}
	}			


	delete [] d1;
	delete [] d2;
	return -1;
}


int matrix_ismatrix(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <ismatrix LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("ismatrix: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <ismatrix LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		return -1;
	}

	delete [] d1;
	
	return 1;

}

int matrix_isvector(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <isvector LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("isvector: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <isvector LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		return -1;
	}

	delete [] d1;

	if ((row != 1) && (column != 1)) {
		return -1;
	}
			
	return 1;

}

int matrix_issquare(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <issquare LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("issquare: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <issquare LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		return -1;
	}

	delete [] d1;

	if (row != column) {
		return -1;
	}
			
	return 1;

}

int matrix_isnull(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <isnull LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("isnull: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <isnull LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <isnull LIST>\n");
		return 0;
	}

	int i,j;

	for (i = 0; i < row; i++) {
		for (j = 0; j < column; j++) {
			if (fabsl(d1[i*column+j]) > EPS) {
				delete [] d1;
				return -1;
			}
		}
	}
			
	delete [] d1;
	return 1;

}

int matrix_isdiagonal(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <isdiagonal LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("isdiagonal: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <isdiagonal LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <isdiagonal LIST>\n");
		return 0;
	}

	if (row != column) {
		delete [] d1;
		syserr("isdiagonal: not a square matrix\n");
		return 0;
	}
	
	int i,j;
	for (i = 0; i < row; i++) {
		for (j = 0; j < column; j++) {
			if (i != j) {
				if (fabsl(d1[i*column+j]) > EPS) {
					delete [] d1;
					return -1;
				}
			} else {
				if (fabsl(d1[i*column+j]) <= EPS) {
					delete [] d1;
					return -1;
				}
			}
		}
	}
			
	delete [] d1;
	return 1;

}

int matrix_issymmetric(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <issymmetric LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;
	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("issymmetric: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <issymmetric LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <issymmetric LIST>\n");
		return 0;
	}

	if (row != column) {
		delete [] d1;
		syserr("issymmetric: not a square matrix\n");
		return 0;
	}
	
	int i,j;
	for (i = 0; i < row; i++) {
		for (j = i; j < column; j++) {
			if (d1[i*column+j] != d1[j*column+i]) {
					delete [] d1;
					return -1;
			}
		}
	}
			
	delete [] d1;
	return 1;

}


int matrix_isregular(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <isregular LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("isregular: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <isregular LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <isregular LIST>\n");
		return 0;
	}

	if (row != column) {
		delete [] d1;
		return -1;
	}

	long double dn;
	long double* d2 = new long double[row*column];
	int i,j,k;
	
	for (i = 0; i < column; i++) {
	    for (j = 0; j < row; j++) {
	    	if (i == j) {
			d2[i*column+j] = 1.0L;
		} else {
			d2[i*column+j] = 0.0L;
		}
	    }
	}

	for (i = 0; i < row; i++) {
		dn = d1[i*column+i];
		if (fabsl(dn) < EPS) {
			delete [] d1;
			delete [] d2;
			return -1;
		}

		for (j = 0; j < column; j++) {
			d1[i*column+j] /= dn;
			d2[i*column+j] /= dn;
		}
		for (j = 0; j < column; j++) {
			if (i != j) {
				dn = d1[j*column+i];
				for (k = 0; k < column; k++) {
					d1[j*column+k] -= (d1[i*column+k] * dn);
					d2[j*column+k] -= (d2[i*column+k] * dn);
				}
			}
		}
	}

	Node* nmat2 = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d2[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat2 = Append(nmat2, MkList(nlist));
	}			

	delete [] d1;
	delete [] d2;

	return 1;
}

int matrix_issingular(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 1) {
		syserr("usage: ::matrix <issingular LIST>\n");
		return 0;
	}

	Node* g = goalscar->Cdr()->Val();

	int rn;

	Node* nlist = g->Car()->Val();
	if ((rn = FuncArg(cx, nlist, goalscar, module)) <= 0) {
		syserr("issingular: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nlist->kind() != LIST) {
		syserr("usage: ::matrix <issingular LIST>\n");
		return 0;
	}

	int row, column;
	long double* d1;
	if (!CheckMatrix(nlist, row, column, d1)) {
		syserr("usage: ::matrix <issingular LIST>\n");
		return 0;
	}

	if (row != column) {
		delete [] d1;
		return 1;
	}

	long double dn;
	long double* d2 = new long double[row*column];
	int i,j,k;
	
	for (i = 0; i < column; i++) {
	    for (j = 0; j < row; j++) {
	    	if (i == j) {
			d2[i*column+j] = 1.0L;
		} else {
			d2[i*column+j] = 0.0L;
		}
	    }
	}

	for (i = 0; i < row; i++) {
		dn = d1[i*column+i];
		if (fabsl(dn) < EPS) {
			delete [] d1;
			delete [] d2;
			return 1;
		}

		for (j = 0; j < column; j++) {
			d1[i*column+j] /= dn;
			d2[i*column+j] /= dn;
		}
		for (j = 0; j < column; j++) {
			if (i != j) {
				dn = d1[j*column+i];
				for (k = 0; k < column; k++) {
					d1[j*column+k] -= (d1[i*column+k] * dn);
					d2[j*column+k] -= (d2[i*column+k] * dn);
				}
			}
		}
	}

	Node* nmat2 = Nil;
	for (i = 0; i < row; i++) {
		Node* nlist = Nil;
		for (j = 0; j < column; j++) {
			dn = d2[i*column+j];
			nlist = Append(nlist, MkList(mka(dn)));
		}
		nmat2 = Append(nmat2, MkList(nlist));
	}			

	delete [] d1;
	delete [] d2;

	return -1;
}

int matrix_copy(Context* cx, Node* goalscar, List* module)
{
	if (ListLength(goalscar->Cdr()) != 2) {
		syserr("usage: ::matrix <copy VAR MATRIX>\n");
		return 0;
	}

	Node* g    = goalscar->Cdr()->Val();

	int rn;

	Node* nvar = g->Car()->Val();
	if ((rn = FuncArg(cx, nvar, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nvar->kind() != UNDEF) {
		syserr("usage: ::matrix <copy VAR MATRIX>\n");
		return 0;
	}

	g = g->Cdr();
	Node* nmat = g->Car()->Val();
	if ((rn = FuncArg(cx, nmat, goalscar, module)) <= 0) {
		syserr("set: failed in the evaluation of the argument. \n");
		return 0;
	}

	if (nmat->kind() != LIST) {
		syserr("usage: ::matrix <copy VAR MATRIX>\n");
		return 0;
	}

	Node* nmat2 = Dup(nmat);

	Node* env = Nil->Cons(Nil);

	SetEnv(env, nvar);
	((Undef*)(nvar->Val()))->Set(nmat2);

	PushStack(cx, Nil, Nil, env);
	return 1;
}


