/**********************************************************************
 
	Copyright (C) 2005- Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	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.

**********************************************************************/

#include	"init.h"
#include	"memory_debug.h"
#include	"mxmap.h"


#define ESTIMATING_MIN	100
//#define ESTIMATING_MIN	5
#define BUF_SIZE	1000
#define MAX_DIST	3
#define TREE_LIMIT	10000

#define DERIM(p)	\
		((p) == ' ' || (p) == '\t' || \
		(p) == '\n' || (p) == '\r')

int handling_hem(MATRIX *,int,int);
void handling_hem_2(MATRIX *,INTEGER64*,int);
void insert_polation_list(MXMAP_LIST * t,INTEGER64 * t1,int * t2);
void setup_mxmap(MXMAP_LIST * t);
void
distance_and_data(double ** rp,INTEGER64 * dist,
		MXMAP_LIST * t,INTEGER64 * target);
void mem_test();

int time_count;
int invalid_command;
int src_dim,dest_dim;
INTEGER64 * margin;
INTEGER64 * index_offset;
double dest_lock_min,dest_lock_max;
double * offset;
double * pitch;
INTEGER64 * pixel_size;
int data_start;
char ** data_type;
char * std_data_type;
INTEGER64 * min,* max;
INTEGER64 * dc_min,* dc_max;
double * dest_max, * dest_min;
char * dest_minmax_bit;
MATRIX * mtx;
MX_CACHE write_c,read_c,write_delta_c,write_rr_c,write_hem_c;
MATRIX_DH_SET avg_mtx;

void * src_mtx;
MATRIX_DH_SET src_mtx_ds;
double * src_mtx_ptr;
void * sd_mtx;
MATRIX_DH_SET  sd_mtx_ds;
double * sd_mtx_ptr;


void
check_bittest(MATRIX * m,INTEGER64 * dim_code,void * d,char * msg);

extern int _debug_flag;
extern int NC_flag;
int mem_dbg_flag;

int default_pri[] = {
	0,0,0,
	PR_UP + 0x2000000,
	PR_UP + 0x2000000,
	PR_UP + 0x2000000,
	
	PR_UP + 0x2000000,
	PR_UP + 0x2000000,
	PR_UP + 0x2000000,
	
	0,0,0,
	0,0,0,
	
	PR_UP + 0x2000000,
	PR_UP + 0x2000000,
	PR_UP + 0x2000000,
	
	0,0,0,
	
	PR_STRT + 0x2000000,
	PR_STRT + 0x2000000,
	PR_STRT + 0x2000000
};

char * sv_fetch_1[] = {
	"<mxFinish",
	"	err-jump-status=\"MS_LOADING_ERR_1\"",
	"	normal-jump-status=\"MS_OK\"/>",
	"<mxLoad target=\"file\"/>",
	0
};

char ** mcd_server[] = {
	0,0,0,					// DEF
	sv_fetch_1,sv_fetch_1,sv_fetch_1,	// FETCH_1
	0,0,0,					// FETCH_2
	0,0,0,					// EDIT_!
	0,0,0,					// EDIT_2
	0,0,0,					// VISU_1
	0,0,0,					// VISU_2
	0,0,0					// SAVE
};



char * cl_fetch_1[] = {
	"<mxFinish",
	"	err-jump=\"MS_FETCH_2\"",
	"	normal-jump-status=\"MS_OK\"/>",
	"<mxLoad target=\"file\"/>",
	0
};

char * cl_fetch_2[] = {
	"<mxFinish",
	"	normal-jump=\"MI_VISU_1\"",
	"	err-jump-status=\"MS_LOADING_ERR_1\"/>",
	"<mxLoad target=\"net\"/>",
	0
};


char * cl_visu_1_bt[] = {
	"<mxFinish",
	"	normal-jump-status=\"MS_OK\"",
	"	err-jump-status=\"MS_PROCESS_ERR_1\"/>",
	"<Define> ^d (mxSeparate ([mxUncompressZ] (mxCH 8))) </Define>",
	"<mxSet> 10 (car d) </mxSet>",
	"<set> ^d (cdr d) </set>",

	"<Let>",
	"<Sub>",
	"	<ch> 12 </ch>",
	"</Sub>",

	"<For dec=\"d\">",
	"	<mxSet> ch (mxStuffing (car d) ([mxCH type=\"parent\"] ch))</mxSet>",
	"	<set> ^ch (+ ch 1) </set>",
	"</For>",
	"</Let>",
	"<mxSet> 11 (mxmapResolutionRate 12 dest-dim) </mxSet>",
	0
};


char * cl_visu_1_tp[] = {
	"<mxFinish",
	"	normal-jump-status=\"MS_OK\"",
	"	err-jump-status=\"MS_PROCESS_ERR_1\"/>",
	"<Define> ^d (mxSeparate ([mxUncompressZ] (mxCH 8))) </Define>",
	"<mxSet> 10 (car d) </mxSet>",
	"<set> ^d (cdr d) </set>",

	"<Let>",
	"<Sub>",
	"	<ch> 12 </ch>",
	"</Sub>",

	"<For dec=\"d\">",
	"	<mxSet> ch (car d) </mxSet>",
	"	<set> ^ch (+ ch 1) </set>",
	"</For>",
	"</Let>",

	"<mxSet> 11 (mxmapResolutionRate 12 dest-dim) </mxSet>",
	0
};

char * cl_save[] = {
	"<mxSave/>",
	0,
};

char ** mcd_client[] = {
	0,0,0,					// DEF
	cl_fetch_1,cl_fetch_1,cl_fetch_1,	// FETCH_1
	cl_fetch_2,cl_fetch_2,cl_fetch_2,	// FETCH_2
	0,0,0,					// EDIT_!
	0,0,0,					// EDIT_2
	cl_visu_1_bt,cl_visu_1_bt,cl_visu_1_tp,	// VISU_1
	0,0,0,					// VISU_2
	cl_save,cl_save,cl_save,		// SAVE
};

double
convert_data(double inp,char * src,char * dest)
{
int r;
int sign;
int deg,min;
double ret;
	if ( strcmp(src,dest) == 0 )
		return inp;
	if ( strcmp(src,"ddmmss.s") == 0 ) {
		if ( strcmp(dest,"degree") == 0 ) {
			if ( inp < 0 ) {
				sign = -1;
				inp = - inp;
			}
			else	sign = 1;
			r = inp;
			deg = r / 10000;
			min = (inp - deg*10000) / 100;
			ret = inp - (deg*10000 + min*100);
			return sign*(deg + ((double)min)/60 + ret/3600);
		}
	}
	else if ( strcmp(src,"degree") == 0 ) {
		if ( strcmp(dest,"ddmmss.s") == 0 ) {
			if ( inp < 0 ) {
				sign = -1;
				inp = - inp;
			}
			else	sign = 1;
			deg = inp;
			inp = (inp - deg)*60;
			min = inp;
			inp = (inp - min)*60;
			return sign*(deg*10000 + min*100 + inp);
		}
	}
	else if ( strcmp(src,"cm") == 0 ) {
		if ( strcmp(dest,"m") == 0 )
			return inp/100;
		else if ( strcmp(dest,"km") == 0 )
			return inp/100000;
	}
	else if ( strcmp(src,"m") == 0 ) {
		if ( strcmp(dest,"cm") == 0 )
			return inp*100;
		else if ( strcmp(dest,"km") == 0 )
			return inp/1000;
	}
	else if ( strcmp(src,"km") == 0 ) {
		if ( strcmp(dest,"cm") == 0 )
			return inp*100000;
		else if ( strcmp(dest,"m") == 0 )
			return inp*1000;
	}
	else {
		fprintf(stderr,"cannot convert %s\n",src);
		exit(1);
	}
	fprintf(stderr,"cannot convert dest %s\n",dest);
	exit(1);
	return 0;
}

int
read_file(char * filename,int (*func)(char*))
{
FILE * fd;
char buffer[BUF_SIZE];
char * s;
char cmd[10][10];
int size;
double dd;
int line;
int i;
int t;
	fd = fopen(filename,"r+");
	if ( fd == 0 ) {
		fprintf(stderr,"cannot open the file %s",filename);
		exit(1);
	}
	line = 1;
	for ( ; ; ) {
		s = fgets(buffer,BUF_SIZE,fd);
		if ( s == 0 )
			break;
		if ( buffer[0] == '\n' ||
			buffer[0] == '\r' ||
			buffer[0] == 0 ) {

			t = get_xltime();
			if ( t != time_count ) {
				time_count = t;
				ss_printf("LINE %i   \n",line);
			}
			line ++;
			continue;
		}
		sscanf(buffer,"%s",cmd[0]);
		if ( cmd[0][0] == '@' ) {
			ss_printf("LINE %i %s",line++,buffer);
			if ( invalid_command )
				continue;

			sscanf(buffer,"%s %s",cmd[0],cmd[1]);

			if ( strcmp(cmd[1],"src-dim") == 0 ) {
				sscanf(buffer,"%s %s %i",cmd[0],cmd[1],
						&src_dim);
				pitch = d_alloc(sizeof(double)*src_dim);
				offset = d_alloc(sizeof(double)*src_dim);
				pixel_size = d_alloc(sizeof(INTEGER64)
							*src_dim);
				data_type = d_re_alloc(
					data_type,
					sizeof(char*)
					*(src_dim + dest_dim + 10));
				margin = d_alloc(sizeof(INTEGER64)*src_dim);
				min = d_alloc(sizeof(INTEGER64)*
						(src_dim+1));
				max = d_alloc(sizeof(INTEGER64)*
						(src_dim+1));
				for ( i = 0 ; i < src_dim ; i ++ )
					min[i] = max[i] = -1;
			}
			else if ( strcmp(cmd[1],"dest-dim") == 0 ) {
				sscanf(buffer,"%s %s %i",cmd[0],cmd[1],
						&dest_dim);
				data_type = d_re_alloc(
					data_type,
					sizeof(char*)
					*(src_dim + dest_dim + 10));
				dest_min = 
					d_alloc(sizeof(double)*dest_dim);
				dest_max = 
					d_alloc(sizeof(double)*dest_dim);
				dest_minmax_bit = d_alloc(dest_dim);
				for ( i = 0 ; i < dest_dim ; i ++ ) {
					dest_min[i] = dest_max[i] = 0;
					dest_minmax_bit[i] = 0;
				}
			}
			else if ( strcmp(cmd[1],"data-start") == 0 )
				sscanf(buffer,"%s %s %i",cmd[0],cmd[1],
						&data_start);
			else if ( strcmp(cmd[1],"data-type") == 0 ) {
				sscanf(buffer,"%s %s %i %s",cmd[0],cmd[1],
						&size,
						cmd[2]);
				data_type[size] = copy_str(cmd[2]);
			}
			else if ( strcmp(cmd[1],"std-data-type") == 0 ) {
				sscanf(buffer,"%s %s %s",cmd[0],cmd[1],
						cmd[2]);
				std_data_type = copy_str(cmd[2]);
			}
			else if ( strcmp(cmd[1],"pitch") == 0 ) {
				sscanf(buffer,"%s %s %s %i %lf",cmd[0],cmd[1],
						cmd[2],
						&size,
						&dd);
				pitch[size] = convert_data(dd,
						cmd[2],std_data_type);
			}
			else if ( strcmp(cmd[1],"margin") == 0 ) {
				sscanf(buffer,"%s %s %i",cmd[0],cmd[1],
						&size);
				sscanf(buffer,"%s %s %i " I64_FORMAT ,
					cmd[0],cmd[1],&size,
					&margin[size]);
			}
			else if ( strcmp(cmd[1],"dest-lock") == 0 ) {
				sscanf(buffer,"%s %s %lf %lf",cmd[0],cmd[1],
					&dest_lock_min,&dest_lock_max);
			}
			else {
				fprintf(stderr,"invalid command %s\n",
					cmd[1]);
				exit(1);
			}
		}
		else {
			t = get_xltime();
			if ( t != time_count ) {
				time_count = t;
				ss_printf("LINE %i   \n",line);
			}
			line ++;
			if ( cmd[0][0] == '#' || cmd[0][0] == 0 || 
				cmd[0][0] == '\n' ||
				cmd[0][0] == '\r' ) {
			}
			else {
				if ( func )
					(*func)(buffer);
			}
		}
	}

	fclose(fd);

	return 0;
}



