示例#1
0
void 
coarsen_klv (
/* Coarsen until nvtxs < vmax, compute and uncoarsen. */
    struct vtx_data **graph,	/* array of vtx data for graph */
    int nvtxs,		/* number of vertices in graph */
    int nedges,		/* number of edges in graph */
    int using_vwgts,		/* are vertices weights being used? */
    int using_ewgts,		/* are edge weights being used? */
    float *term_wgts[],		/* weights for terminal propogation */
    int igeom,                /* dimension for geometric information */
    float **coords,               /* coordinates for vertices */
    int vwgt_max,		/* largest vertex weight */
    int *assignment,		/* processor each vertex gets assigned to */
    double *goal,			/* desired set sizes */
    int architecture,		/* 0 => hypercube, d => d-dimensional mesh */
    int (*hops)[MAXSETS],	/* cost of edge between sets */
    int solver_flag,		/* which eigensolver to use */
    int ndims,		/* number of eigenvectors to calculate */
    int nsets,		/* number of sets being divided into */
    int vmax,			/* largest subgraph to stop coarsening */
    int mediantype,		/* flag for different assignment strategies */
    int mkconnected,		/* enforce connectivity before eigensolve? */
    double eigtol,		/* tolerence in eigen calculation */
    int nstep,		/* number of coarsenings between RQI steps */
    int step,			/* current step number */
    int **pbndy_list,		/* pointer to returned boundary list */
    double *weights,		/* weights of vertices in each set */
    int give_up		/* has coarsening bogged down? */
)
{
    extern FILE *Output_File;	/* output file or null */
    extern int DEBUG_TRACE;	/* trace the execution of the code */
    extern int DEBUG_COARSEN;	/* debug flag for coarsening */
    extern double COARSEN_RATIO_MIN;	/* vtx reduction demanded */
    extern int COARSEN_VWGTS;	/* use vertex weights while coarsening? */
    extern int COARSEN_EWGTS;	/* use edge weights while coarsening? */
    extern int LIMIT_KL_EWGTS;	/* limit edges weights in KL? */
    extern int COARSE_KLV;	/* apply klv as a smoother? */
    extern int COARSE_BPM;	/* apply bipartite matching/flow as a smoother? */
    extern double KL_IMBALANCE;	/* fractional imbalance allowed in KL */
    struct vtx_data **cgraph;	/* array of vtx data for coarsened graph */
    double    new_goal[MAXSETS];/* new goal if not using vertex weights */
    double   *real_goal;	/* chooses between goal and new_goal */
    double    total_weight;	/* total weight of vertices */
    double    goal_weight;	/* total weight of vertices in goal */
    float    *cterm_wgts[MAXSETS];	/* terminal weights for coarse graph */
    float    *new_term_wgts[MAXSETS];	/* modified for Bui's method */
    float   **real_term_wgts;	/* which of previous two to use */
    float     ewgt_max;		/* largest edge weight in graph */
    float    *twptr = NULL;	/* loops through term_wgts */
    float    *twptr_save = NULL;/* copy of twptr */
    float    *ctwptr;		/* loops through cterm_wgts */
    float   **ccoords;		/* coarse graph coordinates */
    int      *v2cv;		/* mapping from vtxs to coarse vtxs */
    int      *flag;		/* scatter array for coarse bndy vtxs */
    int      *bndy_list;	/* list of vertices on boundary */
    int      *cbndy_list;	/* list of vertices of coarse graph on boundary */
    int    *cassignment;	/* set assignments for coarsened vertices */
    int       flattened;	/* was this graph flattened? */
    int       list_length;	/* length of boundary vtx list */
    int       cnvtxs;		/* number of vertices in coarsened graph */
    int       cnedges;		/* number of edges in coarsened graph */
    int       cvwgt_max;	/* largest vertex weight in coarsened graph */
    int       nextstep;		/* next step in RQI test */
    int       max_dev;		/* largest allowed deviation from balance */
    int       i, j;		/* loop counters */
    int       find_bndy(), flatten();
    double    find_maxdeg();
    void      makevwsqrt(), make_connected(), print_connected(), eigensolve();
    void      make_unconnected(), assign(), klvspiff(), coarsen1(), free_graph();
    void      compress_ewgts(), restore_ewgts(), count_weights(), bpm_improve();
    void      simple_part();

    if (DEBUG_COARSEN > 0 || DEBUG_TRACE > 0) {
	printf("<Entering coarsen_kl, step=%d, nvtxs=%d, nedges=%d, vmax=%d>\n",
	       step, nvtxs, nedges, vmax);
    }

    /* Is problem small enough to solve? */
    if (nvtxs <= vmax || give_up) {
	real_goal = goal; 

        simple_part(graph, nvtxs, assignment, nsets, 1, real_goal);
        list_length = find_bndy(graph, nvtxs, assignment, 2, &bndy_list);

        count_weights(graph, nvtxs, assignment, nsets + 1, weights, 1);

        max_dev = (step == 0) ? vwgt_max : 5 * vwgt_max;
        total_weight = 0;
        for (i = 0; i < nsets; i++)
            total_weight += real_goal[i];

	if (max_dev > total_weight) max_dev = vwgt_max;
        goal_weight = total_weight * KL_IMBALANCE / nsets;
        if (goal_weight > max_dev)
            max_dev = goal_weight;

	if (COARSE_KLV) {
            klvspiff(graph, nvtxs, assignment, real_goal,
                 max_dev, &bndy_list, weights);
	}
	if (COARSE_BPM) {
	    bpm_improve(graph, assignment, real_goal, max_dev, &bndy_list,
			    weights, using_vwgts);
	}
	*pbndy_list = bndy_list;
	return;
    }

    /* Otherwise I have to coarsen. */
    flattened = FALSE;
    if (coords != NULL) {
        ccoords = smalloc(igeom * sizeof(float *));
    }
    else {
        ccoords = NULL;
    }
    if (FLATTEN && step == 0) {
	flattened = flatten(graph, nvtxs, nedges, &cgraph, &cnvtxs, &cnedges, &v2cv,
			    using_ewgts && COARSEN_EWGTS,
			    igeom, coords, ccoords);
    }
    if (!flattened) {
	coarsen1(graph, nvtxs, nedges, &cgraph, &cnvtxs, &cnedges, &v2cv,
		 igeom, coords, ccoords,
		 using_ewgts && COARSEN_EWGTS);
    }

    if (term_wgts[1] != NULL) {
	twptr = smalloc((cnvtxs + 1) * (nsets - 1) * sizeof(float));
	twptr_save = twptr;
	for (i = (cnvtxs + 1) * (nsets - 1); i; i--) {
	    *twptr++ = 0;
	}
	twptr = twptr_save;
	for (j = 1; j < nsets; j++) {
	    cterm_wgts[j] = twptr;
	    twptr += cnvtxs + 1;
	}
	for (j = 1; j < nsets; j++) {
	    ctwptr = cterm_wgts[j];
	    twptr = term_wgts[j];
	    for (i = 1; i < nvtxs; i++) {
		ctwptr[v2cv[i]] += twptr[i];
	    }
	}
    }

    else {
	cterm_wgts[1] = NULL;
    }

    /* If coarsening isn't working very well, give up and partition. */
    give_up = FALSE;
    if (nvtxs * COARSEN_RATIO_MIN < cnvtxs && cnvtxs > vmax && !flattened) {
	printf("WARNING: Coarsening not making enough progress, nvtxs = %d, cnvtxs = %d.\n",
	       nvtxs, cnvtxs);
	printf("         Recursive coarsening being stopped prematurely.\n");
	if (Output_File != NULL) {
	    fprintf(Output_File,
		    "WARNING: Coarsening not making enough progress, nvtxs = %d, cnvtxs = %d.\n",
		    nvtxs, cnvtxs);
	    fprintf(Output_File,
		    "         Recursive coarsening being stopped prematurely.\n");
	}
	give_up = TRUE;
    }

    /* Now recurse on coarse subgraph. */
    if (COARSEN_VWGTS) {
	cvwgt_max = 0;
	for (i = 1; i <= cnvtxs; i++) {
	    if (cgraph[i]->vwgt > cvwgt_max)
		cvwgt_max = cgraph[i]->vwgt;
	}
    }

    else
	cvwgt_max = 1;

    cassignment = smalloc((cnvtxs + 1) * sizeof(int));
    if (flattened)
	nextstep = step;
    else
	nextstep = step + 1;
    coarsen_klv(cgraph, cnvtxs, cnedges, COARSEN_VWGTS, COARSEN_EWGTS, cterm_wgts,
		igeom, ccoords, cvwgt_max, cassignment, goal, architecture, hops,
		solver_flag, ndims, nsets, vmax, mediantype, mkconnected,
		eigtol, nstep, nextstep, &cbndy_list, weights, give_up);

    /* Interpolate assignment back to fine graph. */
    for (i = 1; i <= nvtxs; i++) {
	assignment[i] = cassignment[v2cv[i]];
    }

    /* Construct boundary list from coarse boundary list. */
    flag = smalloc((cnvtxs + 1) * sizeof(int));
    for (i = 1; i <= cnvtxs; i++) {
	flag[i] = FALSE;
    }
    for (i = 0; cbndy_list[i]; i++) {
	flag[cbndy_list[i]] = TRUE;
    }

    list_length = 0;
    for (i = 1; i <= nvtxs; i++) {
	if (flag[v2cv[i]])
	    ++list_length;
    }

    bndy_list = smalloc((list_length + 1) * sizeof(int));

    list_length = 0;
    for (i = 1; i <= nvtxs; i++) {
	if (flag[v2cv[i]])
	    bndy_list[list_length++] = i;
    }
    bndy_list[list_length] = 0;

    sfree(flag);
    sfree(cbndy_list);


    /* Free the space that was allocated. */
    sfree(cassignment);
    if (twptr_save != NULL) {
	sfree(twptr_save);
	twptr_save = NULL;
    }
    free_graph(cgraph);
    sfree(v2cv);

    /* Smooth using KL or BPM every nstep steps. */
    if (!(step % nstep) && !flattened) {
	if (!COARSEN_VWGTS && step != 0) {	/* Construct new goal */
	    goal_weight = 0;
	    for (i = 0; i < nsets; i++)
		goal_weight += goal[i];
	    for (i = 0; i < nsets; i++)
		new_goal[i] = goal[i] * (nvtxs / goal_weight);
	    real_goal = new_goal;
	}
	else
	    real_goal = goal;

	if (LIMIT_KL_EWGTS) {
	    find_maxdeg(graph, nvtxs, using_ewgts, &ewgt_max);
	    compress_ewgts(graph, nvtxs, nedges, ewgt_max,
			   using_ewgts);
	}

	/* If not coarsening ewgts, then need care with term_wgts. */
	if (!using_ewgts && term_wgts[1] != NULL && step != 0) {
	    twptr = smalloc((nvtxs + 1) * (nsets - 1) * sizeof(float));
	    twptr_save = twptr;
	    for (j = 1; j < nsets; j++) {
		new_term_wgts[j] = twptr;
		twptr += nvtxs + 1;
	    }

	    for (j = 1; j < nsets; j++) {
		twptr = term_wgts[j];
		ctwptr = new_term_wgts[j];
		for (i = 1; i <= nvtxs; i++) {
		    if (twptr[i] > .5)
			ctwptr[i] = 1;
		    else if (twptr[i] < -.5)
			ctwptr[i] = -1;
		    else
			ctwptr[i] = 0;
		}
	    }
	    real_term_wgts = new_term_wgts;
	}
	else {
	    real_term_wgts = term_wgts;
	    new_term_wgts[1] = NULL;
	}

	max_dev = (step == 0) ? vwgt_max : 5 * vwgt_max;
	total_weight = 0;
	for (i = 0; i < nsets; i++) {
	    total_weight += real_goal[i];
	}
	if (max_dev > total_weight)
	    max_dev = vwgt_max;
	goal_weight = total_weight * KL_IMBALANCE / nsets;
	if (goal_weight > max_dev) {
	    max_dev = goal_weight;
	}

	if (!COARSEN_VWGTS) {
	    count_weights(graph, nvtxs, assignment, nsets + 1, weights,
			  (vwgt_max != 1));
	}

	if (COARSE_KLV) {
	    klvspiff(graph, nvtxs, assignment, real_goal,
		     max_dev, &bndy_list, weights);
	}
	if (COARSE_BPM) {
	    bpm_improve(graph, assignment, real_goal, max_dev, &bndy_list,
			weights, using_vwgts);
	}

	if (real_term_wgts != term_wgts && new_term_wgts[1] != NULL) {
	    sfree(real_term_wgts[1]);
	}

	if (LIMIT_KL_EWGTS)
	    restore_ewgts(graph, nvtxs);
    }

    *pbndy_list = bndy_list;

    if (twptr_save != NULL) {
	sfree(twptr_save);
	twptr_save = NULL;
    }

    /* Free the space that was allocated. */
    if (ccoords != NULL) {
        for (i = 0; i < igeom; i++)
            sfree(ccoords[i]);
        sfree(ccoords);
    }

    if (DEBUG_COARSEN > 0) {
	printf(" Leaving coarsen_klv, step=%d\n", step);
    }
}
示例#2
0
/* Perform KL between two sets. */
int 
kl_refine (
    struct vtx_data **graph,	/* graph data structure */
    struct vtx_data **subgraph,	/* space for subgraph to refine */
    struct bilist *set_list,	/* lists of vtxs in each set */
    struct bilist *vtx_elems,	/* start of storage for lists */
    int *new_assign,		/* set assignments for all vertices */
    int set1,
    int set2,		/* two sets being refined */
    int *glob2loc,		/* maps vertices to subgraph vertices */
    int *loc2glob,		/* maps subgraph vertices to vertices */
    int *sub_assign,		/* new assignment for subgraphs */
    int *old_sub_assign,	/* current assignment for subgraphs */
    int *degrees,		/* space for forming subgraphs */
    int using_ewgts,		/* are edge weights being used? */
    int (*hops)[MAXSETS],	/* KL set preferences */
    double *goal,			/* desired set sizes */
    int *sizes,		/* number of vertices in different sets */
    float *term_wgts[],		/* space for terminal propagation weights */
    int architecture,		/* 0 => hypercube, d => d-dimensional mesh */
    int mesh_dims[3]		/* if mesh, how big is it? */
)
{
    extern int TERM_PROP;	/* perform terminal propagation? */
    extern double KL_IMBALANCE;	/* fractional imbalance allowed in KL */
    struct bilist *ptr;		/* element in set_list */
    double    subgoal[2];	/* goal within two subgraphs */
    double    weights[2];	/* weights for each set */
    double    maxdeg;		/* largest degree of a vertex */
    double    ratio;		/* set sizes / goals */
    int      *null_ptr;		/* argument to klspiff */
    int       vwgt_max;		/* largest vertex weight */
    int       max_dev;		/* largest set deviation allowed in KL */
    int       subnvtxs;		/* number of vtxs in subgraph */
    int       vwgt_sum1;	/* sum of vertex wgts in first set */
    int       vwgt_sum2;	/* sum of vertex wgts in second set */
    int       subnedges;	/* number of edges in subgraph */
    int       setA, setB;	/* two sets being refined */
    int       nsame;		/* number of vertices not moved */
    int       vtx;		/* vertex in subgraph */
    int       i;		/* loop counter */
    double    find_maxdeg();
    void      make_maps_ref(), make_subgraph(), remake_graph();
    void      klspiff(), make_terms_ref(), count_weights();

    /* Compute all the quantities I'll need. */
    null_ptr = NULL;
    make_maps_ref(graph, set_list, vtx_elems, new_assign, sub_assign, 
	set1, set2, glob2loc, loc2glob, &subnvtxs, &vwgt_max,
	&vwgt_sum1, &vwgt_sum2);

    for (i = 1; i <= subnvtxs; i++)
	old_sub_assign[i] = sub_assign[i];

    /* Set up goals for this KL invocation. */
    ratio = (vwgt_sum1 + vwgt_sum2) / (goal[set1] + goal[set2]);
    subgoal[0] = ratio * goal[set1];
    subgoal[1] = ratio * goal[set2];

    if (TERM_PROP) {
        make_terms_ref(graph, using_ewgts, subnvtxs, loc2glob,
	   set1, set2, new_assign, architecture, mesh_dims, term_wgts);
    }

    /* New_assign has overwritten set2 with set1. */
    make_subgraph(graph, subgraph, subnvtxs, &subnedges, new_assign, set1,
		  glob2loc, loc2glob, degrees, using_ewgts);

    maxdeg = find_maxdeg(subgraph, subnvtxs, using_ewgts, (float *) NULL);

    count_weights(subgraph, subnvtxs, sub_assign, 2, weights, (vwgt_max != 1));

    max_dev = vwgt_max;
    ratio = (subgoal[0] + subgoal[1]) * KL_IMBALANCE / 2;
    if (ratio > max_dev) {
	max_dev = ratio;
    }

    klspiff(subgraph, subnvtxs, sub_assign, 2, hops, subgoal,
	    term_wgts, max_dev, maxdeg, using_ewgts, &null_ptr, weights);

    /* Figure out which modification leaves most vertices intact. */
    nsame = 0;
    for (i = 1; i <= subnvtxs; i++) {
	if (old_sub_assign[i] == sub_assign[i])
	    nsame++;
    }
    if (2 * nsame > subnvtxs) {
	setA = set1;
	setB = set2;
    }
    else {
	setA = set2;
	setB = set1;
    }

    /* Now update the assignments. */
    sizes[setA] = sizes[setB] = 0;
    for (i = 1; i <= subnvtxs; i++) {
	vtx = loc2glob[i];
	/* Update the set_lists. */
	ptr = &(vtx_elems[vtx]);
	if (ptr->next != NULL) {
	    ptr->next->prev = ptr->prev;
	}
	if (ptr->prev != NULL) {
	    ptr->prev->next = ptr->next;
	}

	if (sub_assign[i] == 0) {
	    new_assign[vtx] = (int) setA;
	    ++sizes[setA];
	    ptr->next = set_list[setA].next;
	    if (ptr->next != NULL) 
	        ptr->next->prev = ptr;
	    ptr->prev = &(set_list[setA]);
	    set_list[setA].next = ptr;
	}
	else {
	    new_assign[vtx] = (int) setB;
	    ++sizes[setB];
	    ptr->next = set_list[setB].next;
	    if (ptr->next != NULL) 
	        ptr->next->prev = ptr;
	    ptr->prev = &(set_list[setB]);
	    set_list[setB].next = ptr;
	}
    }

    remake_graph(subgraph, subnvtxs, loc2glob, degrees, using_ewgts);

    return(nsame != subnvtxs);
}
示例#3
0
int main(int argc, char *argv[])
{
	struct Cell_head cellhd; 
        struct Range range;
        char *name;                     /* input raster name */
	char *result;                   /* output raster name */
        char *mapset;                   /* mapset name */
	DCELL *inrast;                  /* input buffer */
	DCELL *outrast;                 /* output buffer */
	int row,col;
	int infd, outfd;                /* file descriptor */
	int verbose;
        double *weights;                /* array of weights */
        DCELL **D_rows;
        DCELL *tmp;
        int nrows;                      
        int ncols;
        double min, max;                /* raster map range */
        
	RASTER_MAP_TYPE data_type;      /* type of the map */
        void *values;                   /* neighborhood values */
        int n,i;                        /* number of neighborhood cells */
        int size;                       /* matrix size */
        double ssigma;                  /* sigma of the spatial part */
        double csigma;                  /* sigma of the color part */
        char title[1024];               /* map title */


	struct GModule *module;         /* GRASS module for parsing arguments */
	struct
	    {
		struct Option *input, *output;
		struct Option *sigma_s, *sigma_c, *size;
		struct Option *title;
	} parm;
	struct
	    {
		struct Flag *quiet;
		struct Flag *print_sigmas;
	} flag;

        /* initialize GIS environment */
	G_gisinit(argv[0]);     /* reads grass env, 
                                   stores program name to 
                                   G_program_name
                                   */

        /* initialize module */
	module = G_define_module();
	module->description = ("Gaussian filter for raster maps.");
					        
	/* Define the different options */
	parm.input = G_define_option() ;
	parm.input->key        = "input";
	parm.input->type       = TYPE_STRING;
	parm.input->required   = YES;
	parm.input->description= ("Name of an input layer" );

	parm.output = G_define_option() ;
	parm.output->key        = "output";
	parm.output->type       = TYPE_STRING;
	parm.output->required   = YES;
	parm.output->description= ("Name of an output layer");

	parm.sigma_s = G_define_option() ;
	parm.sigma_s->key        = "ssigma";
	parm.sigma_s->type       = TYPE_DOUBLE;
	parm.sigma_s->required   = NO;
	parm.sigma_s->description= ("Sigma for space part of the filter\n\t(default: 0.465*((size-1)/2)");

	parm.sigma_c = G_define_option() ;
	parm.sigma_c->key        = "csigma";
	parm.sigma_c->type       = TYPE_DOUBLE;
	parm.sigma_c->required   = NO;
	parm.sigma_c->description= ("Sigma for color part of the filter\n(default: 0.465*((color_range)/2)");

        parm.size = G_define_option() ;
	parm.size->key        = "size";
	parm.size->type       = TYPE_INTEGER;
	parm.size->required   = YES;
	parm.size->description= ("Size of the matrix (odd number)");

        flag.print_sigmas = G_define_flag() ;
	flag.print_sigmas->key         = 's' ;
	flag.print_sigmas->description = "Print calculated values for sigmas" ;
        
        flag.quiet = G_define_flag() ;
	flag.quiet->key         = 'q' ;
	flag.quiet->description = "Quiet" ;
        
        /* options and flags pareser */
	if (G_parser(argc, argv))
		exit (-1);
		
        /* stores options and flags to variables */
	name    = parm.input->answer;
	result  = parm.output->answer;
	verbose = (! flag.quiet->answer);
        sscanf(parm.size->answer, "%d", &size);
        if (!parm.sigma_s->answer)
            ssigma = 0.465*((size-1)/2);
        else 
            sscanf(parm.sigma_s->answer, "%lf", &ssigma);
      
        

        /* controlling the input values */
        if (size%2 == 0) 
            G_fatal_error("Size <%d> is not odd number", size);

	/* returs NULL if the map was not found in any mapset, 
         * mapset name otherwise*/
	mapset = G_find_cell2 (name, ""); 
        if (mapset == NULL)
                G_fatal_error ("cell file [%s] not found", name);

       /* color sigma next */
        if (!parm.sigma_c->answer) {
            if (G_read_range(name, mapset, &range) < 0) 
                G_fatal_error("Could not read the raster map range");
                
            /* for raster maps with range from 0-255 the result
             * should be around 60 
             */
            min = (double)range.min;
            max = (double)range.max;
            csigma = 0.456*(max - min)/2;
        }
        else
            sscanf(parm.sigma_c->answer, "%lf", &csigma);
        
        /* print if appropriate */
        if (flag.print_sigmas->answer)
            printf("Space sigma: %f\nColor sigma: %f\n", ssigma, csigma);

 
        if (G_legal_filename (result) < 0)
                G_fatal_error ("[%s] is an illegal name", result);

        /* count weights */
        weights = (double *)malloc(size * size * sizeof(double));
        /* stores values of gauss. bell into 'weigts'*/
        count_weights(weights, size, ssigma);
        
	/* determine the inputmap type (CELL/FCELL/DCELL) */
	data_type = G_raster_map_type(name, mapset);

        /* G_open_cell_old - returns file destriptor (>0) */
	if ( (infd = G_open_cell_old (name, mapset)) < 0)
		G_fatal_error ("Cannot open cell file [%s]", name);

        /* controlling, if we can open input raster */
	if (G_get_cellhd (name, mapset, &cellhd) < 0)
		G_fatal_error ("Cannot read file header of [%s]", name);

	/* Allocate input buffer */
	inrast = G_allocate_raster_buf(data_type);
	
	/* Allocate output buffer, use input map data_type */
	nrows = G_window_rows();
	ncols = G_window_cols();
	outrast = G_allocate_d_raster_buf();


        /* Allocate values buffers */
        values = (DCELL *) malloc(size * size * sizeof(DCELL));
        
        /* allocating memory for rows */
        D_rows = (DCELL **)malloc(size * sizeof(DCELL));
        for (i = 0; i < size; i++) {
            D_rows[i] = G_allocate_raster_buf(DCELL_TYPE);
        }
        
        if (values == NULL) 
            G_fatal_error("Cannot allocate memory");

        /* controlling, if we can write the raster */
	if ( (outfd = G_open_raster_new (result, data_type)) < 0)
		G_fatal_error ("Could not open <%s>",result);

        /* write first rows as NULL values */
        for (row = 0; row < size/2; row++) {
            G_set_d_null_value(outrast, ncols);
            if (G_put_d_raster_row (outfd, outrast) < 0)
                G_fatal_error ("Cannot write to <%s>",result);
        }

        /* allocate first size/2 rows */
        for (row = 0; row < size; row++) 
            if (G_get_d_raster_row(infd, D_rows[row], row) < 0)
		G_fatal_error ("Could not open <%s>",result);
            
        /****************************************************************/
        /* for each row inside the region */
	for ( row = size/2; row < nrows - size/2; row++) {
            

		if (verbose)
		    G_percent (row, nrows, 2);
                
                /* allocate new last row */
               G_get_d_raster_row(infd, D_rows[size-1], row+(size/2));

                /*process the data */
		for (col=0; col < ncols; col++){

                    /* skip the outside columns */
                    if ( (col - size/2) < 0 || ncols <= (col + size/2)) {
                        G_set_d_null_value(outrast, 1);
                    }
                    /* work only with columns, which are inside */
                    else {

                        /* store values of the matrix into arry 'values', 'n' is
                         * number of elements of the matrix */
                        n = D_gather(infd, values, D_rows, col, row,size);
                        ((DCELL *)outrast)[col] = D_bilateral(values, ssigma, csigma, size, weights);
		    }
                } /* for each column */

                /* write raster row to output raster file */
		G_put_d_raster_row (outfd, outrast);

                /* switch rows */
		tmp = D_rows[0];
                for (i = 0; i < size; i++){
                   D_rows[i] = D_rows[i + 1];
                }
		D_rows[size-1] = tmp;

	} /* for each row */
        
        /* write last rows as NULL values */
        for (i = 0; i < size/2; i++) {
            G_set_d_null_value(outrast, ncols);
            G_put_d_raster_row (outfd, outrast);
        }
 
        /* memory cleaning */
	G_free(outrast);
	G_free(inrast);
        G_free(values);

        for (i = 0; i < size; i++) {
            G_free(D_rows[i]);
        }
        free((void *) D_rows);


        /* closing rastr files */
	G_close_cell (infd);
	G_close_cell (outfd);

        /* set the map title */
        sprintf(title, "Bilateral filter of %s with %dx%d matrix: ssigma %.3f, csigma %.3f", name, size, size, ssigma, csigma ); 
        G_put_cell_title (result, title ); 

	return 0;
}