int
phase_1(char * buf)
{
char * p;
double dd;
int cnt;
int i;
	p = buf;
	cnt = 0;
	for ( ; cnt < data_start ; cnt ++ ) {
		for ( ; *p && DERIM(*p) ; p ++ );
		sscanf(p,"%lf",&dd);
		for ( ; *p && !DERIM(*p) ; p ++ );
	}

	for ( i = 0 ; i < src_dim ; i ++ , cnt ++ ) {
		for ( ; *p && DERIM(*p) ; p ++ );
		sscanf(p,"%lf",&dd);
		for ( ; *p && !DERIM(*p) ; p ++ );
		
		dd = rint(convert_data(dd,
			data_type[cnt],std_data_type)/pitch[i]);
		if ( min[i] == -1 ) {
			min[i] = dd;
			max[i] = dd+1;
		}
		else  {
			if ( min[i] > dd )
				min[i] = dd;
			if ( max[i] < dd+1 )
				max[i] = dd+1;
		}
	}

	return 0;
}

int
phase_2(char * buf)
{
char * p;
double dd;
int cnt;
int i,j;
INTEGER64 * src;
double * dest;
int * ix;
MX_CACHE_PARAM cp;
char bit;
double x,y;

int dl_flag;

	p = buf;
	cnt = 0;
	src = mxc_alloc(&write_c,sizeof(INTEGER64)*(src_dim+1));
	dest = mxc_alloc(&write_c,sizeof(double)*dest_dim);
	ix = mxc_alloc(&write_c,sizeof(int)*src_dim);

	for ( ; cnt < data_start ; cnt ++ ) {
		for ( ; *p && DERIM(*p) ; p ++ );
		sscanf(p,"%lf",&dd);
		for ( ; *p && !DERIM(*p) ; p ++ );
	}

	for ( i = 0 ; i < src_dim ; i ++ , cnt ++ ) {
		for ( ; *p && DERIM(*p) ; p ++ );
		sscanf(p,"%lf",&dd);
		for ( ; *p && !DERIM(*p) ; p ++ );
		dd = rint(convert_data(dd,
			data_type[cnt],std_data_type)/pitch[i]);
		src[i+1] = dd - min[i] + margin[i];
	}
	src[0] = 0;

	dl_flag = 0;
	for ( i = 0 ; i < dest_dim ; i ++ , cnt ++ ) {
		for ( ; *p && DERIM(*p) ; p ++ );
		sscanf(p,"%lf",&dd);
		for ( ; *p && !DERIM(*p) ; p ++ );
		dd = convert_data(dd,
			data_type[cnt],std_data_type);
		if ( dest_lock_min && dd < dest_lock_min )
			goto end;
		if ( dest_lock_max && dd > dest_lock_max )
			goto end;
		dest[i] = dd;
		if ( dest_minmax_bit[i] == 0 ) {
			dest_min[i] = dest_max[i] = dd;
			dest_minmax_bit[i] = 1;
		}
		else {
			if ( dest_min[i] > dd )
				dest_min[i] = dd;
			if ( dest_max[i] < dd )
				dest_max[i] = dd;
		}
	}

	bit = 1;

	cp.c = &write_c;
	cp.dc = src;
	cp.ofs = 0;
	cp.data_ix = mxc_alloc(&write_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	cp.data_ptrs[0] = &bit;
	cp.data_ix[0].x = 0;
	cp.data_ix[0].p = 0;



	cp.data_ptrs[1] = dest;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		cp.data_ix[i+1].x = i;
		cp.data_ix[i+1].p = 1;
	}
	write_mx_cache(&cp);

	for ( i = 0 ; i < src_dim+1 ; i ++ )
		for ( j = 0 ; j < src_dim+1 ; j ++ ) {
			if ( i == src_dim )
				x = 1;
			else	x = src[i+1];
			if ( j == src_dim )
				y = 1;
			else	y = src[j+1];
			src_mtx_ptr[i+(src_dim+1)*j] += x*y;
		}

	for ( i = 0 ; i < src_dim+1 ; i ++ )
		for ( j = 0 ; j < dest_dim+1 ; j ++ ) {
			if ( i == src_dim )
				x = 1;
			else	x = src[i+1];
			if ( j == dest_dim )
				y = 1;
			else	y = dest[j];
			sd_mtx_ptr[i+(src_dim+1)*j] += x*y;
		}
	mxc_free(&write_c,cp.data_ix);
end:
	mxc_free(&write_c,src);
	mxc_free(&write_c,dest);
	mxc_free(&write_c,ix);
	
	return 0;
}


int
extrapolation_hem(MX_CACHE_PARAM * p)
{
MXMAP_LIST tree;
double ** rp;
INTEGER64 * dist;
int ret;
MATRIX * m;
double base;
int i,j,f;

	ret = -1;

	m = p->c->m;

	memset(&tree,0,sizeof(tree));
	tree.m = m;
	tree.infinite = 1;
	setup_mxmap(&tree);

	rp = mxc_alloc(p->c,sizeof(double*)*m->p.dim*2);
	dist = mxc_alloc(p->c,sizeof(INTEGER64)*m->p.dim*2);

	distance_and_data(rp,dist,&tree,p->dc);

	((char*)p->data_ptrs[p->data_ix[0].p])[p->data_ix[0].x] = 1;

	f = 0;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		((double*)p->data_ptrs[p->data_ix[i+1].p])[p->data_ix[i+1].x]
					 = 0;
		base = 0;
		for ( j = 0 ; j < m->p.dim*2 ; j ++ ) {
			if ( dist[j] == 0 )
				continue;
			f = 1;
			((double*)p->data_ptrs[p->data_ix[i+1].p])
				[p->data_ix[i+1].x] += rp[j][i] / dist[j];
			base += 1 / (double)dist[j];
		}
		((double*)p->data_ptrs[p->data_ix[i+1].p])
			[p->data_ix[i+1].x] /= base;
	}
	if ( f == 0 )
		goto finish;
	ret = 0;
finish:
	for ( i = 0; i < m->p.dim*2 ; i ++ )
		if ( rp[i] )
			mxc_free(&read_c,rp[i]);
	mxc_free(p->c,rp);
	mxc_free(p->c,dist);
	return ret;
}

void
handling_hem_2(MATRIX * mtx,INTEGER64 * dc,int ep_flag)
{
MX_CACHE_PARAM p;
char bit;
double * dest;
int i,j;
int hem;
int * target_ix;
int * start_ix;
int * size_ix;
int * inc;
int * ofs;
int * hem_pos;
INTEGER64 dd;
INTEGER64 div,base;
INTEGER64 * read_dc;

/*
int t;

	t = get_xltime();
	if ( t != time_count ) {
		time_count = t;
*/
		ss_printf("HEM(%llx %llx) %s\n",
			mtx->pixel_size[0],
			mtx->pixel_size[1],
			pt_dc(mtx,dc,
			PTDC_NODE_ID));
//	}

	dest = mxc_alloc(&read_c,sizeof(double)*(dest_dim));
	target_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim-1));
	start_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim-1));
	size_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim-1));
	inc = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim-1));
	hem_pos = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	read_dc = mxc_alloc(&read_c,sizeof(INTEGER64)*(mtx->p.dim+1));

	for ( i = 0 ; i < mtx->p.dim-1 ; i ++ ) {
		target_ix[i] = 0;
		start_ix[i] = 0;
		inc[i] = 1;
	}
	for ( i = 0 ; i < mtx->p.dim ; i ++ ) {
		dd = dc[i+1];
		dd &= - (((INTEGER64)1)<<
				(dc[0]*mtx->dim_divide[i]
					+ mtx->block_size[i]));
		dc[i+1] = dd;
		dd = ((INTEGER64)1) << 
			(dc[0]*mtx->dim_divide[i] + mtx->block_size[i]);
		if ( dd + dc[i+1] > mtx->pixel_size[i] ) {
			div = dc[0]*mtx->dim_divide[i];
			base = mtx->pixel_size[i] - dc[i+1];
			hem_pos[i] = base >> div;
			if ( base & ((1<<div)-1) )
				hem_pos[i] ++;
		}
		else	hem_pos[i] =
				((INTEGER64)1) << mtx->block_size[i];
	}


	ofs = mxc_alloc(&read_c,sizeof(int)*mtx->p.dim);
	p.c = &read_c;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;

	p.data_ptrs[1] = dest;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 1;
	}

	for ( hem = 0 ; hem < mtx->p.dim ; hem ++ ) {
		j = 0;
		for ( i = 0 ; i < mtx->p.dim ; i ++ ) {
			if ( i == hem )
				continue;
			target_ix[j] = 0;
			size_ix[j] = hem_pos[i]+1;
			j ++;
		}
		for ( ; ; ) {
			i = 0;
			j = 0;
			
			read_dc[0] = dc[0];
			for ( ; i < mtx->p.dim ; i ++ ) {
				if ( i == hem ) {
					read_dc[i+1] = dc[i+1] +
						(hem_pos[i]<<(dc[0]
						*mtx->dim_divide[i]));
					continue;
				}
				read_dc[i+1] = dc[i+1] 
						+ (target_ix[j]
						<< (dc[0]*mtx->
							dim_divide[i]));
				j ++;
			}
			p.dc = read_dc;
			p.ofs = 0;
			p.c = &read_c;

			if ( read_mx_cache(&p) < 0 ) {
				if ( ep_flag == 0 )
					goto next;
				extrapolation_hem(&p);
			}

			p.dc = dc;
			p.ofs = ofs;
			i = 0;
			j = 0;
			for ( ; i < mtx->p.dim ; i ++ ) {
				p.dc[i+1] = dc[i+1];
				if ( i == hem ) {
					p.ofs[i] = 
						hem_pos[i];
					continue;
				}
				p.ofs[i] = target_ix[j];
				j ++;
			}
			p.c = &write_hem_c;
//ss_printf("WW %i %i - %i %i\n",target_ix[0],size_ix[0],hem_pos[0],hem_pos[1]);
			if ( write_mx_cache(&p) < 0 )
				er_panic("HEM");

		next:
			if( inc_ix(target_ix,start_ix,inc,size_ix,
					mtx->p.dim-1) )
				break;
		}
	}

	mxc_free(&read_c,dest);
	mxc_free(&read_c,target_ix);
	mxc_free(&read_c,start_ix);
	mxc_free(&read_c,size_ix);
	mxc_free(&read_c,inc);

}

int
handling_hem(MATRIX * mtx,int level,int ep_flag)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target;
int f;


	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	target[0] = level;
	f = 0;
	for ( ; ; ) {
		lst = mx_search_level_node(mtx,target,BUF_SIZE);
		if ( lst == 0 )
			break;
		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
			if ( lst == 0 )
				break;
		}
		f = 1;

		for ( ; lst ; ) {
			lst2 = lst->next;

			handling_hem_2(mtx,lst->dc,ep_flag);

			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;
		}
	}
	mxc_free(&read_c,target);
	return 0;
}


void
check_hole(MATRIX * m,INTEGER64 * target,int hem)
{
int i;
int * start_ix;
int * inc;
int * target_ix;
int * size_ix;
char bit;
int er;
MX_CACHE_PARAM p;


	for ( i = 1 ; i <= m->p.dim ; i ++ )
		target[i] &= - (((INTEGER64)1)<<((target[0]*m->dim_divide[i-1])
					+ m->block_size[i-1]));
	target_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	start_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	size_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	inc = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	for ( i = 0 ; i < m->p.dim ; i ++ ) {
		target[i+1] = target[i+1] & (-(1<<(target[0]*m->dim_divide[i] + 
						m->block_size[i])));
		target_ix[i] = 0;
		start_ix[i] = 0;
		inc[i] = 1;
		if ( (target[i+1]>>(target[0]*m->dim_divide[i])) + 
				(1<<m->block_size[i])
				<= m->pixel_size_list[target[0]][i] )
			size_ix[i] = (1<<mtx->block_size[i])+hem;
		else	size_ix[i] =
			m->pixel_size_list[target[0]][i] - 
			(target[i+1]>>(target[0]*m->dim_divide[i])) + hem;
	}
	
	p.c = &read_c;
	p.dc = target;
	p.ofs = target_ix;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;

	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = MXC_INVALID;
		p.data_ix[i+1].p = MXC_INVALID;
	}

	for ( ; ; ) {
		er = read_mx_cache(&p);
		if ( er < 0 ) {
			ss_printf("STOP %s\n",pt_dc(m,target,PTDC_PIXEL_1));
			ss_printf(">>> ");
			for ( i = 0  ; i < m->p.dim ; i ++ )
				ss_printf("%i ",target_ix[i]);
			ss_printf("\n");
			er_panic("check_hole(1)");
		}
		if ( bit == 0 ) {
			ss_printf("STOP %s\n",pt_dc(m,target,PTDC_PIXEL_1));
			ss_printf(">>> ");
			for ( i = 0  ; i < m->p.dim ; i ++ )
				ss_printf("%i ",target_ix[i]);
			ss_printf(" * ");
			for ( i = 0  ; i < m->p.dim ; i ++ )
				ss_printf("%i ",size_ix[i]);
			ss_printf("\n");
			er_panic("check_hole(2)");
		}
		if( inc_ix(target_ix,start_ix,inc,size_ix,
					mtx->p.dim) )
			break;
	}

	mxc_free(&read_c,target_ix);
	mxc_free(&read_c,start_ix);
	mxc_free(&read_c,size_ix);
	mxc_free(&read_c,inc);
}

void
check_hole_all(MATRIX * mtx,int level,int hem)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target;
int f;

	target = d_alloc(sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	if ( level < 0 )
		target[0] = mtx->total_levels - 1;
	else	target[0] = level;
	f = 0;
	for ( ; ; ) {
		ss_printf("Check-Hole-1 %s\n",pt_dc(mtx,target,
			PTDC_NODE_ID));

		lst = mx_search_level_node(mtx,target,BUF_SIZE);

		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
		}
		f = 1;

		if ( lst == 0 ) {
			if ( level >= 0 )
				break;
			target[0] --;
			if ( target[0] < 0 ) {
				target[0] = 0;
				break;
			}
			f = 0;
			memset(&target[1],0,sizeof(INTEGER64)*(mtx->p.dim));
			continue;
		}

		for ( ; lst ; ) {
			lst2 = lst->next;

			check_hole(mtx,lst->dc,hem);

			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;

		}
	}
	d_f_ree(target);
}


void
calc_infinite(double * result,INTEGER64 * inp,MX_CACHE * c)
{
MATRIX_ALLOC_VECTOR_PARAM p;
void * d1, * d2;
MATRIX_DH_SET ds;
int i;
double * data;
int dim[2];
	p.dim = 2;
	dim[0] = 1;
	dim[1] = src_dim+1;
	p.ix_size = &dim[0];
	p.default_data = 0;
	p.mxc = c;
	d1 = mxt_alloc_vector(&mx_type_double_v,MD_CALLOC,&p,0);
	get_matrix_dh_set(&ds,d1);
	data = ds.offset;
	for ( i = 0 ; i < src_dim ; i ++ )
		data[i] = inp[i+1];
	data[src_dim] = 1;
	d2 = mxt_mul_mm(avg_mtx.hd,d1,c);
	mxc_free(&read_c,d1);
	get_matrix_dh_set(&ds,d2);
	data = ds.offset;
	for ( i = 0 ; i < src_dim ; i ++ )
		result[i] = data[i];
	mxc_free(&read_c,d2);
}

int
extrapolation_estimate(MXMAP_LIST * tree,
		int cnt,MATRIX * m,INTEGER64 * dc)
{
int i;
int * start_ix;
int * inc;
int * target_ix;
int * size_ix;
char bit;
int er;
MX_CACHE_PARAM p;


	for ( i = 1 ; i <= m->p.dim ; i ++ )
		dc[i] &= - (((INTEGER64)1)<<((dc[0]*m->dim_divide[i-1])
					+ m->block_size[i-1]));
	target_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	start_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	size_ix = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	inc = mxc_alloc(&read_c,sizeof(int)*(mtx->p.dim));
	for ( i = 0 ; i < mtx->p.dim ; i ++ ) {
		target_ix[i] = 0;
		start_ix[i] = 0;
		inc[i] = 1;
		if ( (dc[i+1]>>(dc[0]*m->dim_divide[i])) + 
				(1<<m->block_size[i])
				<= m->pixel_size_list[dc[0]][i] )
			size_ix[i] = 1<<mtx->block_size[i];
		else	size_ix[i] =
			m->pixel_size_list[dc[0]][i] - 
			(dc[i+1]>>(dc[0]*m->dim_divide[i]));
	}
	
	p.c = &read_c;
	p.dc = dc;
	p.ofs = target_ix;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;

	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = MXC_INVALID;
		p.data_ix[i+1].p = MXC_INVALID;
	}

	for ( ; ; ) {
		er = read_mx_cache(&p);
		if ( er < 0 )
{
ss_printf(">>>  %lli %lli\n",
p.c->m->pixel_size[0],
p.c->m->pixel_size[1]);
ss_printf(">>> %s %i %i\n",
pt_dc(p.c->m,dc,PTDC_PIXEL_1),
target_ix[0],target_ix[1]);
			er_panic("extrapolation_estimate");
}

		if ( bit ) {

//ss_printf("ESTIMATE INSERT %i %i\n",target_ix[0],target_ix[1]);
			insert_polation_list(tree,dc,target_ix);
			cnt ++;
		}
		if( inc_ix(target_ix,start_ix,inc,size_ix,
					mtx->p.dim) )
			break;
	}

	mxc_free(&read_c,target_ix);
	mxc_free(&read_c,start_ix);
	mxc_free(&read_c,size_ix);
	mxc_free(&read_c,inc);

	return cnt;
}


void
distance_and_data(double ** rp,INTEGER64 * dist,
		MXMAP_LIST * t,INTEGER64 * target)
{
char bit;
double * data;
int i,j;
INTEGER64 target_org;
INTEGER64 inc;
INTEGER64 d;
MX_CACHE_PARAM p;
MATRIX * m;

	m = t->m;

	data = mxc_alloc(&read_c,sizeof(double)*dest_dim);

	p.c = &read_c;
	p.dc = target;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;

	p.data_ptrs[1] = data;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 1;
	}

	for ( i = 0 ; i < m->p.dim ; i ++ ) {
//ss_printf("dad %i\n",i);
		target_org = target[i+1];
		inc = ((INTEGER64)1)<<
			(target[0]*m->dim_divide[i]);
		d = 1;
		target[i+1] -= inc;
		for ( ; target[i+1] >= 0 ; target[i+1] -= inc ,
				d ++ ) {
			if ( t->max_dist > 0 &&
					d >= t->max_dist )
				break;
			if ( read_mx_cache(&p) < 0 )
				break;
			if ( bit == 0 )
				continue;
			if ( rp ) {
//ss_printf("dad %i A\n",i);
				rp[i] = mxc_alloc(&read_c,sizeof(double)*dest_dim);
				for ( j = 0 ; j < dest_dim ; j ++ )
					rp[i][j] = data[j];
				dist[i] = d;
			}
			dist[i] = d;
			goto next;
		}
		if ( t->infinite ) {
			if ( target[i+1] < 0 )
				target[i+1] = 0;
			dist[i] = target_org>>(target[0]*m->dim_divide[i]);
			if ( rp ) {
//ss_printf("dad %i B\n",i);
				rp[i] = mxc_alloc(&read_c,sizeof(double)*dest_dim);
				calc_infinite(rp[i],target,&read_c);
			}
			else {
				dist[i] = (dist[i]+10)*(dist[i]+10);
			}
		}
		else {
			if ( rp )
//{ss_printf("dad %i C\n",i);
				rp[i] = 0;
//}
			dist[i] = 0;
		}
	next:
		d = 1;
		target[i+1] = target_org + inc;
//ss_printf("dad PIX %lli\n",m->pixel_size[i]);
		for ( ; target[i+1] < m->pixel_size[i] ; 
				target[i+1] += inc,
				d ++ ) {
			if ( t->max_dist > 0 &&
					d >= t->max_dist )
				break;
			if ( read_mx_cache(&p) < 0 )
				break;
			if ( bit == 0 )
				continue;
			if ( rp ) {
//ss_printf("dad %i D %i\n",i,i+m->p.dim);
				rp[i+m->p.dim] 
				   = mxc_alloc(&read_c,sizeof(double)*dest_dim);
				for ( j = 0 ; j < dest_dim ; j ++ )
					rp[i+m->p.dim][j] = data[j];
			}
			dist[i+m->p.dim] = d;
			goto next2;
		}
		if ( t->infinite ) {
			dist[i+m->p.dim] = (target[i+1] - target_org)
					>>(target[0]*m->dim_divide[i]);
			dist[i+m->p.dim]++;
			if ( rp ) {
//ss_printf("dad %i E %i - %lli\n",i,i+m->p.dim,dist[i]);
				rp[i+m->p.dim]
				 = mxc_alloc(&read_c,sizeof(double)*dest_dim);
				calc_infinite(rp[i+m->p.dim],target,&read_c);
			}
			else {
				dist[i+m->p.dim] = 
					(dist[i+m->p.dim]+10)*
					(dist[i+m->p.dim]+10);
			}
		}
		else {
			if ( rp )
//{ss_printf("dad %i F %i\n",i,i+m->p.dim);
				rp[i+m->p.dim] = 0;
//}
			dist[i+m->p.dim] = 0;
		}
	next2:
		target[i+1] = target_org;
	}

	mxc_free(&read_c,data);
	mxc_free(&read_c,p.data_ix);
}

int
mxmap_list_cmp(MXMAP_NODE * n1,MXMAP_NODE * n2)
{
	if ( n1->weight < n2->weight )
		return -1;
	if ( n1->weight > n2->weight )
		return 1;
	return 0;
}

void
purge_polation_list(MXMAP_LIST * tree)
{
AVT_NODE * n;
MXMAP_NODE * nd, * nd2;
	for ( ; tree->tree ; ) {
		n = avt_delete(&tree->tree,tree->tree->data,
				mxmap_list_cmp);
		nd = n->data;
		for ( ; nd ; ) {
			nd2 = nd->next;
			d_f_ree(nd->target);
			d_f_ree(nd);
			nd = nd2;
		}
		d_f_ree(n);
	}
}

int
insert_polation_list_2(MXMAP_LIST * tree,INTEGER64 * target)
{
MX_CACHE_PARAM p;
char bit;
INTEGER64 * dist;
double d,d2;
int i,j;
AVT_NODE * n, * n2;
MXMAP_NODE * ndata, * nd2;
MX_CACHE_PARAM_IX * dix;
int ret;

	ret = -1;
	p.c = &read_c;
	p.dc = target;
	p.ofs = 0;
	p.data_ix = dix = 
		mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = MXC_INVALID;
		p.data_ix[i+1].p = MXC_INVALID;
	}


	if ( read_mx_cache(&p) < 0 )
		goto finish_1;
	if ( bit == 1 )
		goto finish_1;

	dist = mxc_alloc(&read_c,sizeof(INTEGER64)*(tree->m->p.dim*2));

	distance_and_data(0,dist,tree,target);
	d = 0;
	for ( i = 0 ; i < tree->m->p.dim*2 ; i ++ ) {
		if ( dist[i] == 0 )
			continue;
		d2 = 1;
		for ( j = 0 ; j < tree->pol ; j ++ )
			d2 *= ((double)dist[i]);
		d += 1/d2;
	}
	if ( d == 0 )
		goto finish_2;

	ret = 0;
	d = d / tree->div;
	tree->div ++;

//ss_printf("IPL-1 %s %f\n",pt_dc(tree->m,target,PTDC_PIXEL_1),d);

	ndata = d_alloc(sizeof(*ndata));
	ndata->next = 0;
	ndata->weight = d;
	ndata->target = target;
	n = d_alloc(sizeof(*n));
	n->data = ndata;
	n2 = avt_insert(&tree->tree,n,mxmap_list_cmp);
	if ( n2 != n ) {
		nd2 = n2->data;
		ndata->next = nd2->next;
		nd2->next = ndata;
		d_f_ree(n);
	}
	tree->count ++;

finish_2:
	mxc_free(&read_c,dist);
finish_1:
	mxc_free(&read_c,dix);

	return ret;
}

void
insert_polation_list(MXMAP_LIST * t,INTEGER64 * t1,int * t2)
{
INTEGER64 * t3;
int i,j;
INTEGER64 inc;


	for ( i = 0 ; i < t->m->p.dim ; i ++ ) {
		inc = ((INTEGER64)1)<<(
			t1[0] * t->m->dim_divide[i]);

		t3 = d_alloc(sizeof(INTEGER64)*(t->m->p.dim+1));
		memcpy(t3,t1,sizeof(INTEGER64)*(t->m->p.dim+1));
		if ( t2 )
			for ( j = 0 ; j < t->m->p.dim ; j ++ )
				t3[j+1] += ((INTEGER64)t2[j])<<
					(t1[0] * t->m->dim_divide[j]);
		
//ss_printf("IPL %s - %i\n",pt_dc(t->m,t3,PTDC_PIXEL_1),i);

		t3[i+1] -= inc;
		if ( insert_polation_list_2(t,t3) < 0 )
			d_f_ree(t3);

		t3 = d_alloc(sizeof(INTEGER64)*(t->m->p.dim+1));
		memcpy(t3,t1,sizeof(INTEGER64)*(t->m->p.dim+1));
		if ( t2 )
			for ( j = 0 ; j < t->m->p.dim ; j ++ )
				t3[j+1] += ((INTEGER64)t2[j])<<
					(t1[0] * t->m->dim_divide[j]);

		t3[i+1] += inc;
		if ( insert_polation_list_2(t,t3) < 0 )
			d_f_ree(t3);

	}
}

typedef struct __dpl {
	MXMAP_NODE * 	nd;
	int		free_flag;
} __DPL;

int
__delete_polation_list(AVT_NODE * a,__DPL * d)
{
MXMAP_NODE * nd;
	nd = a->data;
	if ( nd->next ) {
		d->nd = nd->next;
		nd->next = nd->next->next;
	}
	else {
		d->nd = a->data;
		d->free_flag = 1;
	}
	return 1;
}

INTEGER64 *
delete_polation_list(MXMAP_LIST * t)
{
__DPL d;
INTEGER64 * ret;
AVT_NODE * n;
static int dpl_time;
int tm;
	if ( t->tree == 0 )
		return 0;
	d.nd = 0;
	d.free_flag = 0;
	avt_trace_from_large(t->tree,__delete_polation_list,&d);
	ret = d.nd->target;
	if ( d.free_flag ) {
		n = avt_delete(&t->tree,d.nd,mxmap_list_cmp);
		d_f_ree(n);
	}
	d_f_ree(d.nd);
	t->count --;

	tm = get_xltime();
	if ( tm != dpl_time ) {
		ss_printf("DPL %i\n",t->count);
		dpl_time = tm;
	}
	return ret;
}

void
extrapolation_2(MXMAP_LIST* tree,INTEGER64 * target)
{
double ** rp;
MATRIX * m;
double * data;
MX_CACHE_PARAM p;
char bit;
int i,j;
int f;
double base;
INTEGER64 * dist;
int t;


	m = tree->m;

	t = get_xltime();
	if ( time_count != t ) {
		ss_printf("EX-2 %lli %lli %s\n",
			tree->m->pixel_size[0],
			tree->m->pixel_size[1],
			pt_dc(m,target,
				PTDC_PIXEL_1));
		time_count = t;
	}

	p.c = &read_c;
	p.dc = target;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ptrs[1] = 0;

	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = MXC_INVALID;
		p.data_ix[i+1].p = MXC_INVALID;
	}

	if ( read_mx_cache(&p) < 0 )
		goto finish_2;
	if ( bit )
		goto finish_2;


	rp = mxc_alloc(&read_c,sizeof(double*)*m->p.dim*2);
	memset(rp,0,sizeof(double*)*m->p.dim*2);
	dist = mxc_alloc(&read_c,sizeof(INTEGER64)*m->p.dim*2);

	distance_and_data(rp,dist,tree,target);

	bit = 1;
	data = mxc_alloc(&read_c,sizeof(double)*dest_dim);

	f = 0;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		data[i] = 0;
		base = 0;
		for ( j = 0 ; j < m->p.dim*2 ; j ++ ) {
			if ( dist[j] == 0 )
				continue;
			f = 1;
			data[i] += rp[j][i] / dist[j];
			base += 1 / (double)dist[j];
		}
		data[i] /= base;

	}
	if ( f == 0 )
		goto finish;

	p.c = &read_c;
	p.dc = target;
	p.ofs = 0;
//	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ptrs[1] = data;

	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 1;
	}

	write_mx_cache(&p);

finish:
	mxc_free(&read_c,data);
	mxc_free(&read_c,dist);
	for ( i = 0 ; i < m->p.dim*2 ; i ++ )
		if ( rp[i] )
			mxc_free(&read_c,rp[i]);
	mxc_free(&read_c,rp);

	if ( tree->infinite )
		insert_polation_list(tree,target,0);

finish_2:
	mxc_free(&read_c,p.data_ix);
}

void
setup_mxmap(MXMAP_LIST * t)
{
int pp;
	for ( pp = 0 ; t->m->p.dim >= (1<<pp) ; pp ++ );
	if ( (pp+1) & 1 )
		t->pol = (pp+1)/2+1;
	else	t->pol = (pp+1)/2;
	t->div = 1;
	t->count = 0;
}

int
extrapolation_1(MATRIX * mtx,int level,int max_dist)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target,* _target;
int f;
int eret;
MXMAP_LIST tree;
int ret;

	memset(&tree,0,sizeof(tree));
	tree.m = mtx;
	tree.infinite = 1;
	tree.max_dist = max_dist;
	setup_mxmap(&tree);
	target = d_alloc(sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	if ( level < 0 )
		target[0] = mtx->total_levels - 1;
	else	target[0] = level;
	f = 0;
	eret = 0;
	for ( ; ; ) {
		ss_printf("EXPOLATION-1 %s %i\n",pt_dc(mtx,target,
			PTDC_NODE_ID),eret);

		lst = mx_search_level_node(mtx,target,BUF_SIZE);

		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
		}
		f = 1;

		if ( lst == 0 ) {
			if ( eret > ESTIMATING_MIN )
				break;
			if ( level >= 0 )
				break;
			target[0] --;
			if ( target[0] < 0 ) {
				target[0] = 0;
				break;
			}
			f = 0;
			memset(&target[1],0,sizeof(INTEGER64)*(mtx->p.dim));
			purge_polation_list(&tree);
			eret = 0;
			continue;
		}

		for ( ; lst ; ) {
			lst2 = lst->next;

			eret = extrapolation_estimate(&tree,
						eret,mtx,lst->dc);

			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;

			if ( max_dist > 0 && tree.count > TREE_LIMIT ) {
				for ( ; tree.count > TREE_LIMIT/2 ; ) {
					_target = delete_polation_list(&tree);
					extrapolation_2(&tree,_target);
					d_f_ree(_target);
				}
			}
		}
	}
ss_printf("ERET %i %i %i\n",eret,level,target[0]);
	ret = target[0];
	d_f_ree(target);

	for ( ; tree.tree ; ) {
		_target = delete_polation_list(&tree);
		extrapolation_2(&tree,_target);
		d_f_ree(_target);
	}

ss_printf("EX-1 hem handling\n");
	
	handling_hem(mtx,ret,1);

ss_printf("EX-1 hem handling END\n");
	return ret;
}

void
extrapolation_4(MATRIX * m,INTEGER64 * dc,int max_dist)
{
int i;
INTEGER64 * end_pos;
INTEGER64 * inc;
INTEGER64 * target;
MX_CACHE_PARAM p;
char bit;
double * data;
	end_pos = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	inc = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	data = mxc_alloc(&read_c,sizeof(double)*dest_dim);
	for ( i = 0 ; i < m->p.dim ; i ++ ) {
		target[i+1] = dc[i+1];
		dc[i+1] &= - (((INTEGER64)1)<<
				(dc[0] * m->dim_divide[i]
					+ m->block_size[i]));
		end_pos[i+1] = dc[i+1] + 
				(((INTEGER64)1)<<
				(dc[0] * m->dim_divide[i]
					+ m->block_size[i]));
		if ( end_pos[i+1] > m->pixel_size[i] )
			end_pos[i+1] = m->pixel_size[i];
		inc[i+1] = ((INTEGER64)1)<<
				(dc[0] * m->dim_divide[i]);
	}
	p.c = &read_c;
	p.dc = target;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;
	p.data_ptrs[1] = data;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 1;
	}

	for ( ; ; ) {
		target[0] = dc[0]-1;
		p.c = &read_c;
		if ( read_mx_cache(&p) >= 0 ) {

//ss_printf("EX-3 %i %f %f\n",bit,data[0],data[1]);
			if ( bit ) {
				target[0] = dc[0];
				p.c = &write_hem_c;
				write_mx_cache(&p);
			}
		}

		if ( inc_dim_code_ix(target,dc,inc,end_pos,m->p.dim) )
			break;
	}
	
	mxc_free(&read_c,end_pos);
	mxc_free(&read_c,inc);
	mxc_free(&read_c,target);
	mxc_free(&read_c,data);
	
	extrapolation_1(m,dc[0],max_dist);
}

void
extrapolation_3(MATRIX * mtx,int level,int max_dist)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target;
int f;

	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	target[0] = level;
	f = 0;
	for ( ; ; ) {
		ss_printf("EXPOLATION-3 %s\n",pt_dc(mtx,target,
			PTDC_NODE_ID));

		lst = mx_search_level_node(mtx,target,BUF_SIZE);
		if ( lst == 0 ) {
			break;
		}
		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
			if ( lst == 0 )
				break;
		}
		f = 1;

		for ( ; lst ; ) {
			lst2 = lst->next;

			ss_printf("EXPOLATION-3-handle %s\n",
				pt_dc(mtx,lst->dc,
			PTDC_NODE_ID));

			extrapolation_4(mtx,lst->dc,max_dist);

			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;

		}
	}
	mxc_free(&read_c,target);

	handling_hem(mtx,level,1);
}

int
extrapolation_7(
	MX_CACHE_PARAM * p,
	MXMAP_LIST * tree,
	INTEGER64 * target,
	INTEGER64 * st_ofs,
	INTEGER64 * dc,
	INTEGER64 * inc,
	INTEGER64 * end_pos,
	MATRIX * m,
	int lev,
	int cnt)
{
int i,j;
int d;
int _cnt;
INTEGER64 * start;
	if ( lev <= cnt ) {
		i = 1;
		for ( d = 0 ; d < lev ; d ++ ) {
			for ( ; i <= m->p.dim ; i ++ )
				if ( st_ofs[i] )
					break;
			if ( i > m->p.dim )
				return -1;
			i ++;
			if ( i > m->p.dim )
				return -1;
		}
		if ( i > m->p.dim )
			return -1;
		for ( j = i ; j <= m->p.dim ; j ++ )
			st_ofs[j] = 0;
		for ( ; i <= m->p.dim ; i ++ ) {
			st_ofs[i] = inc[i]>>1;
			if ( extrapolation_7(
					p,tree,
					target,
					st_ofs,
					dc,
					inc,
					end_pos,
					m,
					lev+1,
					cnt) < 0 )
				return -1;
			for ( j = i ; j <= m->p.dim ; j ++ )
				st_ofs[j] = 0;
		}
		return 0;
	}
	else {
ss_printf("===== %s\n",pt_dc(m,dc,PTDC_PIXEL_1));
		start = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
		for ( i = 1 ; i <= m->p.dim ; i ++ ) {
			target[i] = start[i] = dc[i] + st_ofs[i];
		}
ss_printf("2 %s inc(%s)\n",pt_dc(m,st_ofs,PTDC_PIXEL_1),pt_dc(m,inc,PTDC_PIXEL_1));
		start[0] = target[0] = dc[0];
_cnt = 0;
		for ( ; ; ) {
/*
if ( target[1] == (1<<dc[0]) && target[2] == (2<<dc[0]) )
ss_printf("** 1 2 -->\n");
*/
//ss_printf("LOOP %s\n",pt_dc(m,target,PTDC_PIXEL_1));
			extrapolation_2(tree,target);
_cnt++;
			if ( inc_dim_code_ix(target,start,inc,end_pos,m->p.dim) )
				break;
		}
ss_printf("2 %s = %i\n",pt_dc(m,st_ofs,PTDC_PIXEL_1),_cnt);
		mxc_free(&read_c,start);
		return 0;
	}
}


void
extrapolation_6(MATRIX * m,INTEGER64 * dc)
{
int i;
INTEGER64 * end_pos;
INTEGER64 * inc;
INTEGER64 * target;
INTEGER64 * st_ofs;
MX_CACHE_PARAM p;
char bit;
double * data;
int cnt;
MXMAP_LIST tree;

ss_printf("EX-6 %s\n",pt_dc(m,dc,PTDC_NODE_ID));

	end_pos = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	inc = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	inc[0] = dc[0];
	data = mxc_alloc(&read_c,sizeof(double)*dest_dim);
	for ( i = 0 ; i < m->p.dim ; i ++ ) {
		dc[i+1] &= - (((INTEGER64)1)<<
				(dc[0] * m->dim_divide[i]
					+ m->block_size[i]));
		target[i+1] = dc[i+1];
		end_pos[i+1] = (dc[i+1] + 
				(((INTEGER64)1)<<
				(dc[0] * m->dim_divide[i]
					+ m->block_size[i])))+1;
		if ( end_pos[i+1] > m->pixel_size[i] )
			end_pos[i+1] = m->pixel_size[i];
		inc[i+1] = (((INTEGER64)1)<<
				((dc[0]+1) * m->dim_divide[i]));
	}
	p.c = &read_c;
	p.dc = target;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = &bit;
	p.data_ptrs[1] = data;

	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;
	for ( i = 0 ; i < dest_dim ; i ++ ){
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 1;
	}
	for ( ; ; ) {
		target[0] = dc[0]+1;
		p.c = &read_c;
		if ( read_mx_cache(&p) >= 0 ) {
			if ( bit ) {
				target[0] = dc[0];
				p.c = &write_hem_c;
				write_mx_cache(&p);
			}
else ss_printf("*************************** EX-6 ERR\n");
		}

		if ( inc_dim_code_ix(target,dc,inc,end_pos,m->p.dim) )
			break;
	}
	
	st_ofs = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	memset(st_ofs,0,sizeof(INTEGER64)*(m->p.dim+1));

	memset(&tree,0,sizeof(tree));
	tree.m = m;
	tree.infinite = 0;
	tree.count = 2;
	setup_mxmap(&tree);
	tree.max_dist = 2;

	for ( cnt = 0 ; cnt < m->p.dim ; cnt ++ )
		extrapolation_7(&p,&tree,target,st_ofs,dc,inc,end_pos,m,0,cnt);

	mxc_free(&read_c,st_ofs);
	mxc_free(&read_c,end_pos);
	mxc_free(&read_c,inc);
	mxc_free(&read_c,target);
	mxc_free(&read_c,data);

check_hole(m,dc,0);
}


void
extrapolation_5(MATRIX * mtx,int level)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target;
int f;

	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	target[0] = level;
	f = 0;
	for ( ; ; ) {
		lst = mx_search_level_node(mtx,target,BUF_SIZE);
		if ( lst == 0 ) {
			break;
		}
		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
			if ( lst == 0 )
				break;
		}
		f = 1;

		for ( ; lst ; ) {
			lst2 = lst->next;

			extrapolation_6(mtx,lst->dc);

			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;

		}
	}
	mxc_free(&read_c,target);

//	extrapolation_1(mtx,level,max_dist);
}


void
pee_1(MATRIX * m,INTEGER64 * dc)
{
int i;
INTEGER64 * inc;
INTEGER64 * target_ix;
INTEGER64 * end_pos;
double * data1,* data2;
char bit;
double * delta;
double d;
MX_CACHE_PARAM p1;
double zero;
static int time_count;
int tm;
int level;
	for ( i = 1 ; i <= m->p.dim ; i ++ )
		dc[i] &= - (((INTEGER64)1)<<((dc[0]*m->dim_divide[i-1])
					+ m->block_size[i-1]));
	target_ix = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	end_pos = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	inc = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));

	delta = mxc_alloc(&read_c,sizeof(double)*
			  (m->total_levels+1));
	data1 = mxc_alloc(&read_c,sizeof(double)*dest_dim);
	data2 = mxc_alloc(&read_c,sizeof(double)*dest_dim);

	p1.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));

ss_printf("ppe-1-1\n");

	for ( level = 0 ; level < m->p.total_levels ; level ++ ) {
		
		for ( i = 1 ; i <= mtx->p.dim ; i ++ ) {
			target_ix[i] = dc[i];
			inc[i] = 1;
			end_pos[i] = dc[i] + (1<<m->block_size[i]);
			if ( end_pos[i] > m->pixel_size[i] )
				end_pos[i] = m->pixel_size[i];
		}
		for ( i = 0 ; i < m->total_levels ; i ++ )
			delta[i] = 0;
		
		p1.c = &read_c;
		p1.dc = target_ix;
		p1.ofs = 0;

ss_printf("ppe-1-2\n");
		p1.data_ptrs[0] = &bit;
		p1.data_ix[0].x = 0;
		p1.data_ix[0].p = 0;

		for ( i = 0 ; i < dest_dim ; i ++ ) {
			p1.data_ix[i+1].x = i;
			p1.data_ix[i+1].p = 1;
		}
		p1.data_ptrs[0] = &bit;

		for ( ; ; ) {
			target_ix[0] = 0;
tm = get_xltime();
if ( tm != time_count ) {
ss_printf("ppe %s %i\n",pt_dc(m,target_ix,PTDC_PIXEL_1),level);
time_count = tm;
}
			p1.data_ptrs[1] = data1;
			p1.data_ix[0].x = 0;
			p1.data_ix[0].p = 0;
			if ( read_mx_cache(&p1) < 0 )
				goto next;
			if ( bit == 0 )
				goto next;
			target_ix[0] = level;

			p1.data_ptrs[1] = data2;

			p1.data_ix[0].x = MXC_INVALID;
			p1.data_ix[0].p = MXC_INVALID;

			p1.inp_level = p1.dc[0];
			p1.inp_buf = 0;
			if ( read_mx_ip_double(&p1) < 0 )
				er_panic("pee1");
			for ( i = 0 ; i < dest_dim ; i ++ ) {
				d = data1[i] - data2[i];
				if ( d < 0 )
					d = -d;
				if ( delta[level] < d )
					delta[level] = d;
			}
		next:
			if( inc_dim_code_ix(target_ix,dc,inc,end_pos,
						m->p.dim) )
				break;
		}
	
	}
ss_printf("ppe-1-3\n");
	
	p1.c = &write_delta_c;
	p1.dc = dc;

	mxc_free(&read_c,p1.data_ix);

	p1.data_ix = mxc_alloc(&read_c,
			sizeof(MX_CACHE_PARAM_IX)*(m->total_levels+1));
ss_printf("ppe-1-4\n");
	p1.data_ptrs[0] = delta;
	for ( i = 0 ; i < m->total_levels ; i ++ ) {
		p1.data_ix[i+1].x = i;
		p1.data_ix[i+1].p = 0;
	}
ss_printf("ppe-1-5\n");
	zero = 0;
	p1.data_ix[0].x = 0;
	p1.data_ix[0].p = 1;
	p1.data_ptrs[1] = &zero;

ss_printf("ppe-1-6\n");

	write_mx_cache(&p1);
ss_printf("ppe-1-7\n");

	mxc_free(&read_c,p1.data_ix);
	mxc_free(&read_c,target_ix);
	mxc_free(&read_c,end_pos);
	mxc_free(&read_c,inc);
	mxc_free(&read_c,data1);
	mxc_free(&read_c,data2);

ss_printf("ppe-1-8\n");

}

void
polation_error_estimation_1(MATRIX * mtx)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target;
int f;

	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	f = 0;
	for ( ; ; ) {
		lst = mx_search_level_node(mtx,target,BUF_SIZE);
		if ( lst == 0 ) {
			break;
		}
		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
			if ( lst == 0 )
				break;
		}
		f = 1;

		for ( ; lst ; ) {
			lst2 = lst->next;

ss_printf("P8-pee-1\n");
			pee_1(mtx,lst->dc);
ss_printf("P8-pee-2\n");
			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));
ss_printf("P8-pee-3\n");

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;

		}
	}
	mxc_free(&read_c,target);
}

void
pee_2(MATRIX * m,INTEGER64 * dc)
{
MX_DIM_CODE_LIST * lst,* lst2;
MX_CACHE_PARAM p;
double * data,* acc;
double delta;
int i;

	data = mxc_alloc(&write_delta_c,sizeof(double)*m->total_levels);
	acc = mxc_alloc(&write_delta_c,sizeof(double)*m->total_levels);

	p.c = &write_delta_c;
	p.dc = 0;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&write_delta_c,sizeof(MX_CACHE_PARAM_IX)*(m->total_levels+1));
	p.data_ptrs[0] = data;
	for ( i = 0 ; i < m->total_levels; i ++ ) {
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 0;
		acc[i] = 0;
	}
	p.data_ix[0].x = p.data_ix[0].p = MXC_INVALID;

	lst = get_children_list(0,m,dc,GN_ERROR_NORETRY,1,0);
	for ( ; lst ; ) {
		lst2 = lst->next;

		p.dc = lst->dc;
		read_mx_cache(&p);	

		for ( i = 0 ; i < m->total_levels ; i ++ ) {
			if ( acc[i] > data[i] )
				continue;
			acc[i] = data[i];
		}

		d_f_ree(lst->dc);
		d_f_ree(lst);

		lst = lst2;
	}
	
	delta = acc[dc[0]];
	p.data_ix[0].x = 0;
	p.data_ix[0].p = 0;
	p.data_ptrs[0] = &delta;
	write_mx_cache(&p);

	mxc_free(&write_delta_c,data);
	mxc_free(&write_delta_c,acc);
}


void
polation_error_estimation_2(MATRIX * mtx,int level)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target;
int f;

	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	target[0] = level;
	f = 0;
	for ( ; ; ) {
		lst = mx_search_level_node(mtx,target,BUF_SIZE);
		if ( lst == 0 ) {
			break;
		}
		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
			if ( lst == 0 )
				break;
		}
		f = 1;

		for ( ; lst ; ) {
			lst2 = lst->next;

ss_printf("P8-pee-3\n");
			pee_2(mtx,lst->dc);
ss_printf("P8-pee-4\n");

			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));
ss_printf("P8-pee-5\n");

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;

		}
	}
	mxc_free(&read_c,target);
}

void
rr_2(MATRIX * m,INTEGER64 * dc)
{
MX_CACHE_PARAM p;
void * diff;
int i;
INTEGER64 * end_pos;
INTEGER64 * inc;
INTEGER64 * target;
double * data;

MATRIX_DH_SET ds;
void * pitch_ptr;
void * b1,* b2,* b3, * b4;
double rr;


	end_pos = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	inc = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(m->p.dim+1));
	data = mxc_alloc(&read_c,sizeof(double)*dest_dim);

	for ( i = 0 ; i < m->p.dim ; i ++ ) {
		dc[i+1] &=
			- (((INTEGER64)1)<<(dc[0]*m->dim_divide[i] +
					m->block_size[i]));
		inc[i+1] = ((INTEGER64)1)<<(dc[0]*m->dim_divide[i]);
		target[i+1] = dc[i+1];
	}
	inc[0] = target[0] = dc[0];

	p.c = &read_c;
	p.dc = target;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ptrs[0] = data;
	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 0;
	}
	p.data_ix[0].x = p.data_ix[0].p = MXC_INVALID;

	pitch_ptr = mxt_get_matrix_from_ary(
			&mx_type_double_v,
			pitch,m->p.dim,2,p.c);
	for ( ; ; ) {
		p.c = &read_c;
		p.inp_level = p.dc[0];
		p.inp_buf = 0;
		diff = read_mx_ipdiff_double(&p);
		if ( diff == 0 )
			continue;
		b2 = mxt_mul_mm(diff,
			b1=mxt_trans_m(pitch_ptr,p.c),p.c);
		b4 = mxt_mul_mm(b3=mxt_trans_m(b2,p.c),b2,p.c);
		get_matrix_dh_set(&ds,b4);
		rr = sqrt(*(double*)ds.offset);

		p.c = &write_rr_c;
		write_mx_cache(&p);

		mxc_free(&read_c,b1);
		mxc_free(&read_c,b2);
		mxc_free(&read_c,b3);
		mxc_free(&read_c,b4);
		mxc_free(&read_c,diff);

		if ( inc_dim_code_ix(target,dc,inc,end_pos,m->p.dim) )
			break;
	}
	mxc_free(&read_c,pitch_ptr);

	mxc_free(&read_c,target);
	mxc_free(&read_c,data);
	mxc_free(&read_c,inc);
	mxc_free(&read_c,end_pos);
}


void
rr_1(MATRIX * mtx,int level)
{
MX_DIM_CODE_LIST * lst, * lst2;
INTEGER64 * target;
int f;

	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(mtx->p.dim+1));
	memset(target,0,sizeof(INTEGER64)*(mtx->p.dim+1));
	target[0] = level;
	f = 0;
	for ( ; ; ) {
		lst = mx_search_level_node(mtx,target,BUF_SIZE);
		if ( lst == 0 ) {
			break;
		}
		if ( f && cmp_dim_code(mtx,target,lst->dc) == 0 ) {
			lst2 = lst;
			lst = lst->next;
			d_f_ree(lst2->dc);
			d_f_ree(lst2);
			if ( lst == 0 )
				break;
		}
		f = 1;

		for ( ; lst ; ) {
			lst2 = lst->next;

			rr_2(mtx,lst->dc);

			memcpy(target,lst->dc,
				sizeof(INTEGER64)*(mtx->p.dim+1));

			d_f_ree(lst->dc);
			d_f_ree(lst);

			lst = lst2;

		}
	}
	mxc_free(&read_c,target);
}

double
get_pitch_tolerance()
{
int i;
double ret;
	ret = 0;
	for ( i = 0 ; i < src_dim ; i ++ )
		ret += pitch[i];
	return ret/src_dim;
}




void
reverse_matrix(MATRIX * m,char * filename)
{
int i;
INTEGER64 * start_pos;
INTEGER64 * end_pos;
INTEGER64 * inc;
INTEGER64 * target;
MX_CACHE_PARAM p;
double * data;
double * _target;
FILE * fd;
int cnt;
int level;
MATRIX_DH_SET data_ds,target_ds;
MATRIX_ALLOC_VECTOR_PARAM vp;
void * data_ptr;
void * target_ptr;
int ix[2];
static int cnt_time;
int tim;

	fd = fopen(filename,"w+");

	ix[0] = 1;
	ix[1] = src_dim;
	vp.dim = 2;
	vp.ix_size = &ix[0];
	vp.default_data = 0;
	vp.mxc = &read_c;
	data_ptr = mxt_alloc_vector(
			&mx_type_double_v,
			MD_CALLOC,
			&vp,0);
	get_matrix_dh_set(&data_ds,data_ptr);
	data = data_ds.offset;

	ix[0] = 1;
	ix[1] = dest_dim;
	vp.dim = 2;
	vp.ix_size = &ix[0];
	vp.default_data = 0;
	vp.mxc = &read_c;
	target_ptr = mxt_alloc_vector(
			&mx_type_double_v,
			MD_CALLOC,
			&vp,0);
	get_matrix_dh_set(&target_ds,target_ptr);
	_target = target_ds.offset;

	start_pos = mxc_alloc(&read_c,sizeof(INTEGER64)*(dest_dim+1));
	end_pos = mxc_alloc(&read_c,sizeof(INTEGER64)*(dest_dim+1));
	inc = mxc_alloc(&read_c,sizeof(INTEGER64)*(dest_dim+1));
	target = mxc_alloc(&read_c,sizeof(INTEGER64)*(dest_dim+1));
	for ( i = 0 ; i < m->p.dim ; i ++ ) {
		start_pos[i+1] = 0;
		target[i+1] = 0;
		inc[i+1] = 1;
		end_pos[i+1] = ((dest_max[i] - dest_min[i])/pitch[i] + 1);
	}
	p.c = &read_c;
	p.dc = 0;
	p.ofs = 0;
	p.data_ix = mxc_alloc(&read_c,sizeof(MX_CACHE_PARAM_IX)*(dest_dim+1));
	p.data_ix[0].x = p.data_ix[0].p = MXC_INVALID;

	for ( i = 0 ; i < dest_dim ; i ++ ) {
		p.data_ix[i+1].x = i;
		p.data_ix[i+1].p = 0;
		data[i] = m->pixel_size[i]/2;
	}
//_debug_flag = 1;

	cnt = 1;
	level = m->total_levels-1;
	p.inp_level = level;
	for ( ; ; cnt ++ ) {
		tim = get_xltime();
		if ( cnt_time != tim ) {
			ss_printf("cnt = %i\n",cnt);
			cnt_time = tim;
		}

		for ( i = 0 ; i < dest_dim ; i ++ )
			_target[i] = target[i+1] * pitch[i] + dest_min[i];

		p.ret_buf = data_ptr;
		p.inp_buf = target_ptr;
		p.avg_mtx = avg_mtx.hd;
		p.tolerance = get_pitch_tolerance();
//		p.tolerance = 200;
//		p.tolerance = 1;
		p.try_max = 50;
//	p.inp_level = level;
		matrix_newton_double(&p);

		fprintf(fd,"%i\t",cnt);
		for ( i = 0 ; i < dest_dim ; i ++ ) {
			fprintf(fd,"%f\t",convert_data(
				_target[i],
				std_data_type,
				data_type[data_start+i]));
		}
		for ( i = 0 ; i < src_dim ; i ++ )
			fprintf(fd,"%f\t",convert_data(
				data[i] * pitch[i] + offset[i],
				std_data_type,
				data_type[src_dim+data_start+i]));
		if ( p.tolerance < p.result_tolerance )
			fprintf(fd,"\t%f =*=\n",p.result_tolerance);
		else 	fprintf(fd,"\t%f\n",p.result_tolerance);

		if ( inc_dim_code_ix(target,start_pos,inc,end_pos,
					m->p.dim) )
			break;
	}
	
	mxc_free(&read_c,start_pos);
	mxc_free(&read_c,end_pos);
	mxc_free(&read_c,inc);
	mxc_free(&read_c,target);
	mxc_free(&read_c,data_ptr);
	mxc_free(&read_c,target_ptr);
	mxc_free(&read_c,p.data_ix);

	fclose(fd);
}

void
calc_avg_mtx(MATRIX * m)
{
void * v_vct;
double * v_ptr;
MATRIX_DH_SET v_ds;
MATRIX_DH_SET ret_ds; 
void * ret;
double * ret_ptr;
double * avg_ptr;
void * avg;

/*
void * test,* test2;
MATRIX_DH_SET test2_ds;
double * test2_ptr;
double dd;
*/

MATRIX_ALLOC_VECTOR_PARAM vp;
int ix[2];

int i,j,k;

	ix[0] = 1;
	ix[1] = src_dim + 1;
	vp.dim = 2;
	vp.ix_size = ix;
	vp.default_data = 0;
	vp.mxc = &read_c;
	v_vct = mxt_alloc_vector(
			&mx_type_double_v,
			MD_CALLOC,
			&vp,0);
	get_matrix_dh_set(&v_ds,v_vct);
	v_ptr = v_ds.offset;
	
	ix[0] = src_dim+1;
	ix[1] = dest_dim+1;
	vp.dim = 2;
	vp.ix_size = ix;
	vp.default_data = 0;
	vp.mxc = &read_c;
	avg = mxt_alloc_vector(
			&mx_type_double_v,
			MD_CALLOC,
			&vp,0);
	get_matrix_dh_set(&avg_mtx,avg);
	avg_ptr = avg_mtx.offset;
/*
ss_printf("src_mtx %s\n",mxt_print(&mx_type_double_v,src_mtx,0));
ss_printf("sd_mtx %s\n",mxt_print(&mx_type_double_v,sd_mtx,0));
*/
	for (  j = 0 ; j < dest_dim ; j ++ ) {
		for ( i = 0 ; i <= src_dim ; i ++ )
			v_ptr[i] = sd_mtx_ptr[i+(src_dim+1)*j];
//ss_printf("v_vct %s\n",mxt_print(&mx_type_double_v,v_vct,0));
		
		ret = resolve_equation_double(src_mtx,v_vct,&read_c);
		if ( ret == 0 )
			er_panic("calc_avg_mtx");
		get_matrix_dh_set(&ret_ds,ret);
		ret_ptr = ret_ds.offset;
//ss_printf("ret_ptr %s\n",mxt_print(&mx_type_double_v,ret,0));
		for ( k = 0 ; k <= src_dim ; k ++ )
			avg_ptr[k + (src_dim+1)*j] = ret_ptr[k];
	}
/*
test =  mxt_mul_mm(avg_mtx.hd,src_mtx,&read_c);
ss_printf("TEST-1 %s\n",mxt_print(&mx_type_double_v,test,0));
mxc_free(&read_c,test);
ss_printf("avg_mtx %s\n",mxt_print(&mx_type_double_v,avg_mtx.hd,0));
*/
	for ( k = 0 ; k < src_dim ; k ++ )
		avg_ptr[k + (src_dim+1)*(dest_dim)] = 0;
	avg_ptr[(src_dim+1)*(dest_dim+1)-1] = 1;

/*
test =  mxt_mul_mm(avg_mtx.hd,src_mtx,&read_c);
ss_printf("TEST-2 %s\n",mxt_print(&mx_type_double_v,test,0));
mxc_free(&read_c,test);

	ix[0] = 1;
	ix[1] = 3;
	vp.dim = 2;
	vp.ix_size = ix;
	vp.default_data = 0;
	vp.mxc = &read_c;
	test2 = mxt_alloc_vector(
			&mx_type_double_v,
			MD_CALLOC,
			&vp,0);
	get_matrix_dh_set(&test2_ds,test2);
	test2_ptr = test2_ds.offset;

	test2_ptr[0] = 200000.00000;
	test2_ptr[1] = 1220700.00000;
	test2_ptr[2] = 1;

	for ( i = 0 ; i < 2 ; i ++ ) {
		dd = test2_ptr[i];
		dd = rint(convert_data(dd,
			"ddmmss.s","degree")/pitch[i]);
		test2_ptr[i] = dd - min[i] + margin[i];
ss_printf("test2_ptr %i %f\n",i,test2_ptr[i]);
	}

	test = mxt_mul_mm(avg_mtx.hd,test2,&read_c);
ss_printf("TEST-3 %s\n",mxt_print(&mx_type_double_v,test,0));
mxc_free(&read_c,test);
*/

}

void
write_parameters(MATRIX * m)
{
void * p;
MATRIX_DH_SET p_ds;
MATRIX_ALLOC_VECTOR_PARAM vp;
int ix;
MATRIX_NODE * n;
INTEGER64 * dim_code;
double * pitch_ptr;
char ** str_ptr;
int i;
int err;

	dim_code = d_alloc(sizeof(INTEGER64)*(m->p.dim+1));
	memset(dim_code,0,sizeof(INTEGER64)*(m->p.dim+1));

	ix = src_dim * 2;
	vp.dim = 1;
	vp.ix_size = &ix;
	vp.default_data = 0;
	vp.mxc = 0;

	dim_code[1] = (DC_PARAM)*(((INTEGER64)1)<<m->block_size[0]);

retry:
	err = 0;
	p = get_matrix_node_channel(
		&err,&n,m,dim_code,
		CH_PARAM_DOUBLE,GN_NODE,GN_NODE_CREATE,
		&vp);
	if ( p == 0 ) {
		if ( err == ME_MATRIX_ERR ) {
			sleep_sec(1);
			goto retry;
		}
		fprintf(stderr,"cannot write parameters (%i)\n",err);
		exit(1);
	}
	get_matrix_dh_set(&p_ds,p);
	pitch_ptr = p_ds.offset;
	for ( i = 0 ; i < src_dim ; i ++ ) {
		pitch_ptr[i] = offset[i];
		pitch_ptr[i+src_dim] = pitch[i];
	}

	matrix_node_channel_unlock(n,NF_DIRTY);

	ix = 2;
	vp.dim = 1;
	vp.ix_size = &ix;
	vp.default_data = 0;
	vp.mxc = 0;

	p = get_matrix_node_channel(
		&err,&n,m,dim_code,
		CH_PARAM_DOUBLE,GN_NODE,GN_NODE_CREATE,
		&vp);
	if ( p == 0 ) {
		fprintf(stderr,"cannot write parameters (%i)\n",err);
		exit(1);
	}
	get_matrix_dh_set(&p_ds,p);
	str_ptr = p_ds.offset;
	str_ptr[0] = copy_str(std_data_type);
	str_ptr[1] = copy_str(std_data_type);

	matrix_node_channel_unlock(n,NF_DIRTY);

	unlock_node(n,0);

	d_f_ree(dim_code);
}

void
flush_memory(int f)
{
	flush_mx_cache(&write_c,f);
	flush_mx_cache(&read_c,f);
	flush_mx_cache(&write_rr_c,f);
	flush_mx_cache(&write_delta_c,f);
	flush_mx_cache(&write_hem_c,f);
}

void
set_mode_cals(MATRIX * mtx)
{
	save_mode_cal(mtx,MI_MODE_SERVER,mcd_server,default_pri);
	save_mode_cal(mtx,MI_MODE_CRIENT,mcd_client,default_pri);
}

int
_main(int argc,char ** argv)
{
int inp;
int i;
MXMAP_WORK * mw;
int * access_ch;
int * access_delta_ch;
int rr_ch;
int start_level;
int lev;
MATRIX_ALLOC_VECTOR_PARAM vp;
int ix[2];
double zero = 0;

	minimum_matrix_init(argc,argv); 


	for ( inp = 1 ; inp < argc && 
		strcmp(argv[inp],"-inp") ; inp ++ );
	if ( inp == argc ) {
		fprintf(stderr,"input files are required\n");
		exit(1);
	}
	inp ++;

	ss_printf("PHASE 1 :: Estimating amount of data\n");

	for ( i = inp ; i < argc ; i ++ )
		read_file(argv[i],phase_1);
	
	ss_printf("PHASE 1(2);;\n");
	

	index_offset = mxc_alloc(&read_c,sizeof(INTEGER64)*src_dim);
	for ( i = 0 ; i < src_dim ; i ++ ) {
		offset[i] = (min[i] -  margin[i])*pitch[i];
		pixel_size[i] = max[i] - min[i] + 2*margin[i];
	}

	mw = d_alloc(sizeof(*mw));
	mw->src_dim = src_dim;
	mw->dest_dim = dest_dim;
	mw->pixel_size = pixel_size;

	ss_printf("PHASE 1(2-1);; %f\n",dest_min[0]);


	mtx = open_matrix(0,l_string(std_cm,argv[1]),0,
			open_mxmap,mw);
	if ( mtx == 0 ) {
		fprintf(stderr,"cannot open the matrix %s\n",
			argv[1]);
		exit(1);
	}
	wait_matrix_mode(mtx);
	set_matrix_env(mtx,"create-node","enable");

	ss_printf("PHASE 1(3);;\n");


	access_ch = d_alloc(sizeof(int)*(dest_dim+1));
	for ( i = 0 ; i < dest_dim ; i ++ )
		access_ch[i+1] = CH_DATA+i;
	access_ch[0] = CH_BITMASK;

	access_delta_ch = d_alloc(sizeof(int)*(mtx->total_levels+1));
	for ( i = 0 ; i < mtx->total_levels ; i ++ )
		access_delta_ch[i+1] = CH_DATA+dest_dim+i;
	access_delta_ch[0] = CH_DELTA;

	rr_ch = CH_RESO_RATE;

	ss_printf("PHASE 1(4);;\n");

	write_c.m = read_c.m = mtx;
	write_c.gn_tree_node = GN_TREE;
	write_c.gn_create = GN_LIST_CREATE;
	write_c.gn_wait = GN_LIST_CREATE;
	write_c.access_ch = &access_ch[0];
	write_c.ds_len = dest_dim + 1;
	mxc_setup(&write_c);

	write_delta_c.m = read_c.m = mtx;
	write_delta_c.gn_tree_node = GN_NODE;
	write_delta_c.gn_create = GN_ERROR_NORETRY;
	write_delta_c.gn_wait = GN_ERROR_NORETRY;
	write_delta_c.access_ch = &access_delta_ch[0];
	write_delta_c.ds_len = mtx->total_levels + 1;
	mxc_setup(&write_delta_c);

	write_rr_c.m = read_c.m = mtx;
	write_rr_c.gn_tree_node = GN_NODE;
	write_rr_c.gn_create = GN_ERROR_NORETRY;
	write_rr_c.gn_wait = GN_ERROR_NORETRY;
	write_rr_c.access_ch = &rr_ch;
	write_rr_c.ds_len = 1;
	mxc_setup(&write_rr_c);

	read_c.gn_tree_node = GN_NODE;
	read_c.gn_create = GN_ERROR_NORETRY;
	read_c.gn_wait = GN_ERROR_NORETRY;
	read_c.access_ch = &access_ch[0];
	read_c.ds_len = dest_dim + 1;
	mxc_setup(&read_c);

	write_hem_c.m = read_c.m = mtx;
	write_hem_c.gn_tree_node = GN_NODE;
	write_hem_c.gn_create = GN_ERROR_NORETRY;
	write_hem_c.gn_wait = GN_ERROR_NORETRY;
	write_hem_c.access_ch = &access_ch[0];
	write_hem_c.ds_len = dest_dim + 1;
	mxc_setup(&write_hem_c);


	write_parameters(mtx);
	set_mode_cals(mtx);

	ss_printf("PHASE 2 :: Reading the data\n");

	ix[0] = ix[1] = src_dim+1;
	vp.ix_size = ix;
	vp.dim = 2;
	vp.default_data = &zero;
	src_mtx = mxt_alloc_vector(
			&mx_type_double_v,
			MD_DALLOC,
			&vp,0);
	get_matrix_dh_set(&src_mtx_ds,src_mtx);
	src_mtx_ptr = src_mtx_ds.offset;

	ix[0] = src_dim+1;
	ix[1] = dest_dim+1;
	vp.ix_size = ix;
	vp.dim = 2;
	vp.default_data = &zero;
	sd_mtx = mxt_alloc_vector(
			&mx_type_double_v,
			MD_DALLOC,
			&vp,0);
	get_matrix_dh_set(&sd_mtx_ds,sd_mtx);
	sd_mtx_ptr = sd_mtx_ds.offset;

	invalid_command = 1;

	for ( i = inp ; i < argc ; i ++ )
		read_file(argv[i],phase_2);

	flush_mx_cache(&write_c,0);
	calc_avg_mtx(mtx);
	flush_memory(0);
	
	ss_printf("dest_min = %f\n",dest_min[0]);
	ss_printf("PHASE 3 :: Hem control 1\n");

	set_matrix_env(mtx,"create-node","disable");
	handling_hem(mtx,0,0);

mem_test("PHASE 4");
	ss_printf("PHASE 4 :: Multi resolution layering\n");

	dc_min = d_alloc(sizeof(INTEGER64)*(src_dim+1));
	dc_max = d_alloc(sizeof(INTEGER64)*(src_dim+1));

	for ( i = 0 ; i < src_dim ; i ++ ) {
		dc_min[i+1] = margin[i];
		dc_max[i+1] = max[i] - min[i] + margin[i];
	}
	dc_min[0] = dc_max[0] = 0;

	flush_memory(0);
	load_indicate(1);
	matrix_peano_trigger(mtx,dc_min,dc_max,MI_EDIT_1_TP);
	sync_matrix(mtx);
	load_indicate(0);

	ss_printf("PHASE 5 :: Interpolation the data holes\n");
	start_level = extrapolation_1(mtx,-1,-1);

//goto end;
	ss_printf("PHASE 6 :: Extrapolation in low resolution layers\n");
	
	for ( lev = start_level+1 ; lev < mtx->total_levels ; lev ++ )
		extrapolation_3(mtx,lev,-1);

	ss_printf("PHASE 7 :: Extrapolation in high resolution layers\n");
	
	for ( lev = start_level-1 ; lev >= 0 ; lev -- ) {
		extrapolation_5(mtx,lev);
		handling_hem(mtx,lev,1);
	}
	

	ss_printf("PHASE 8 :: Polation Error Estimatiion\n");
	
	polation_error_estimation_1(mtx);
	for ( lev = 1 ; lev < mtx->total_levels ; lev ++ )
		polation_error_estimation_2(mtx,lev);

/*
	ss_printf("PHASE 8 :: Resolution Rate\n");
	
	for ( lev = 0 ; lev < mtx->total_levels ; lev ++ )
		rr_1(mtx,lev);
*/

	ss_printf("PHASE 9 :: Multi resolution layering\n");

	flush_memory(0);
	matrix_peano_trigger(mtx,dc_min,dc_max,MI_EDIT_2_TP);

	if ( dest_dim != src_dim ) {
		ss_printf("END OF TASK\n");
		ss_printf("Reverse matrix is not generated because dest_dim != src_dim\n");
		goto end;
	}

	ss_printf("PHASE 10 :: Reverse Matrix\n");

	reverse_matrix(mtx,argv[2]);


end:
	flush_memory(1);
	close_matrix(mtx);
	return 0;
}

