[GRASS-SVN] r59305 - in grass/branches/releasebranch_6_4/raster/r.li: . r.li.cwed r.li.daemon r.li.dominance r.li.edgedensity r.li.mpa r.li.mps r.li.padcv r.li.padrange r.li.padsd r.li.patchdensity r.li.patchnum r.li.pielou r.li.renyi r.li.richness r.li.shannon r.li.shape r.li.simpson

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Mar 24 04:43:14 PDT 2014


Author: neteler
Date: 2014-03-24 04:43:14 -0700 (Mon, 24 Mar 2014)
New Revision: 59305

Added:
   grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/weight.csv
Removed:
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/index.h
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/main.c.unused
Modified:
   grass/branches/releasebranch_6_4/raster/r.li/TODO
   grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/cwed.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/description.html
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/Makefile
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.h
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.h
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.h
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/description.html
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.h
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.h
   grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/worker.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.dominance/dominance.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.edgedensity/edgedensity.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.mpa/mpa.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.mps/mps.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.padcv/padcv.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.padrange/padrange.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.padsd/padsd.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.patchdensity/main.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.patchnum/main.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.pielou/pielou.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.renyi/renyi.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.richness/richness.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.shannon/shannon.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.shape/main.c
   grass/branches/releasebranch_6_4/raster/r.li/r.li.simpson/simpson.c
Log:
r.li.*: backport of rewrite in trunk (trac #1214)

Modified: grass/branches/releasebranch_6_4/raster/r.li/TODO
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/TODO	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/TODO	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,5 +1,54 @@
 TODO list
+=========
 
+Brute-force testing
+-------------------
+# TODO: change to/add 3x3 example
+
+# 7x7 moving window test:
+# still Spearfish...
+
+# created as described in EXAMPLES, moving window r.li.setup/description.html:
+echo "SAMPLINGFRAME 0|0|1|1
+SAMPLEAREA -1|-1|0.015021459227467811|0.011058451816745656
+MOVINGWINDOW" > $HOME/.r.li/history/movwindow7
+
+export GRASS_OVERWRITE=1
+g.region rast=landcover.30m -p
+r.mapcalc "forests = if(landcover.30m >= 41 && landcover.30m <= 43,1,null())"
+
+MEASURE="dominance edgedensity mpa mps padcv padrange padsd patchdensity patchnum pielou richness shannon shape simpson"
+
+for mymeasure in $MEASURE ; do
+  r.li.${mymeasure} input=forests conf=movwindow7 out=forests_${mymeasure}_mov7
+  r.univar forests_${mymeasure}_mov7
+done
+
+# also alpha:
+r.li.renyi input=forests conf=movwindow7 out=forests_renyi_mov7_a06 alpha=0.6
+r.univar forests_renyi_mov7_a06
+
+echo "End of r.li tests"
+
+
+========================
+North Carolina tests
+
+echo "SAMPLINGFRAME 0|0|1|1
+SAMPLEAREA 0.0|0.0|1.0|1.0" > $HOME/.r.li/history/landsat_test
+
+g.region rast=lsat7_2002_40 -p
+r.li.shannon input=lsat7_2002_40 conf=landsat_test out=landsat_shannon
+--> Result written to ASCII file <$HOME/.r.li/output/landsat_shannon>
+
+
+
+===============================================================
+GRASS 6
+-------
+
+TODO: backport all GRASS 7 fixes
+
 A few remaining things should be done soon:
 - add relevant references
 - use English variable names in C code

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/cwed.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/cwed.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/cwed.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,19 +1,26 @@
-/*
- * \brief calculates contrast weighted edge density index
+
+/****************************************************************************
  *
- *   \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.cwed
+ * AUTHOR(S):    Serena Pallecchi student of Computer Science University of Pisa (Italy)
+ *               Commission from Faunalia Pontedera (PI) www.faunalia.it
+ *               Markus Metz
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
- *       
- */
+ * PURPOSE:      calculates contrast weighted edge density index
+ * COPYRIGHT:    (C) 2006-2014 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
 
+
+#include <fcntl.h>		/* for O_RDONLY usage */
+
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include <fcntl.h>		/* for O_RDONLY usage */
-
 #include "../r.li.daemon/defs.h"
 #include "../r.li.daemon/daemon.h"
 
@@ -25,6 +32,7 @@
 #define _PRES 1
 #define _ERR -1
 
+rli_func contrastWeightedEdgeDensity;
 int calculate(int fd, struct area_entry *ad, Coppie * cc, long totCoppie,
 	      double *result);
 int calculateD(int fd, struct area_entry *ad, Coppie * cc, long totCoppie,
@@ -80,12 +88,10 @@
 				double *result)
 {
     double indice = 0;		/* the result */
-    struct Cell_head hd;
     int i = 0;
     int file_fd = -1;
     int l;			/*number of read byte */
     int ris = 0;
-    char *mapset;
     char *file;
     char *strFile;
     char row[NMAX];		/* to read the file */
@@ -146,14 +152,6 @@
 	return RLI_ERRORE;
     }
 
-    mapset = G_find_cell(ad->raster, "");
-
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1) {
-	G_fatal_error("can't read raster header");
-	return RLI_ERRORE;
-    }
-
-
     for (i = 0; i < totRow; i++) {
 	long num = 0;
 	char **b;
@@ -293,14 +291,16 @@
     int i = 0, j;
     int mask_fd = -1;
     int masked = FALSE;
-    int *mask_corr, *mask_sup;
+    int *mask_corr = NULL, *mask_sup = NULL, *mask_tmp;
 
-    CELL *buf_corr, *buf_sup;
+    CELL *buf_corr, *buf_sup, *buf_null;
     CELL prevCell, corrCell, supCell;
 
     generic_cell c1;
     generic_cell c2;
 
+    if (ad->rl < 2)
+	G_fatal_error(_("Row cache is too small"));
 
     /* open mask if needed */
     if (ad->mask == 1) {
@@ -314,32 +314,30 @@
 	    G_fatal_error("malloc mask_corr failed");
 	    return RLI_ERRORE;
 	}
-
 	mask_sup = G_malloc(ad->cl * sizeof(int));
 	if (mask_sup == NULL) {
-	    G_fatal_error("malloc mask_sup failed");
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_corr[j] = 0;
 
 	masked = TRUE;
     }
 
-    buf_sup = G_allocate_cell_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
+    buf_null = G_allocate_cell_buf();
+    if (buf_null == NULL) {
+	G_fatal_error("malloc buf_null failed");
 	return RLI_ERRORE;
     }
 
     c1.t = CELL_TYPE;
     c2.t = CELL_TYPE;
 
-    buf_corr = G_allocate_cell_buf();
-    if (buf_corr == NULL) {
-	G_fatal_error("error malloc buf_corr");
-	return RLI_ERRORE;
-    }
+    /*the first time buf_sup is all null */
+    G_set_c_null_value(buf_null + ad->x, ad->cl);
+    buf_sup = buf_null;
 
-    G_set_c_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	/* read row of raster */
 	buf_corr = RLI_get_cell_raster_row(fd, j + ad->y, ad);
@@ -348,6 +346,9 @@
 	}
 	/*read mask if needed */
 	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_corr;
+	    mask_corr = mask_tmp;
 	    if (read(mask_fd, mask_corr, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("reading mask_corr");
 		return RLI_ERRORE;
@@ -357,14 +358,20 @@
 	G_set_c_null_value(&prevCell, 1);
 	G_set_c_null_value(&corrCell, 1);
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf_corr[i + ad->x];
-	    if (masked && mask_corr[i + ad->x] == 0) {
-		area--;
+	    if (masked && mask_corr[i] == 0) {
 		G_set_c_null_value(&corrCell, 1);
 	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
+	    
 	    if (!(G_is_null_value(&corrCell, CELL_TYPE))) {
 		supCell = buf_sup[i + ad->x];
+		if (masked && (mask_sup[i] == 0)) {
+		    G_set_c_null_value(&supCell, 1);
+		}
 
 		/* calculate how many edges the cell has */
 		if (((!G_is_null_value(&prevCell, CELL_TYPE))) &&
@@ -391,11 +398,8 @@
 			return RLI_ERRORE;
 		}
 	    }
-	    prevCell = buf_corr[i + ad->x];
+	    prevCell = corrCell;
 	}
-
-	if (masked)
-	    mask_sup = mask_corr;
     }
 
     /* calcolo dell'indice */
@@ -419,7 +423,8 @@
 	G_free(mask_sup);
     }
 
-    G_free(buf_sup);
+    G_free(buf_null);
+
     return RLI_OK;
 }
 
@@ -434,16 +439,17 @@
     int i = 0, j;
     int mask_fd = -1;
     int masked = FALSE;
-    int *mask_corr, *mask_sup;
+    int *mask_corr = NULL, *mask_sup = NULL, *mask_tmp;
 
-    DCELL *buf_corr, *buf_sup;
+    DCELL *buf_corr, *buf_sup, *buf_null;
     DCELL prevCell, corrCell, supCell;
 
     generic_cell c1;
     generic_cell c2;
 
+    if (ad->rl < 2)
+	G_fatal_error(_("Row cache is too small"));
 
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0) {
@@ -456,29 +462,30 @@
 	    G_fatal_error("malloc mask_corr failed");
 	    return RLI_ERRORE;
 	}
-
 	mask_sup = G_malloc(ad->cl * sizeof(int));
 	if (mask_sup == NULL) {
-	    G_fatal_error("malloc mask_corr failed");
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_corr[j] = 0;
 
 	masked = TRUE;
     }
 
-    buf_sup = G_allocate_d_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
+    buf_null = G_allocate_d_raster_buf();
+    if (buf_null == NULL) {
+	G_fatal_error("malloc buf_null failed");
 	return RLI_ERRORE;
     }
 
     c1.t = DCELL_TYPE;
     c2.t = DCELL_TYPE;
 
-    buf_corr = G_allocate_d_raster_buf();
+    /*the first time buf_sup is all null */
+    G_set_d_null_value(buf_null + ad->x, ad->cl);
+    buf_sup = buf_null;
 
-    G_set_d_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	/* read row of raster */
 	buf_corr = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
@@ -487,6 +494,9 @@
 	}
 	/*read mask if needed */
 	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_corr;
+	    mask_corr = mask_tmp;
 	    if (read(mask_fd, mask_corr, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("reading mask_corr");
 		return RLI_ERRORE;
@@ -495,15 +505,22 @@
 	G_set_d_null_value(&prevCell, 1);
 	G_set_d_null_value(&corrCell, 1);
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf_corr[i + ad->x];
-	    if (masked && mask_corr[i + ad->x] == 0) {
+	    if (masked && mask_corr[i] == 0) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
+
 	    if (!(G_is_null_value(&corrCell, DCELL_TYPE))) {
 		supCell = buf_sup[i + ad->x];
-		/* calculate how many edge the cell has */
+		if (masked && (mask_sup[i] == 0)) {
+		    G_set_d_null_value(&supCell, 1);
+		}
+
+		/* calculate how many edges the cell has */
 		if (((!G_is_null_value(&prevCell, DCELL_TYPE))) &&
 		    (corrCell != prevCell)) {
 		    int r = 0;
@@ -528,11 +545,8 @@
 		}
 
 	    }
-	    prevCell = buf_corr[i + ad->x];
+	    prevCell = corrCell;
 	}
-
-	if (masked)
-	    mask_sup = mask_corr;
     }
 
     /* calcolo dell'indice */
@@ -554,6 +568,9 @@
 	G_free(mask_corr);
 	G_free(mask_sup);
     }
+
+    G_free(buf_null);
+    
     return RLI_OK;
 }
 
@@ -569,16 +586,17 @@
     int i = 0, j;
     int mask_fd = -1;
     int masked = FALSE;
-    int *mask_corr, *mask_sup;
+    int *mask_corr = NULL, *mask_sup = NULL, *mask_tmp;
 
-    FCELL *buf_corr, *buf_sup;
+    FCELL *buf_corr, *buf_sup, *buf_null;
     FCELL prevCell, corrCell, supCell;
 
     generic_cell c1;
     generic_cell c2;
 
+    if (ad->rl < 2)
+	G_fatal_error(_("Row cache is too small"));
 
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0) {
@@ -591,30 +609,27 @@
 	    G_fatal_error("malloc mask_corr failed");
 	    return RLI_ERRORE;
 	}
-
 	mask_sup = G_malloc(ad->cl * sizeof(int));
 	if (mask_sup == NULL) {
-	    G_fatal_error("malloc mask_sup failed");
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_corr[j] = 0;
 
 	masked = TRUE;
     }
 
     /* allocate and inizialize buffers */
-    buf_sup = G_allocate_f_raster_buf();
-    if (buf_sup == NULL) {
+    buf_null = G_allocate_f_raster_buf();
+    if (buf_null == NULL) {
 	G_fatal_error("malloc buf_sup failed");
 	return RLI_ERRORE;
     }
-    G_set_f_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
+    /*the first time buf_sup is all null */
+    G_set_f_null_value(buf_null + ad->x, ad->cl);
+    buf_sup = buf_null;
 
-    buf_corr = G_allocate_f_raster_buf();
-    if (buf_corr == NULL) {
-	G_fatal_error("malloc buf_corr failed");
-	return RLI_ERRORE;
-    }
-
     c1.t = FCELL_TYPE;
     c2.t = FCELL_TYPE;
 
@@ -627,6 +642,9 @@
 	}
 	/*read mask if needed */
 	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_corr;
+	    mask_corr = mask_tmp;
 	    if (read(mask_fd, mask_corr, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("reading mask_corr");
 		return RLI_ERRORE;
@@ -635,21 +653,28 @@
 	G_set_f_null_value(&prevCell, 1);
 	G_set_f_null_value(&corrCell, 1);
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf_corr[i + ad->x];
-	    if (masked && mask_corr[i + ad->x] == 0) {
+	    if (masked && mask_corr[i] == 0) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
+
 	    if (!(G_is_null_value(&corrCell, FCELL_TYPE))) {
 		supCell = buf_sup[i + ad->x];
+		if (masked && (mask_sup[i] == 0)) {
+		    G_set_f_null_value(&supCell, 1);
+		}
 
+		/* calculate how many edges the cell has */
 		if (((!G_is_null_value(&prevCell, FCELL_TYPE))) &&
 		    (corrCell != prevCell)) {
 		    int r = 0;
 
-		    c1.val.dc = corrCell;
-		    c2.val.dc = prevCell;
+		    c1.val.fc = corrCell;
+		    c2.val.fc = prevCell;
 		    r = updateCoppia(cc, c1, c2, totCoppie);
 		    if (r == RLI_ERRORE)
 			return RLI_ERRORE;
@@ -667,11 +692,8 @@
 		}
 
 	    }
-	    prevCell = buf_corr[i + ad->x];
+	    prevCell = corrCell;
 	}
-
-	if (masked)
-	    mask_sup = mask_corr;
     }
 
     /* calcolo dell'indice */
@@ -693,6 +715,9 @@
 	G_free(mask_corr);
 	G_free(mask_sup);
     }
+
+    G_free(buf_null);
+
     return RLI_OK;
 }
 

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/description.html
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/description.html	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/description.html	2014-03-24 11:43:14 UTC (rev 59305)
@@ -42,7 +42,7 @@
 <em>my_conf</em> configuration file (previously defined with
 <em>r.li.setup</em>) and saving results in <em>my_out</em>, run:
 <div class="code"><pre>
-r.li.cwed map=my_map conf=my_conf path=my_file output=my_out \
+r.li.cwed map=my_map conf=my_conf output=my_out \
           path=/path/to/weights.csv
 </pre></div>
 

Added: grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/weight.csv
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/weight.csv	                        (rev 0)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.cwed/weight.csv	2014-03-24 11:43:14 UTC (rev 59305)
@@ -0,0 +1,4 @@
+12,16,0.65
+44,123,0.32
+56,12,0.54
+23,66,0.99

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/Makefile
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/Makefile	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/Makefile	2014-03-24 11:43:14 UTC (rev 59305)
@@ -4,7 +4,7 @@
 
 LIB_NAME = grass_rli.$(GRASS_VERSION_NUMBER)
 
-LIB_OBJS = daemon.o list.o ipc.o worker.o GenericCell.o	avl.o avlID.o
+LIB_OBJS = daemon.o list.o worker.o GenericCell.o avl.o avlID.o
 
 DEPENDENCIES = $(GISDEP) 
 

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -57,7 +57,32 @@
     return root;
 }
 
+void avl_destroy(avl_tree root)
+{
+    struct avl_node *it;
+    struct avl_node *save = root;
 
+    /*
+    Rotate away the left links so that
+    we can treat this like the destruction
+    of a linked list
+    */
+    while((it = save) != NULL) {
+	if (it->left_child == NULL) {
+	    /* No left links, just kill the node and move on */
+	    save = it->right_child;
+	    G_free(it);
+	    it = NULL;
+	}
+	else {
+	    /* Rotate away the left link and check again */
+	    save = it->left_child;
+	    it->left_child = save->right_child;
+	    save->right_child = it;
+	}
+    }
+}
+
 long howManyCell(const avl_tree root, const generic_cell k)
 {
     avl_node *nodo = NULL;

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.h
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.h	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avl.h	2014-03-24 11:43:14 UTC (rev 59305)
@@ -34,6 +34,7 @@
 
 /* prototype of functions */
 avl_tree avl_make(const generic_cell k, const long n);
+void avl_destroy(avl_tree root);
 avl_node *avl_find(const avl_tree root, const generic_cell k);
 int avl_add(avl_tree * root, const generic_cell k, const long n);
 long avl_to_array(avl_node * root, long i, AVL_table * a);

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -49,7 +49,32 @@
     return root;
 }
 
+void avlID_destroy(avlID_tree root)
+{
+    struct avlID_node *it;
+    struct avlID_node *save = root;
 
+    /*
+    Rotate away the left links so that
+    we can treat this like the destruction
+    of a linked list
+    */
+    while((it = save) != NULL) {
+	if (it->left_child == NULL) {
+	    /* No left links, just kill the node and move on */
+	    save = it->right_child;
+	    G_free(it);
+	    it = NULL;
+	}
+	else {
+	    /* Rotate away the left link and check again */
+	    save = it->left_child;
+	    it->left_child = save->right_child;
+	    save->right_child = it;
+	}
+    }
+}
+
 long howManyID(const avlID_tree root, const long k)
 {
     avlID_node *nodo = NULL;

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.h
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.h	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/avlID.h	2014-03-24 11:43:14 UTC (rev 59305)
@@ -29,6 +29,7 @@
 
 /* prototype of functions */
 avlID_tree avlID_make(const long k, const long n);
+void avlID_destroy(avlID_tree root);
 avlID_node *avlID_find(const avlID_tree root, const long k);
 int avlID_add(avlID_tree * root, const long k, const long n);
 long avlID_to_array(avlID_node * root, long i, avlID_table * a);

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -40,27 +40,17 @@
 #define random rand
 #endif
 
-int calculateIndex(char *file, int f(int, char **, struct area_entry *, double *),
+int calculateIndex(char *file, rli_func *f,
 		   char **parameters, char *raster, char *output)
 {
 
     char pathSetup[GPATH_MAX], out[GPATH_MAX], parsed;
-    char *reportChannelName, *random_access_name;
+    char *random_access_name;
     struct History history;
     struct g_area *g;
-    int receiveChannel;
     int res;
-    int i, mypid, doneDir, withoutJob, mv_fd, random_access;
+    int i, doneDir, mv_fd, random_access;
 
-    int num_workers;
-    /* check if environment variable override was set */
-    const char *p = getenv("WORKERS");
-    num_workers = p ? atoi(p) : DEFAULT_WORKERS;
-    if ((num_workers <= 0) || (num_workers > 1e6))
-	G_fatal_error(_("Invalid number of workers: [%s]"), p);
-
-    wd child[num_workers];
-
     /* int mv_rows, mv_cols; */
     struct list *l;
     msg m, doneJob;
@@ -71,48 +61,10 @@
     l->head = NULL;
     l->tail = NULL;
     l->size = 0;
-    mypid = getpid();
 
-    /* create report pipe */
-    reportChannelName = G_tempfile();
-    if (mkfifo(reportChannelName, 0644) == -1)
-	G_fatal_error("Error in pipe creation");
+    worker_init(raster, f, parameters);
 
-    /*###############################################
-       --------------create childs-------------------
-       ############################################### */
-
-    i = 0;
-    while (i < num_workers) {
-	int childpid;
-
-	/*creating pipe */
-	child[i].pipe = G_tempfile();
-	if (mkfifo(child[i].pipe, 0755) == -1)
-	    G_fatal_error(_("Error in pipe creation"));
-	childpid = fork();
-	if (childpid) {
-	    /*father process */
-	    child[i].pid = childpid;
-	    child[i].channel = open(child[i].pipe, O_WRONLY | O_CREAT, 0755);
-
-	    if (child[i].channel == -1) {
-		G_fatal_error(_("Error opening channel %i"), i);
-	    }
-	    i++;
-	}
-	else {
-	    /*child process */
-	    worker(raster, f, reportChannelName, child[i].pipe, parameters);
-	    exit(0);
-	}
-    }
-
-    /*open reportChannel */
-    receiveChannel = open(reportChannelName, O_RDONLY, 0755);
-
-
-    /*########################################################      
+    /*#########################################################
        -----------------create area queue----------------------
        ######################################################### */
 
@@ -124,6 +76,7 @@
 	file += strlen(testpath);
 
     /* TODO: check if this path is portable */
+    /* TODO: use G_rc_path() */
     sprintf(pathSetup, "%s/.r.li/history/%s", G_home(), file);
     G_debug(1, "r.li.daemon pathSetup: [%s]", pathSetup);
     parsed = parseSetup(pathSetup, l, g, raster);
@@ -150,10 +103,17 @@
 	/* text file output */
 	/* check if ~/.r.li/output exists */
 	sprintf(out, "%s/.r.li/", G_home());
+	doneDir = G_mkdir(out);
+	if (doneDir == -1 && errno != EEXIST)
+	    G_fatal_error(_("Cannot create %s/.r.li/ directory"), G_home());
 
+	/* check if ~/.r.li/ exists */
+	sprintf(out, "%s/.r.li/", G_home());
 	doneDir = G_mkdir(out);
 	if (doneDir == -1 && errno != EEXIST)
 	    G_fatal_error(_("Cannot create %s/.r.li/ directory"), G_home());
+
+	/* check if ~/.r.li/output exists */
 	sprintf(out, "%s/.r.li/output", G_home());
 	doneDir = G_mkdir(out);
 	if (doneDir == -1 && errno != EEXIST)
@@ -167,22 +127,16 @@
     /*#######################################################
        ------------------analysis loop----------------------
        ####################################################### */
-    /* first job scheduling */
-    while ((i < num_workers) && next_Area(parsed, l, g, &m) != 0) {
-	send(child[i].channel, &m);
-	i++;
-    }
 
     /*body */
     while (next_Area(parsed, l, g, &m) != 0) {
-	int j = 0, donePid;
+	worker_process(&doneJob, &m);
 
-	receive(receiveChannel, &doneJob);
-
+	/*perc++; */
+	/*G_percent (perc, WORKERS, 1); */
 	if (doneJob.type == DONE) {
 	    double result;
 
-	    donePid = doneJob.f.f_d.pid;
 	    result = doneJob.f.f_d.res;
 	    /* output */
 	    if (parsed != MVWIN) {
@@ -196,7 +150,6 @@
 	    }
 	}
 	else {
-	    donePid = doneJob.f.f_e.pid;
 	    if (parsed != MVWIN) {
 		/* text file output */
 		error_Output(res, doneJob);
@@ -206,97 +159,10 @@
 		/* TODO write to raster NULL ??? */
 	    }
 	}
-	j = 0;
-
-
-	while (j < num_workers && donePid != child[j].pid)
-	    j++;
-
-	send(child[j].channel, &m);
-
     }
 
-    /* kill childs */
-    withoutJob = i;
-    while (i > 0) {
-	int j = 0, donePid, status;
+    worker_end();
 
-	receive(receiveChannel, &doneJob);
-	if (doneJob.type == DONE) {
-	    double result;
-
-	    donePid = doneJob.f.f_d.pid;
-	    result = doneJob.f.f_d.res;
-	    if (parsed != MVWIN) {
-		/* text file output */
-		print_Output(res, doneJob);
-	    }
-	    else {
-		/* raster output */
-		raster_Output(random_access, doneJob.f.f_d.aid, g,
-			      doneJob.f.f_d.res);
-	    }
-	}
-	else {
-	    donePid = doneJob.f.f_e.pid;
-	    if (parsed != MVWIN) {
-		/* text file output */
-		error_Output(res, doneJob);
-	    }
-	    else {
-		/* printf("todo2 "); fflush(stdout); */
-		/* TODO write to raster */
-	    }
-	}
-
-	i--;
-
-	while (j < num_workers && donePid != child[j].pid)
-	    j++;
-
-	m.type = TERM;
-	m.f.f_t.pid = mypid;
-	send(child[j].channel, &m);
-	wait(&status);
-
-	if (!(WIFEXITED(status)))
-	    G_warning(_("r.li.worker (pid %i) exited with abnormal status: %i"),
-		      donePid, status);
-	else
-	    G_verbose_message(_("r.li.worker (pid %i) terminated successfully"),
-			      donePid);
-
-	/* remove pipe */
-	if (close(child[j].channel) != 0)
-	    G_message(_("Cannot close %s file (PIPE)"), child[j].pipe);
-	if (unlink(child[j].pipe) != 0)
-	    G_message(_("Cannot delete %s file (PIPE)"), child[j].pipe);
-    }
-
-    /* kill children without Job */
-    for (i = withoutJob; i < num_workers; i++) {
-	int status;
-
-	m.type = TERM;
-	m.f.f_t.pid = mypid;
-	send(child[i].channel, &m);
-	wait(&status);
-
-	if (!(WIFEXITED(status)))
-	    G_warning(_("r.li.worker (pid %i) exited with abnormal status: %i"),
-		      child[i].pid, status);
-	else
-	    G_verbose_message(_("r.li.worker (pid %i) terminated successfully"),
-			      child[i].pid);
-
-	/* remove pipe */
-	if (close(child[i].channel) != 0)
-	    G_message(_("Cannot close %s file (PIPE2)"), child[i].pipe);
-	if (unlink(child[i].pipe) != 0)
-	    G_message(_("Cannot delete %s file (PIPE2)"), child[i].pipe);
-    }
-
-
     /*################################################
        --------------delete tmp files------------------
        ################################################ */
@@ -309,17 +175,12 @@
 	G_short_history(output, "raster", &history);
 	G_command_history(&history);
 	G_write_history(output, &history);
+	G_message(_("Raster map <%s> created."), output);
     } else {
 	/* text file output */
 	G_message("Result written to ASCII file <%s>", out);
     }
 
-    if (close(receiveChannel) != 0)
-	G_message(_("Cannot close receive channel file"));
-
-    if (unlink(reportChannelName) != 0)
-	G_message(_("Cannot delete %s file"), child[i].pipe);
-
     return 1;
 }
 
@@ -328,12 +189,14 @@
 {
     struct stat s;
     struct Cell_head cellhd;
-    char *buf, *token, *mapset; /* *raster_fqn, */
+    char *buf, *mapset; /* *raster_fqn, */
+    const char *token;
     int setup;
     int letti;
     double rel_x, rel_y, rel_rl, rel_cl;
     double sf_n, sf_s, sf_e, sf_w;
     int sf_x, sf_y, sf_rl, sf_cl;
+    int sa_x, sa_y, sa_rl, sa_cl;
     int size;
 
     if (stat(path, &s) != 0)
@@ -366,11 +229,28 @@
     if (G_get_cellhd(raster, mapset, &cellhd) == -1)
 	G_fatal_error(_("Cannot read raster header file"));
 
+    /* use current region ! */
+    G_get_window(&cellhd);
+
     /* calculate absolute sampling frame definition */
     sf_x = (int)rint(cellhd.cols * rel_x);
     sf_y = (int)rint(cellhd.rows * rel_y);
     sf_rl = (int)rint(cellhd.rows * rel_rl);
     sf_cl = (int)rint(cellhd.cols * rel_cl);
+    
+    /* sanity check */
+    if (sf_x < 0)
+	sf_x = 0;
+    if (sf_y < 0)
+	sf_y = 0;
+    if (sf_x > cellhd.cols)
+	sf_x = cellhd.cols;
+    if (sf_y > cellhd.rows)
+	sf_y = cellhd.rows;
+    if (sf_rl > cellhd.rows - sf_y)
+	sf_rl = cellhd.rows - sf_y;
+    if (sf_cl > cellhd.cols - sf_x)
+	sf_cl = cellhd.cols - sf_x;
 
     /* calculate sample frame boundaries */
     sf_n = cellhd.north - (cellhd.ns_res * sf_y);
@@ -393,19 +273,28 @@
 
 	    if (rel_sa_x == -1.0 && rel_sa_y == -1.0) {
 		/* runtime disposition */
-		int sa_rl, sa_cl;
 
 		sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
 		sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
+
+		/* sanity check */
+		if (sa_rl > cellhd.rows - sf_y)
+		    sa_rl = cellhd.rows - sf_y;
+		if (sa_cl > cellhd.cols - sf_x)
+		    sa_cl = cellhd.cols - sf_x;
+
+		/* total sample area */
 		g->rows = sf_rl;
 		g->cols = sf_cl;
+		g->x = sf_x;
+		g->y = sf_y;
+		/* current sample area (subset of total sample area) */
 		g->rl = sa_rl;
 		g->cl = sa_cl;
-		g->count = 1;
 		g->sf_x = sf_x;
 		g->sf_y = sf_y;
-		g->x = sf_x;
-		g->y = sf_y;
+
+		g->count = 1;
 		g->maskname = NULL;
 
 		return disposeAreas(l, g, strtok(NULL, "\n"));
@@ -416,10 +305,30 @@
 		toReturn = NORMAL;
 		/*read file and create list */
 		m.type = AREA;
-		m.f.f_a.x = (int)rint(cellhd.cols * rel_sa_x);
-		m.f.f_a.y = (int)rint(cellhd.rows * rel_sa_y);
-		m.f.f_a.rl = (int)rint(cellhd.rows * rel_sa_rl);
-		m.f.f_a.cl = (int)rint(cellhd.cols * rel_sa_cl);
+		/* current sample area (subset of total sample area) */
+		sa_x = (int)rint(cellhd.cols * rel_sa_x);
+		sa_y = (int)rint(cellhd.rows * rel_sa_y);
+		sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
+		sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
+
+		/* sanity check */
+		if (sa_x < 0)
+		    sa_x = 0;
+		if (sa_y < 0)
+		    sa_y = 0;
+		if (sa_x > cellhd.cols)
+		    sa_x = cellhd.cols;
+		if (sa_y > cellhd.rows)
+		    sa_y = cellhd.rows;
+		if (sa_rl > cellhd.rows - sa_y)
+		    sa_rl = cellhd.rows - sa_y;
+		if (sa_cl > cellhd.cols - sa_x)
+		    sa_cl = cellhd.cols - sa_x;
+
+		m.f.f_a.x = sa_x;
+		m.f.f_a.y = sa_y;
+		m.f.f_a.rl = sa_rl;
+		m.f.f_a.cl = sa_cl;
 		m.f.f_a.aid = aid;
 		aid++;
 		insertNode(l, m);
@@ -445,17 +354,25 @@
 
 	    if (rel_sa_x == -1 && rel_sa_y == -1) {
 		/* runtime disposition */
-		int sa_rl, sa_cl;
 
 		sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
 		sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
+
+		/* sanity check */
+		if (sa_rl > cellhd.rows - sf_y)
+		    sa_rl = cellhd.rows - sf_y;
+		if (sa_cl > cellhd.cols - sf_x)
+		    sa_cl = cellhd.cols - sf_x;
+
+		/* total sample area */
 		g->rows = sf_rl;
 		g->cols = sf_cl;
+		g->x = sf_x;
+		g->y = sf_y;
+		/* current sample area (subset of total sample area) */
 		g->rl = sa_rl;
 		g->cl = sa_cl;
 		g->count = 1;
-		g->x = sf_x;
-		g->y = sf_y;
 		g->maskname = maskname;
 		return disposeAreas(l, g, strtok(NULL, "\n"));
 	    }
@@ -464,10 +381,30 @@
 		msg m;
 
 		m.type = MASKEDAREA;
-		m.f.f_ma.x = (int)rint(cellhd.cols * rel_sa_x);
-		m.f.f_ma.y = (int)rint(cellhd.rows * rel_sa_y);
-		m.f.f_ma.rl = (int)rint(cellhd.rows * rel_sa_rl);
-		m.f.f_ma.cl = (int)rint(cellhd.cols * rel_sa_cl);
+		/* current sample area (subset of total sample area) */
+		sa_x = (int)rint(cellhd.cols * rel_sa_x);
+		sa_y = (int)rint(cellhd.rows * rel_sa_y);
+		sa_rl = (int)rint(cellhd.rows * rel_sa_rl);
+		sa_cl = (int)rint(cellhd.cols * rel_sa_cl);
+
+		/* sanity check */
+		if (sa_x < 0)
+		    sa_x = 0;
+		if (sa_y < 0)
+		    sa_y = 0;
+		if (sa_x > cellhd.cols)
+		    sa_x = cellhd.cols;
+		if (sa_y > cellhd.rows)
+		    sa_y = cellhd.rows;
+		if (sa_rl > cellhd.rows - sa_y)
+		    sa_rl = cellhd.rows - sa_y;
+		if (sa_cl > cellhd.cols - sa_x)
+		    sa_cl = cellhd.cols - sa_x;
+
+		m.f.f_ma.x = sa_x;
+		m.f.f_ma.y = sa_y;
+		m.f.f_ma.rl = sa_rl;
+		m.f.f_ma.cl = sa_cl;
 		m.f.f_ma.aid = aid;
 		strcpy(m.f.f_ma.mask, maskname);
 		aid++;
@@ -485,12 +422,11 @@
 	double sa_n, sa_s, sa_w, sa_e;
 	int aid = 1;
 	char maskname[GNAME_MAX] = {'\0'};
-	struct Cell_head window;
 	msg m;
 
 	/* Get the window setting. g.region rast=<input raster> */
 	/*   ? same as cellhd above ? */
-	G_get_window(&window);
+	/* no. the current window might be different */
 
 	do {
 	    strcpy(maskname, strtok(NULL, "|"));
@@ -501,21 +437,40 @@
 
 	    m.type = MASKEDAREA;
 
-	    /* Each input overlay area from input vector are converted to raster
-	       via v.to.rast. See r.li.setup/sample_area_vector.sh. This is to used 
-	       only for reading the region (NS, EW). */
+	    /* Each input overlay area from input vector are converted to
+		raster via v.to.rast. See r.li.setup/sample_area_vector.sh.
+		This is used only for reading the region (NS, EW). */
 
-	    /* Get start x and y position of masked overlay raster with respect 
-	       to input raster region from window. 
-	       sa_n, sa_e are read from configuration file. */
+	    /* current sample area (subset of total sample area) */
 
-	    m.f.f_ma.x = (int)G_easting_to_col(sa_e, &window);
-	    m.f.f_ma.y = (int)G_northing_to_row(sa_n, &window);
+	    /* Get start x and y position of masked overlay raster with
+		respect to current region.
+		sa_n, sa_w are read from configuration file. */
+	    sa_x = (int)rint((sa_w - cellhd.west) / cellhd.ew_res);
+	    sa_y = (int)rint((cellhd.north - sa_n) / cellhd.ns_res);
 
 	    /* Get row count and column count of overlay raster */
-	    m.f.f_ma.rl = (int)rint((sa_n - sa_s) / cellhd.ns_res);
-	    m.f.f_ma.cl = (int)rint((sa_e - sa_w) / cellhd.ew_res);
+	    sa_rl = (int)rint((sa_n - sa_s) / cellhd.ns_res);
+	    sa_cl = (int)rint((sa_e - sa_w) / cellhd.ew_res);
 
+	    /* sanity check */
+	    if (sa_x < 0)
+		sa_x = 0;
+	    if (sa_y < 0)
+		sa_y = 0;
+	    if (sa_x > cellhd.cols)
+		sa_x = cellhd.cols;
+	    if (sa_y > cellhd.rows)
+		sa_y = cellhd.rows;
+	    if (sa_rl > cellhd.rows - sa_y)
+		sa_rl = cellhd.rows - sa_y;
+	    if (sa_cl > cellhd.cols - sa_x)
+		sa_cl = cellhd.cols - sa_x;
+
+	    m.f.f_ma.x = sa_x;
+	    m.f.f_ma.y = sa_y;
+	    m.f.f_ma.rl = sa_rl;
+	    m.f.f_ma.cl = sa_cl;
 	    m.f.f_ma.aid = aid;
 	    strcpy(m.f.f_ma.mask, maskname);
 	    aid++;
@@ -710,7 +665,10 @@
 	char s[100];
 	int len;
 
-	sprintf(s, "RESULT %i|%f\n", m.f.f_d.aid, m.f.f_d.res);
+	if (G_is_null_value(&m.f.f_d.res, DCELL_TYPE))
+	    sprintf(s, "RESULT %i|NULL\n", m.f.f_d.aid);
+	else
+	    sprintf(s, "RESULT %i|%.15g\n", m.f.f_d.aid, m.f.f_d.res);
 	len = strlen(s);
 
 	if (write(out, s, len) == len)
@@ -787,6 +745,7 @@
 	}
 
 	G_put_raster_row(mv_fd, cell_buf, DCELL_TYPE);
+
     }
 
     G_set_d_null_value(cell_buf, G_window_cols() + 1);

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.h
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.h	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/daemon.h	2014-03-24 11:43:14 UTC (rev 59305)
@@ -22,10 +22,6 @@
 #include "defs.h"
 
 
-/**
- * \brief number of r.li.workers to use
- */
-#define DEFAULT_WORKERS 10
 #define NORMAL 1
 #define MVWIN 2
 #define GEN 3
@@ -99,10 +95,11 @@
 
  /**
   * \brief fields of an area descriptor
-  * \member x the x coordinate of upper left corner
-  * \member y the y coordinate of upper left corner
-  * \member rl area length in rows
-  * \member cl area length in columns
+  * \member x column offset = start of sample area
+  * \member y row offset = start of sample area
+  * \member rl sample area length in rows
+  * \member cl sample area length in columns
+  * \member rc number of rows in the cache
   * \member mask file descriptor of mask raster file (-1 if there is no mask)
  */
 struct area_entry
@@ -111,6 +108,7 @@
     int y;
     int rl;
     int cl;
+    int rc;
     int mask;
     int data_type;
     cell_manager cm;
@@ -120,9 +118,18 @@
     char *mask_name;
 };
 
+/**
+ * \brief function prototype for index calculation
+ * \param fd file descripter of opened raster map
+ * \param par optional parameters
+ * \param ad definition of the sample area
+ * \param result pointer to store the result
+ * \return RLI_ERRORE error occurs in calculating index
+ * \return RLI_OK  otherwise
+ */
+typedef int rli_func(int fd, char **par, struct area_entry *ad, double *result);
 
 
-
 /**
  * \brief applies the f index once for every
  * area defined in setup file
@@ -132,7 +139,8 @@
  * \return 0 error occurs in calculating index
  * \return 1  otherwise
  */
-int calculateIndex(char *file, int f(int, char **, struct area_entry *, double *),
+
+int calculateIndex(char *file, rli_func *f,
 		   char **parameters, char *raster, char *output);
 
 /**
@@ -197,12 +205,13 @@
  * \brief client implementation
  * \param raster the raster map to analyze
  * \param f the function used for index computing
- * \param server_channel the channel where to send the result
- * \param mychannel the channel where to receive the area messages
  * \param result where to put the result of index computing
  */
-void worker(char *raster, int f(int, char **, struct area_entry *, double *),
-	    char *server_channel, char *mychannel, char **parameters);
+void worker_init(char *raster, rli_func *f,
+		 char **parameters);
+void worker_process(msg * ret, msg * m);
+void worker_end(void);
+
  /**
   * \brief adapts the mask at current raster file
   * \param mask name of mask raster file
@@ -211,7 +220,7 @@
   * \param cl the lenght in cols of sample area
   * \return the name of mask raster file to use
   */
-char *mask_preprocessing(char *mask, char *raster, int rl, int cl);
+char *mask_preprocessing(char *mask, char *raster, struct area_entry *ad);
 
  /**
   * \brief writes the output for a raster file
@@ -266,4 +275,3 @@
   */
 FCELL *RLI_get_fcell_raster_row(int fd, int row, struct area_entry * ad);
 
-#include "index.h"

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/description.html
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/description.html	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/description.html	2014-03-24 11:43:14 UTC (rev 59305)
@@ -68,9 +68,6 @@
 </pre></div><br>
 to use an ad hoc build memory management developed to speed up the system.
 The documentation is in doxygen files.
-<p>
-The <tt>WORKERS</tt> environment variable can be set to the number of
-concurrent processes desired. If not set, the default is 10 concurrent jobs.
 
 
 <h2>SEE ALSO</h2>

Deleted: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/index.h
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/index.h	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/index.h	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,50 +0,0 @@
-/*
- * \file index.h
- *
- * \brief declaration of functions for r.li raster analysis
- *  
- * \author Claudio Porta, Lucio Davide Spano, Serena Pallecchi students of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
- *        Luca Delucchi and Duccio Rocchini, Fondazione Edmund Mach, Italy: r.li.pielou, r.li.renyi
- *
- *
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
- * 
- * \version 1.1
- *
- */
-
-
- /* #################################################
-    ADD HERE INDEX DECLARATIONS
-    ################################################# */
-
-
-
- /**
-  * \brief calculate patch density index on selected area
-  * the abstract function is patch_density= patch_number / area
-  */
-int patch_density(int fd, char **par, struct area_entry *ad, double *result);
-
-int patch_number(int fd, char **par, struct area_entry *ad, double *result);
-int shape_index(int fd, char **par, struct area_entry *ad, double *result);
-int shannon(int fd, char **par, struct area_entry *ad, double *result);
-
-int pielou(int fd, char **par, struct area_entry *ad, double *result);
-int renyi(int fd, char **par, struct area_entry *ad, double *result);
-
-int simpson(int fd, char **par, struct area_entry *ad, double *result);
-int meanPatchSize(int fd, char **par, struct area_entry *ad, double *result);
-int meanPixelAttribute(int fd, char **par, struct area_entry *ad, double *result);
-int contrastWeightedEdgeDensity(int fd, char **par, struct area_entry *ad,
-				double *result);
-int edgedensity(int fd, char **valore, struct area_entry *ad, double *result);
-int patchAreaDistributionCV(int fd, char **par, struct area_entry *ad, double *result);
-int patchAreaDistributionMN(int fd, char **par, struct area_entry *ad, double *result);
-int patchAreaDistributionSD(int fd, char **par, struct area_entry *ad, double *result);
-int patchAreaDistributionRANGE(int fd, char **par, struct area_entry *ad,
-			       double *result);
-int dominance(int fd, char **par, struct area_entry *ad, double *result);
-int richness(int fd, char **par, struct area_entry *ad, double *result);

Deleted: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,87 +0,0 @@
-
-/**
- * \file IPC.c
- *
- * \brief implementation of interprocess communication
- *	primitives between r.li.daemon and r.li.worker
- *
- *
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
- *
- *
- * \author Lucio Davide Spano
- * 
- * \version 1.0
- * 
- */
-
-
-#include <unistd.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include "ipc.h"
-
-
-int send(int pipe, msg *m)
-{
-    int check;
-
-    /* write on pipe */
-    check = write(pipe, m, sizeof(msg));
-
-    if (check > 0)
-	return 1;
-    else
-	return 0;
-}
-
-int receive(int pipe, msg *m)
-{
-    return read(pipe, m, sizeof(msg));
-}
-
-void printMsg(msg m)
-{
-
-    switch (m.type) {
-    case AREA:{
-	    G_message(_("				AREA MESSAGE: \n \
-				aid = %i \n \
-				x = %i \n \
-				y = %i \n \
-				rl = %i \n \
-				cl = %i \n "), m.f.f_a.aid, m.f.f_a.x, m.f.f_a.y, m.f.f_a.rl, m.f.f_a.cl);
-	}
-	break;
-    case MASKEDAREA:{
-	    G_message(_(" 				MASKEDAREA MESSAGE: \n \
-				aid = %i \n \
-				x = %i \n \
-				y = %i \n \
-				rl = %i \n \
-				cl = %i \n \
-				mask = %s \n "),
-		      m.f.f_ma.aid, m.f.f_ma.x, m.f.f_ma.y, m.f.f_ma.rl, m.f.f_ma.cl, m.f.f_ma.mask);
-	}
-	break;
-    case DONE:{
-	    G_message(_(" 				DONE MESSAGE: \n \
-				aid = %i \n \
-				pid = %i \n \
-				result = %f \n "), m.f.f_d.aid, m.f.f_d.pid, m.f.f_d.res);
-	}
-	break;
-    case ERROR:{
-	    G_message(_(" 				ERROR MESSAGE: \n \
-				aid = %i \n \
-				pid = %i \n "), m.f.f_e.aid, m.f.f_e.pid);
-	}
-	break;
-    case TERM:{
-	    G_message(_(" 				TERM MESSAGE: \n \
-				pid = %i \n "), m.f.f_t.pid);
-	}
-	break;
-    }
-}

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.h
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.h	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/ipc.h	2014-03-24 11:43:14 UTC (rev 59305)
@@ -120,23 +120,3 @@
     fields f;
 } msg;
 
-/**
- * \brief send the specified message through the pipe channel.
- * \param pipe the pipe used to send message
- * \param m the message to send
- * \return 1 message sent, 0 otherwise
- */
-int send(int pipe, msg * m);
-
-/**
- * \brief receive a message through the pipe channel
- * \param pipe the pipe used to receive message
- * \param m the message to receive
- * \return 1 message sent, 0 otherwise
- */
-int receive(int pipe, msg * m);
-
-/**
- * \brief debug function, print a message to STDOUT
- */
-void printMsg(msg m);

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -65,7 +65,8 @@
 	struct node *tmp = l->head;
 
 	l->head = NULL;
-	free(tmp);
+	G_free(tmp->m);
+	G_free(tmp);
 	l->size--;
     }
     else {
@@ -73,7 +74,8 @@
 
 	l->head = l->head->next;
 	l->head->prev = NULL;
-	free(tmp);
+	G_free(tmp->m);
+	G_free(tmp);
 	l->size--;
     }
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.h
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.h	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/list.h	2014-03-24 11:43:14 UTC (rev 59305)
@@ -68,13 +68,15 @@
   * \param dist inter-area distance
   * \param add_row cell to add in rows
   * \param add_col cell to add in columns
-  * \param x x coordinate of next area
-  * \param y y coordinate of next area
-  * \param rl area length in rows
-  * \param cl areal length in columns
+  * \param rows area length in rows
+  * \param cols area length in columns
+  * \param x column offset of next area
+  * \param y row offset of next area
+  * \param rl sample area length in rows
+  * \param cl sample area length in columns
   * \param count identifier of next area
-  * \param sf_x x coordinate of sample frame
-  * \param sf_y y coordinate of sample frame
+  * \param sf_x column offset of sample frame
+  * \param sf_y row offset of sample frame
   * \param maskname name of mask for the area
   */
 struct g_area

Deleted: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/main.c.unused
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/main.c.unused	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/main.c.unused	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,227 +0,0 @@
-/****************************************************************************
- *
- * MODULE:       r.li.daemon
- * AUTHOR(S):    Claudio Porta, Lucio D. Spano, Serena Pallecchi (original contributors)
- *                students of Computer Science University of Pisa (Italy)
- *               Commission from Faunalia Pontedera (PI) www.faunalia.it
- *               Fixes: Markus Neteler <neteler itc.it>
- *               
- * PURPOSE:      r.li.daemon with a simple index for library debug
- * COPYRIGHT:    (C) 2006-2007 by the GRASS Development Team
- *
- *               This program is free software under the GNU General Public
- *               License (>=v2). Read the file COPYING that comes with GRASS
- *               for details.
- *
- *****************************************************************************/
-
-#include <stdlib.h>
-#include <fcntl.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include "daemon.h"
-
-/**
- * main with a simple index for library debug
- *
- * This program is free software under the GPL (>=v2)
- * Read the COPYING file that comes with GRASS for details.
- *
- */
-int main(int argc, char *argv[]){
-	struct Option *raster, *conf, *output;
-	struct GModule *module;
-	
-	G_gisinit(argv[0]);
-	module = G_define_module();
-	module->description =_("Calculates <simple> index on a raster map");
-	module->keywords = _("raster, landscape structure analysis, job launcher");
-
-	/* define options */
-	
-	raster = G_define_standard_option(G_OPT_R_MAP);
-	
-	conf = G_define_option();
-	conf->key = "conf";
-	conf->description = "Areas configuration file";
-	conf->gisprompt = "old_file,file,input";
-	conf->type = TYPE_STRING;
-	conf->required = YES;
-	
-	output = G_define_standard_option(G_OPT_R_OUTPUT);
-	
-	/** add other options for index parameters here */
-	
-	if (G_parser(argc, argv))
-	   exit(EXIT_FAILURE);
-
-	return calculateIndex(conf->answer, simple_index, NULL, raster->answer, output->answer);
-	
-}
-
-int simple_index(int fd, char ** par, area_des ad, double *result){
-	CELL *buf, *sup;
-	int count, i,j, connected=0, complete_line=1;
-	double area;
-	char *mapset, c[150];
-	struct Cell_head hd;
-	CELL complete_value;
-	
-	G_set_c_null_value(&complete_value, 1);
-	mapset = G_find_cell(ad->raster, "");
-	if (G_get_cellhd(ad->raster, mapset, &hd) == - 1)
-		return 0;
-	sup = G_allocate_cell_buf();
-	if(ad->mask == -1){
-		double meters_row, meters_col;
-		/* no mask */
-		
-		/*calculate area size */
-		meters_row = G_distance(hd.north,hd.west, hd.south, hd.west)\
-		/hd.rows;
-		meters_col = G_distance(hd.north, hd.west, hd.north, hd.east)\
-		/hd.cols;
-		area = meters_row * ad->rl * meters_col * ad->cl;
-		
-		/*calculate number of patch*/
-		count =0;
-		for(i = 0; i<ad->rl; i++){
-			connected = 0;
-			buf = RLI_get_cell_raster_row(fd, i+ad->y, ad);
-			if(i > 0){
-				sup = RLI_get_cell_raster_row(fd, i-1+ad->y, ad);
-			}
-			
-			if (complete_line){
-				if (! G_is_null_value( &(buf[ad->x]), CELL_TYPE) &&\
-					buf[ad->x] != complete_value)
-					count++;
-				for(j=0; j<ad->cl; j++){
-					if (buf[j+ad->x] != buf[j+1+ad->x]){
-						complete_line=0;
-						if(!G_is_null_value( &(buf[j+ad->x]), CELL_TYPE) &&\
-							buf[j+ad->x] != complete_value)
-							count++;
-						}
-				}
-				if (complete_line){
-					complete_value = buf[ad->x];
-				}
-			}
-			else{
-				complete_line = 1;
-				for(j=0; j<ad->cl; j++){
-					if (sup[j+ad->x] == buf[j+ad->x]){
-						connected = 1;
-					}
-					if (buf[j+ad->x] != buf[j+1+ad->x]){
-						complete_line =0;
-						if (!connected && \
-							!G_is_null_value( &(buf[j+ad->x]), CELL_TYPE)){
-							count++;
-							connected =0;									
-						}
-						else{
-							connected=0;
-						}
-					}
-				}
-				if (complete_line)
-					complete_value = buf[ad->x];
-			}
-		}
-
-		#ifdef DEBUG
-		printf("number of patch = %i\n", count);
-		#endif
-		#ifdef DEBUG
-		printf("area = %f\n", area);
-		#endif
-		*result= (count/area) * 10000;
-		return 1;
-	}
-	else{
-		double meters_row, meters_col;
-		int cell_dim = 0, mask_fd, *mask_buf;
-		CELL null_value;
-		
-		G_set_c_null_value(&null_value, 1);
-		/* mask */
-		if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
-			return 0;
-		mask_buf = malloc(ad->cl * sizeof(int));
-		/*calculate area size */
-		meters_row = G_distance(hd.north,hd.west, hd.south, hd.west)\
-		/hd.rows;
-		meters_col = G_distance(hd.north, hd.west, hd.north, hd.east)\
-		/hd.cols;
-		
-		/*calculate number of patch*/
-		count =0;
-		for(i = 0; i<ad->rl; i++){
-			G_get_raster_row(fd, buf, i+ad->y, CELL_TYPE);
-			if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
-				return 0;
-			if(i>0){
-				G_get_raster_row(fd, sup, i-1, CELL_TYPE);
-			}
-			/* mask values */
-			for (j=0; j<ad->cl; j++){
-				if(mask_buf[j] == 0)
-					buf[ad->x +j] = null_value;
-			}
-			if (complete_line){
-				if (! G_is_null_value( &(buf[ad->x]), CELL_TYPE) &&\
-					buf[ad->x] != complete_value)
-					count++;
-				for(j=0; j<ad->cl; j++){
-					if (buf[j+ad->x] != buf[j+1+ad->x]){
-						complete_line=0;
-						if(!G_is_null_value( &(buf[j+ad->x]), CELL_TYPE)&&\
-							buf[j+ad->x] != complete_value)
-							count++;
-						}
-				}
-				if (complete_line){
-					complete_value = buf[ad->x];
-				}
-			}
-			else{
-				complete_line = 1;
-				for(j=0; j<ad->cl; j++){
-					if (sup[j+ad->x] == buf[j+ad->x]){
-						connected = 1;
-					}
-					if (buf[j+ad->x] != buf[j+1+ad->x]){
-						complete_line =0;
-						if (!connected && \
-							!G_is_null_value( &(buf[j+ad->x]), CELL_TYPE)){
-							count++;
-							connected =0;									
-						}
-						else{
-							connected=0;
-						}
-					}
-				}
-				if (complete_line)
-					complete_value = buf[ad->x];
-			}
-		}
-		#ifdef DEBUG
-		printf("number of patch = %i\n", count);
-		#endif
-		#ifdef DEBUG
-		printf("area = %f\n", area);
-		#endif
-		area = cell_dim * meters_row * meters_col;
-		*result= (count/area)*10000;
-		free(buf);
-		free(sup);
-		free(mask_buf);
-		return 1;
-	}
-}
-
-
-

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/worker.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/worker.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.daemon/worker.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -37,36 +37,41 @@
 
 #define CACHESIZE 4194304
 
-void worker(char *raster, int f(int, char **, struct area_entry *, double *),
-	    char *server_channel, char *mychannel, char **parameters)
+static int fd, aid;
+static int erease_mask = 0, data_type = 0;
+static int cache_rows, used = 0;
+static struct area_entry * ad;
+static double result;
+static struct Cell_head hd;
+static cell_manager cm;
+static dcell_manager dm;
+static fcell_manager fm;
+static char *raster;
+static char **parameters;
+static rli_func *func;
+
+void worker_init(char *r, rli_func *f, char **p)
 {
     char *mapset;
-    int fd, aid;
-    int rec_ch, send_ch, erease_mask = 0, data_type = 0;
-    int cache_rows, used = 0;
-    msg toReceive, toSend;
-    static struct area_entry *ad;
-    double result;
-    int pid;
-    struct Cell_head hd;
-    cell_manager cm;
-    dcell_manager dm;
-    fcell_manager fm;
 
     cm = G_malloc(sizeof(struct cell_memory_entry));
     fm = G_malloc(sizeof(struct fcell_memory_entry));
     dm = G_malloc(sizeof(struct dcell_memory_entry));
-    pid = getpid();
     ad = G_malloc(sizeof(struct area_entry));
 
+    raster = r;
+    parameters = p;
+    func = f;
+
     /* open raster map */
     mapset = G_find_cell(raster, "");
     fd = G_open_cell_old(raster, mapset);
-    if (G_get_cellhd(raster, mapset, &hd) == -1) {
-	G_message(_("CHILD[pid = %i] cannot open raster map"), pid);
-	exit(EXIT_FAILURE);
-    }
+    if (G_get_cellhd(raster, mapset, &hd) == -1)
+	    G_fatal_error(_("Cannot open raster map <%s>"), raster);
 
+    /* get current window */
+    G_get_window(&hd);
+
     /* read data type to allocate cache */
     data_type = G_raster_map_type(raster, mapset);
 
@@ -74,6 +79,8 @@
     switch (data_type) {
     case CELL_TYPE:{
 	    cache_rows = CACHESIZE / (hd.cols * sizeof(CELL));
+	    if (cache_rows < 4)
+		cache_rows = 4;
 	    cm->cache = G_malloc(cache_rows * sizeof(CELL *));
 	    cm->contents = G_malloc(cache_rows * sizeof(int));
 	    cm->used = 0;
@@ -81,6 +88,8 @@
 	} break;
     case DCELL_TYPE:{
 	    cache_rows = CACHESIZE / (hd.cols * sizeof(DCELL));
+	    if (cache_rows < 4)
+		cache_rows = 4;
 	    dm->cache = G_malloc(cache_rows * sizeof(DCELL *));
 	    dm->contents = G_malloc(cache_rows * sizeof(int));
 	    dm->used = 0;
@@ -88,6 +97,8 @@
 	} break;
     case FCELL_TYPE:{
 	    cache_rows = CACHESIZE / (hd.cols * sizeof(FCELL));
+	    if (cache_rows < 4)
+		cache_rows = 4;
 	    fm->cache = G_malloc(cache_rows * sizeof(FCELL *));
 	    fm->contents = G_malloc(cache_rows * sizeof(int));
 	    fm->used = 0;
@@ -95,146 +106,132 @@
 	} break;
     }
     ad->data_type = data_type;
+    ad->rc = cache_rows;
     ad->cm = cm;
     ad->fm = fm;
     ad->dm = dm;
+}
 
-    /* open receive channel */
-    rec_ch = open(mychannel, O_RDONLY, 0755);
-    if (rec_ch == -1) {
-	G_message(_("CHILD[pid = %i] cannot open receive channel"), pid);
-	exit(0);
-    }
+void worker_process(msg * ret, msg * m)
+{
+    switch (m->type) {
+    case AREA:
+	aid = m->f.f_a.aid;
+	ad->x = m->f.f_a.x;
+	ad->y = m->f.f_a.y;
+	ad->rl = m->f.f_a.rl;
+	ad->cl = m->f.f_a.cl;
+	ad->raster = raster;
+	ad->mask = -1;
+	break;
+    case MASKEDAREA:
+	aid = m->f.f_ma.aid;
+	ad->x = m->f.f_ma.x;
+	ad->y = m->f.f_ma.y;
+	ad->rl = m->f.f_ma.rl;
+	ad->cl = m->f.f_ma.cl;
+	ad->raster = raster;
 
-    /* open send channel */
-    send_ch = open(server_channel, O_WRONLY, 0755);
-    if (send_ch == -1) {
-	G_message(_("CHILD[pid = %i] cannot open receive channel"), pid);
-	exit(0);
-    }
+	/* mask preprocessing */
+	ad->mask_name = mask_preprocessing(m->f.f_ma.mask, raster, ad);
 
-    /* receive loop */
-    receive(rec_ch, &toReceive);
-
-    while (toReceive.type != TERM) {
-	if (toReceive.type == AREA) {
-	    aid = toReceive.f.f_ma.aid;
-	    ad->x = toReceive.f.f_a.x;
-	    ad->y = toReceive.f.f_a.y;
-	    ad->rl = toReceive.f.f_a.rl;
-	    ad->cl = toReceive.f.f_a.cl;
-	    ad->raster = raster;
+	if (ad->mask_name == NULL) {
+	    G_message(_("unable to open <%s> mask ... continuing without!"),
+		      m->f.f_ma.mask);
 	    ad->mask = -1;
 	}
-	else if (toReceive.type == MASKEDAREA) {
-	    aid = toReceive.f.f_ma.aid;
-	    ad->x = toReceive.f.f_ma.x;
-	    ad->y = toReceive.f.f_ma.y;
-	    ad->rl = toReceive.f.f_ma.rl;
-	    ad->cl = toReceive.f.f_ma.cl;
-	    ad->raster = raster;
-
-	    /* mask preprocessing */
-	    ad->mask_name = mask_preprocessing(toReceive.f.f_ma.mask,
-					       raster, ad->rl, ad->cl);
-	    if (ad->mask_name == NULL) {
-		G_message(_("CHILD[pid = %i]: unable to open <%s> mask ... continuing without!"),
-			  pid, toReceive.f.f_ma.mask);
-		ad->mask = -1;
-	    }
-	    else {
-		if (strcmp(toReceive.f.f_ma.mask, ad->mask_name) != 0)
-		    /* temporary mask created */
-		    erease_mask = 1;
-		ad->mask = open(ad->mask_name, O_WRONLY, 0755);
-		if (ad->mask == -1) {
-		    G_message(_("CHILD[pid = %i]: unable to open <%s> mask ... continuing without!"),
-			      pid, toReceive.f.f_ma.mask);
-		}
-	    }
+	else {
+	    if (strcmp(m->f.f_ma.mask, ad->mask_name) != 0)
+		/* temporary mask created */
+		erease_mask = 1;
+	    ad->mask = 1;
 	}
-	else
-	    G_fatal_error("Program error, worker() toReceive.type=%d",
-			  toReceive.type);
+	break;
+    default:
+	G_fatal_error("Program error, worker() type=%d", m->type);
+	break;
+    }
+    
+    /* sanity check on the sample area ? */
+    /* 0 <= ad->x < hd.cols */
+    /* 0 <= ad->y < hd.rows */
+    /* ad->rl + ad->y <= hd.rows */
+    /* ad->cl + ad->x <= hd.cols */
 
-	/* memory menagement */
-	if (ad->rl > used) {
-	    /* allocate cache */
-	    int i;
+    /* memory menagement */
+    if (ad->rc > used) {
+	/* allocate cache */
+	int i;
 
-	    switch (data_type) {
-	    case CELL_TYPE:{
-		    for (i = 0; i < (ad->rl - used); i++) {
-			cm->cache[used + i] = G_allocate_cell_buf();
-		    }
+	switch (data_type) {
+	case CELL_TYPE:{
+		for (i = 0; i < (ad->rc - used); i++) {
+		    cm->cache[used + i] = G_allocate_cell_buf();
+		    cm->contents[used + i] = -1;
 		}
-		break;
-	    case DCELL_TYPE:{
-		    for (i = 0; i < ad->rl - used; i++) {
-			dm->cache[used + i] = G_allocate_d_raster_buf();
-		    }
+	    }
+	    break;
+	case DCELL_TYPE:{
+		for (i = 0; i < ad->rc - used; i++) {
+		    dm->cache[used + i] = G_allocate_d_raster_buf();
+		    dm->contents[used + i] = -1;
 		}
-		break;
-	    case FCELL_TYPE:{
-		    for (i = 0; i < ad->rl - used; i++) {
-			fm->cache[used + i] = G_allocate_f_raster_buf();
-		    }
+	    }
+	    break;
+	case FCELL_TYPE:{
+		for (i = 0; i < ad->rc - used; i++) {
+		    fm->cache[used + i] = G_allocate_f_raster_buf();
+		    fm->contents[used + i] = -1;
 		}
-		break;
 	    }
-	    cm->used = ad->rl;
-	    dm->used = ad->rl;
-	    fm->used = ad->rl;
-	    used = ad->rl;
+	    break;
 	}
+	cm->used = ad->rc;
+	dm->used = ad->rc;
+	fm->used = ad->rc;
+	used = ad->rc;
+    }
 
-	/* calculate function */
+    /* calculate function */
 
-	if (f(fd, parameters, ad, &result) == RLI_OK) {
-	    /* success */
-	    toSend.type = DONE;
-	    toSend.f.f_d.aid = aid;
-	    toSend.f.f_d.pid = getpid();
-	    toSend.f.f_d.res = result;
-	}
-	else {
-	    /* fail */
-	    toSend.type = ERROR;
-	    toSend.f.f_e.aid = aid;
-	    toSend.f.f_e.pid = getpid();
-	}
+    if (func(fd, parameters, ad, &result) == RLI_OK) {
+	/* success */
+	ret->type = DONE;
+	ret->f.f_d.aid = aid;
+	ret->f.f_d.pid = 0;
+	ret->f.f_d.res = result;
+    }
+    else {
+	/* fail */
+	ret->type = ERROR;
+	ret->f.f_e.aid = aid;
+	ret->f.f_e.pid = 0;
+    }
 
-	send(send_ch, &toSend);
-
-	if (erease_mask == 1) {
-	    erease_mask = 0;
-	    unlink(ad->mask_name);
-	}
-
-	receive(rec_ch, &toReceive);
+    if (erease_mask == 1) {
+	erease_mask = 0;
+	unlink(ad->mask_name);
     }
+}
+
+void worker_end(void)
+{
     /* close raster map */
     G_close_cell(fd);
-
-    /* close channels */
-    close(rec_ch);
-    close(send_ch);
-
-    return;
 }
 
-char *mask_preprocessing(char *mask, char *raster, int rl, int cl)
+char *mask_preprocessing(char *mask, char *raster, struct area_entry *ad)
 {
-    char *mapset, *mask_mapset, *tmp_file;
+    const char *tmp_file;
+    char *mapset, *mask_mapset;
     struct Cell_head cell, oldcell;
     int mask_fd, old_fd, *buf, i, j;
     CELL *old;
-    double add_row, add_col;
 
-    buf = G_malloc(cl * sizeof(int));
+    buf = G_malloc(ad->cl * sizeof(int));
 
     G_debug(3, "daemon mask preproc: raster=[%s] mask=[%s]  rl=%d cl=%d",
-	    raster, mask, rl, cl);
+	    raster, mask, ad->rl, ad->cl);
 
     /* mapset is used hold the mapset of input raster */
     mapset = G_find_cell(raster, "");
@@ -243,40 +240,37 @@
     if (G_get_cellhd(raster, mapset, &cell) == -1)
 	return NULL;
 
-
     mask_mapset = G_find_cell(mask, "");
 
     /* open raster */
     if (G_get_cellhd(mask, mask_mapset, &oldcell) == -1)
 	return NULL;
 
-    add_row = 1.0 * oldcell.rows / rl;
-    add_col = 1.0 * oldcell.cols / cl;
-
     tmp_file = G_tempfile();
     mask_fd = open(tmp_file, O_RDWR | O_CREAT, 0755);
-
     old_fd = G_open_cell_old(mask, mask_mapset);
-
-    G_debug(1, "worker.c: mask <%s@%s>", mask, mask_mapset);
     old = G_allocate_cell_buf();
 
-    for (i = 0; i < rl; i++) {
-	int riga;
+    /* write out sample area size: ad->rl rows and ad->cl columns */
 
-	riga = (int)rint(i * add_row);
-	G_get_map_row_nomask(old_fd, old, riga);
-	for (j = 0; j < cl; j++) {
-	    int colonna;
+    for (i = 0; i < ad->rl; i++) {
 
-	    colonna = (int)rint(j * add_col);
-	    buf[j] = old[colonna];
+	G_get_map_row_nomask(old_fd, old, i + ad->y);
+	for (j = 0; j < ad->cl; j++) {
+
+	    /* NULL -> 0, else 1 */
+	    buf[j] = !G_is_null_value(&old[j + ad->x], CELL_TYPE);
 	}
-	if (write(mask_fd, buf, cl * sizeof(int)) < 0)
+	if (write(mask_fd, buf, ad->cl * sizeof(int)) < 0)
 	    return NULL;
     }
 
     close(mask_fd);
+    G_close_cell(old_fd);
+    
+    G_free(buf);
+    G_free(old);
+    
     return G_store(tmp_file);
 }
 
@@ -284,7 +278,7 @@
 {
     int hash;
 
-    hash = row % ad->rl;
+    hash = row % ad->rc;
     if (ad->cm->contents[hash] == row)
 	return ad->cm->cache[hash];
     else {
@@ -299,7 +293,7 @@
 {
     int hash;
 
-    hash = row % ad->rl;
+    hash = row % ad->rc;
     if (ad->dm->contents[hash] == row)
 	return ad->dm->cache[hash];
     else {
@@ -314,7 +308,7 @@
 {
     int hash;
 
-    hash = row % ad->rl;
+    hash = row % ad->rc;
     if (ad->fm->contents[hash] == row)
 	return ad->fm->cache[hash];
     else {

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.dominance/dominance.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.dominance/dominance.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.dominance/dominance.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -15,20 +15,20 @@
  *
  *****************************************************************************/
 
-#include <grass/gis.h>
-#include <grass/glocale.h>
-
 #include <stdlib.h>
 #include <fcntl.h>
 #include <math.h>
 
-#include "../r.li.daemon/defs.h"
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+#include "../r.li.daemon/daemon.h"
 #include "../r.li.daemon/avlDefs.h"
 #include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
 
 /* template is shannon */
 
+rli_func dominance;
 int calculate(int fd, struct area_entry *ad, double *result);
 int calculateD(int fd, struct area_entry *ad, double *result);
 int calculateF(int fd, struct area_entry *ad, double *result);
@@ -66,15 +66,9 @@
 
 int dominance(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
@@ -98,8 +92,9 @@
 	}
     }
 
-    if (ris != RLI_OK)
+    if (ris != RLI_OK) {
 	return RLI_ERRORE;
+    }
 
     *result = indice;
 
@@ -114,30 +109,23 @@
     CELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
     avl_tree albero = NULL;
     AVL_table *array;
+    generic_cell uc;
 
-    generic_cell cc;
+    uc.t = CELL_TYPE;
 
-    cc.t = CELL_TYPE;
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -151,7 +139,6 @@
     }
 
     G_set_c_null_value(&precCell, 1);
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -161,74 +148,73 @@
 	}
 
 	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf[i + ad->x];
 
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, CELL_TYPE))) {
-		a = 1;
-		if (G_is_null_value(&precCell, cc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
-		    if (albero == NULL) {
-			cc.val.c = precCell;
-			albero = avl_make(cc, totCorr);
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
 
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
+		    if (albero == NULL) {
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			/* TODO missing?: else  - see r.li.simpson/simpson.c */
-			m++;
-		    }
-		    else {
-			cc.val.c = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-		precCell = corrCell;
-	    }
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
 
-	}			/* end for */
-    }				/* end for */
-
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.c = precCell;
-	    albero = avl_make(cc, totCorr);
-
+	    uc.val.c = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -236,8 +222,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.c = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.c = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -260,7 +246,12 @@
 		}
 	    }
 	}
+    }
 
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
 	array = G_malloc(m * sizeof(AVL_tableRow));
 	if (array == NULL) {
@@ -274,28 +265,26 @@
 	}
 
 	/* calculate shannon */
+	shannon = 0;
 	for (i = 0; i < m; i++) {
-	    t = (double)array[i]->tot;
-	    percentuale = (double)(t / area);
-	    logaritmo = (double)log(percentuale);
-	    somma = somma + (percentuale * logaritmo);
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
 	}
-
-	if (m != 0)
-	    indice = log((double)m) + somma;
-	else
-	    indice = 0;
 	G_free(array);
+
+	*result = log(m) + shannon;
     }
-    else			/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+    else
+	G_set_d_null_value(result, 1);
 
-
-    if (masked)
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
-    *result = indice;
-
     return RLI_OK;
 }
 
@@ -307,28 +296,22 @@
     DCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
     avl_tree albero = NULL;
     AVL_table *array;
-    generic_cell cc;
+    generic_cell uc;
 
-    cc.t = DCELL_TYPE;
+    uc.t = DCELL_TYPE;
 
     /* open mask if needed */
     if (ad->mask == 1) {
@@ -343,7 +326,6 @@
     }
 
     G_set_d_null_value(&precCell, 1);
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -354,75 +336,72 @@
 
 	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, DCELL_TYPE))) {
-		a = 1;
-		if (G_is_null_value(&precCell, DCELL_TYPE)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			cc.val.dc = precCell;
-			albero = avl_make(cc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			cc.val.dc = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-		precCell = corrCell;
-	    }
-
-	}			/*close for */
-    }				/*close for */
-
-    if (masked) {
-	G_free(mask_buf);
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
     }
 
-	/*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.dc = precCell;
-	    albero = avl_make(cc, totCorr);
+	    uc.val.dc = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -430,8 +409,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.fc = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.dc = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -454,7 +433,12 @@
 		}
 	    }
 	}
+    }
 
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
 	array = G_malloc(m * sizeof(AVL_tableRow));
 	if (array == NULL) {
@@ -463,33 +447,31 @@
 	}
 	tot = avl_to_array(albero, zero, array);
 	if (tot != m) {
-	    G_warning
-		("avl_to_array unaspected value. the result could be wrong");
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
 	    return RLI_ERRORE;
 	}
 
-	/* calculate summary */
+	/* calculate shannon */
+	shannon = 0;
 	for (i = 0; i < m; i++) {
-	    t = (double)array[i]->tot;
-	    percentuale = (double)(t / area);
-	    logaritmo = (double)log(percentuale);
-	    somma = somma + (percentuale * logaritmo);
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
 	}
 	G_free(array);
 
-	if (m != 0)
-	    indice = log((double)m) + somma;
-	else
-	    indice = 0;
+	*result = log(m) + shannon;
     }
     else
-	/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+    }
 
-    *result = indice;
-
-
     return RLI_OK;
 }
 
@@ -501,28 +483,22 @@
     FCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
     avl_tree albero = NULL;
     AVL_table *array;
-    generic_cell cc;
+    generic_cell uc;
 
-    cc.t = FCELL_TYPE;
+    uc.t = FCELL_TYPE;
 
     /* open mask if needed */
     if (ad->mask == 1) {
@@ -547,73 +523,72 @@
 
 	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each fcell in the row */
-
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, FCELL_TYPE))) {
-		a = 1;
-		if (G_is_null_value(&precCell, FCELL_TYPE)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			cc.val.fc = precCell;
-			albero = avl_make(cc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			cc.val.fc = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-
-		precCell = corrCell;
-	    }
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.fc = precCell;
-	    albero = avl_make(cc, totCorr);
+	    uc.val.fc = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -621,8 +596,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.fc = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.fc = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -645,7 +620,12 @@
 		}
 	    }
 	}
+    }
 
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
 	array = G_malloc(m * sizeof(AVL_tableRow));
 	if (array == NULL) {
@@ -659,29 +639,25 @@
 	}
 
 	/* calculate shannon */
+	shannon = 0;
 	for (i = 0; i < m; i++) {
-	    t = (double)array[i]->tot;
-	    percentuale = (double)(t / area);
-	    logaritmo = (double)log(percentuale);
-	    somma = somma + (percentuale * logaritmo);
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
 	}
-
-	if (m != 0)
-	    indice = log((double)m) + somma;
-	else
-	    indice = 0;
-
 	G_free(array);
+
+	*result = log(m) + shannon;
     }
-    else			/*if a is 0, that is all cell are null, i put index=-1 */
-	  indice = (double)(-1);
+    else
+	G_set_d_null_value(result, 1);
 
-
+    avl_destroy(albero);
     if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
     }
 
-    *result = indice;
-
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.edgedensity/edgedensity.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.edgedensity/edgedensity.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.edgedensity/edgedensity.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,28 +1,35 @@
-/*
- * \brief calculates edge density index
+
+/****************************************************************************
  *
- *  AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.edgedensity
+ * AUTHOR(S):    Serena Pallecchi student of Computer Science University of Pisa (Italy)
+ *               Commission from Faunalia Pontedera (PI) www.faunalia.it
+ *               Rewrite: Markus Metz
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
+ * PURPOSE:      calculates edge density index
+ * COPYRIGHT:    (C) 2006-2014 by the GRASS Development Team
  *
- */
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
 
-#include <grass/gis.h>
-#include <grass/glocale.h>
-
 #include <stdlib.h>
 #include <fcntl.h>		/* for O_RDONLY usage */
 #include <math.h>
 
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
 #include "../r.li.daemon/avlDefs.h"
 #include "../r.li.daemon/avl.h"
 #include "../r.li.daemon/daemon.h"
 
-int calculate(int fd, struct area_entry *ad, char **valore, double *result);
-int calculateD(int fd, struct area_entry *ad, char **valore, double *result);
-int calculateF(int fd, struct area_entry *ad, char **valore, double *result);
+rli_func edgedensity;
+int calculate(int fd, struct area_entry *ad, char **par, double *result);
+int calculateD(int fd, struct area_entry *ad, char **par, double *result);
+int calculateF(int fd, struct area_entry *ad, char **par, double *result);
 
 int main(int argc, char *argv[])
 {
@@ -56,6 +63,7 @@
     class->description = _("It can be integer, double or float; "
 			   "it will be changed in function of map type");
 
+
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
@@ -67,35 +75,27 @@
 
     return calculateIndex(conf->answer, edgedensity, par, raster->answer,
 			  output->answer);
-
 }
 
-int edgedensity(int fd, char **valore, struct area_entry *ad, double *result)
+int edgedensity(int fd, char **par, struct area_entry *ad, double *result)
 {
-    struct Cell_head hd;
     int ris = -1;
-    char *mapset;
     double indice = 0;
 
-    mapset = G_find_cell(ad->raster, "");
-
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
-	    ris = calculate(fd, ad, valore, &indice);
+	    ris = calculate(fd, ad, par, &indice);
 	    break;
 	}
     case DCELL_TYPE:
 	{
-	    ris = calculateD(fd, ad, valore, &indice);
+	    ris = calculateD(fd, ad, par, &indice);
 	    break;
 	}
     case FCELL_TYPE:
 	{
-	    ris = calculateF(fd, ad, valore, &indice);
+	    ris = calculateF(fd, ad, par, &indice);
 	    break;
 	}
     default:
@@ -114,726 +114,536 @@
 }
 
 
-int calculate(int fd, struct area_entry *ad, char **valore, double *result)
+int calculate(int fd, struct area_entry *ad, char **par, double *result)
 {
-    double indice = 0;
-    double e = 0;
-    double somma = 0;
-    double area = 0;
-    CELL *buf_corr, *buf_sup, *buf_inf;
-    CELL prevCell, corrCell, supCell, infCell, nextCell;
-    AVL_table *array;
-    long tot = 0;
-    long zero = 0;
-    long m = 0;
-    long bordoCorr = 0;
-    avl_tree albero = NULL;
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    CELL ptype;
+    long nedges, area; 
     int i, j;
-    int mask_fd = -1, *mask_corr, *mask_sup, *mask_inf;
-    int masked = FALSE;
-    int ris;
-    generic_cell c1;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    buf_sup = NULL;
-    c1.t = CELL_TYPE;
+    G_get_window(&hd);
 
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
-
-	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0) {
-	    G_fatal_error("Cannot open mask file <%s>", ad->mask_name);
-	    return RLI_ERRORE;  /* FIXME: can not return from a fatal error */
-	}
-
-	mask_corr = G_malloc(ad->cl * sizeof(int));
-	if (mask_corr == NULL) {
-	    G_fatal_error("malloc mask_corr failed");
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
 	}
-
-	mask_inf = G_malloc(ad->cl * sizeof(int));
-	if (mask_inf == NULL) {
-	    G_fatal_error("malloc mask_inf failed");
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
 
 	masked = TRUE;
     }
 
-    buf_sup = G_allocate_cell_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
+    buf_null = G_allocate_cell_buf();
+    if (buf_null == NULL) {
+	G_fatal_error("malloc buf_null failed");
 	return RLI_ERRORE;
     }
 
     /* the first time buf_sup is all null */
-    G_set_c_null_value(buf_sup + ad->x, ad->cl);
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
+    if (par != NULL) {	/* only 1 class */
+	char *sval;
+
+	sval = par[0];
+	ptype = atoi(sval);
+    }
+    else
+	G_set_c_null_value(&ptype, 1);
+
+    nedges = 0;
+    area = 0;
+
     /* for each raster row */
-    for (j = 0; j < ad->rl; j++) {
+    for (i = 0; i < ad->rl; i++) {
 
 	/* read row of raster */
-	buf_corr = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
 
-	if (j > 0)		/* not first row */
-	    buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+	if (i > 0)		/* not first row */
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
 
-	if ((j + 1) < ad->rl) {	/*not last row */
-	    buf_inf = RLI_get_cell_raster_row(fd, 1 + j + ad->y, ad);
-	}
-	else {
-	    buf_inf = G_allocate_cell_buf();
-	    if (buf_inf == NULL) {
-		G_fatal_error("malloc buf_inf failed");
+	/* read mask if needed */
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
 		return RLI_ERRORE;
-	    }
-	    G_set_c_null_value(buf_inf + ad->x, ad->cl);
 	}
 
-	/*read mask if needed */
-	if (masked) {
-	    if (read(mask_fd, mask_corr, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("reading mask_corr");
-		return RLI_ERRORE;
-	    }
+	G_set_c_null_value(&precCell, 1);
 
-	    if ((j + 1) < ad->rl) {	/* not last row */
-		if (read(mask_fd, mask_inf, (ad->cl * sizeof(int))) < 0) {
-		    G_fatal_error("reading mask_inf at row j");
-		    return RLI_ERRORE;
-		}
+	for (j = 0; j < ad->cl; j++) {
+	    corrCell = buf[j + ad->x];
+
+	    if (masked && mask_buf[j] == 0) {
+		G_set_c_null_value(&corrCell, 1);
 	    }
 	    else {
-		int z = 0;
-
-		for (z = 0; z < ad->cl; z++)
-		    mask_inf[z + ad->x] = 0;
+		/* total sample area */
+		area++;
 	    }
-	}
 
-	G_set_c_null_value(&nextCell, 1);
-	G_set_c_null_value(&prevCell, 1);
-	G_set_c_null_value(&corrCell, 1);
-
-	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
-	    corrCell = buf_corr[i + ad->x];
-
-
-	    if (masked && mask_corr[i + ad->x] == 0) {
-		G_set_c_null_value(&corrCell, 1);
-		area--;
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
 	    }
 
-	    if (!(G_is_null_value(&corrCell, CELL_TYPE))) {
-		if ((i + 1) == ad->cl)	/*last cell of the row */
-		    G_set_c_null_value(&nextCell, 1);
-		else if (masked && mask_corr[i + 1 + ad->x] == 0)
-		    G_set_c_null_value(&nextCell, 1);
-		else
-		    nextCell = buf_corr[i + 1 + ad->x];
-
-		supCell = buf_sup[i + ad->x];
-
-		if (masked && mask_inf[i + ad->x] == 0)
-		    G_set_c_null_value(&infCell, 1);
-		else
-		    infCell = buf_inf[i + ad->x];
-
-		/* calculate how many edges the cell has */
-		if ((G_is_null_value(&prevCell, CELL_TYPE)) ||
-		    (corrCell != prevCell)) {
-		    bordoCorr++;
+	    if (!G_is_c_null_value(&ptype)) {
+		/* only one patch type */
+		if (!G_is_c_null_value(&corrCell) && corrCell == ptype) {
+		    if (corrCell != precCell)
+			nedges++;
+		    if (corrCell != supCell)
+			nedges++;
+		    /* right and bottom */
+		    if (i == ad->rl - 1)
+			nedges++;
+		    if (j == ad->cl - 1)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&supCell, CELL_TYPE)) ||
-		    (corrCell != supCell)) {
-		    bordoCorr++;
+		if (!G_is_c_null_value(&precCell) && precCell == ptype) {
+		    if (corrCell != precCell)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&infCell, CELL_TYPE)) ||
-		    (corrCell != infCell)) {
-		    bordoCorr++;
+		if (!G_is_c_null_value(&supCell) && supCell == ptype) {
+		    if (corrCell != supCell)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&nextCell, CELL_TYPE)) ||
-		    (corrCell != nextCell)) {
-		    bordoCorr++;
-		}
-
-		/* store the result in the tree */
-		if (albero == NULL) {
-		    c1.val.c = corrCell;
-		    albero = avl_make(c1, bordoCorr);
-		    if (albero == NULL) {
-			G_fatal_error("avl_make error");
-			return RLI_ERRORE;
+	    }
+	    else {
+		/* all patch types */
+		if (!G_is_c_null_value(&corrCell)) {
+		    if (corrCell != precCell) {
+			nedges++;
 		    }
-		    m++;
-		}
-		else {
-		    c1.val.c = corrCell;
-		    ris = avl_add(&albero, c1, bordoCorr);
-
-		    switch (ris) {
-		    case AVL_ERR:
-			{
-			    G_fatal_error("avl_add error");
-			    return RLI_ERRORE;
-			}
-		    case AVL_ADD:
-			{
-			    m++;
-			    break;
-			}
-		    case AVL_PRES:
-			{
-			    break;
-			}
-		    default:
-			{
-			    G_fatal_error("avl_add unknown error");
-			    return RLI_ERRORE;
-			}
+		    if (corrCell != supCell) {
+			nedges++;
 		    }
+		    /* right and bottom */
+		    if (i == ad->rl - 1)
+			nedges++;
+		    if (j == ad->cl - 1)
+			nedges++;
 		}
-		bordoCorr = 0;
+		if (!G_is_c_null_value(&precCell) && corrCell != precCell) {
+		    nedges++;
+		}
+		if (!G_is_c_null_value(&supCell) && corrCell != supCell) {
+		    nedges++;
+		}
 	    }
-	    prevCell = buf_corr[i + ad->x];
+	    precCell = corrCell;
 	}
-	if (masked)
-	    mask_sup = mask_corr;
     }
 
     /* calculate index */
-    if (area == 0)
-	indice = -1;
-    else {
+    if (area > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double elength, cell_size;
 
-	if (valore != NULL) {	/* only 1 class */
-	    char *sval;
-	    int val;
-	    CELL cella;
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-	    sval = valore[0];
-	    val = atoi(sval);
-	    cella = val;
-	    c1.t = CELL_TYPE;
-	    c1.val.c = cella;
-	    e = (double)howManyCell(albero, c1);
-	    somma = e;
-	}
-	else {			/* all classes */
-	    array = G_malloc(m * sizeof(AVL_tableRow));
-	    if (array == NULL) {
-		G_fatal_error("malloc array failed");
-		return RLI_ERRORE;
-	    }
-	    tot = avl_to_array(albero, zero, array);
-	    if (tot != m) {
-		G_warning
-		    ("avl_to_array unexpected value. the result could be wrong");
-	    }
-	    for (i = 0; i < m; i++) {
-		e = (double)array[i]->tot;
-		somma = somma + e;
-	    }
-	    G_free(array);
-	}
+	elength = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols) + 
+	          (NS_DIST1 + NS_DIST2) / (2  * hd.rows)) / 2;
 
-	indice = somma * 10000 / area;
+	cell_size = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols)) *
+	            ((NS_DIST1 + NS_DIST2) / (2 * hd.rows));
+
+	*result = (double) nedges * elength * 10000 / (area * cell_size);
     }
+    else
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
     if (masked) {
-	G_free(mask_inf);
-	G_free(mask_corr);
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
     }
+    G_free(buf_null);
 
-    /* G_free(buf_sup); */   /* <-- why not free it? */
     return RLI_OK;
 }
 
-int calculateD(int fd, struct area_entry *ad, char **valore, double *result)
+int calculateD(int fd, struct area_entry *ad, char **par, double *result)
 {
-    double indice = 0;
-    double e = 0;
-    double somma = 0;
-    double area = 0;
-
-    DCELL *buf_corr, *buf_sup, *buf_inf;
-    DCELL prevCell, corrCell, supCell, infCell, nextCell;
-
-    AVL_table *array;
-
-    long tot = 0;
-    long zero = 0;
-    long m = 0;
-    long bordoCorr = 0;
-
-    avl_tree albero = NULL;
-
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    DCELL ptype;
+    long nedges, area; 
     int i, j;
-    int mask_fd = -1, *mask_corr, *mask_sup, *mask_inf;
-    int masked = FALSE;
-    int ris;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    generic_cell c1;
+    G_get_window(&hd);
 
-    c1.t = DCELL_TYPE;
-
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
-	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0) {
-	    G_fatal_error("Cannot open mask file");
-	    return RLI_ERRORE;  /* FIXME: can not return from a fatal error */
-	}
-
-	mask_corr = G_malloc(ad->cl * sizeof(int));
-	if (mask_corr == NULL) {
-	    G_fatal_error("malloc mask_corr failed");
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
 	}
-
-	mask_inf = G_malloc(ad->cl * sizeof(int));
-	if (mask_inf == NULL) {
-	    G_fatal_error("malloc mask_inf failed");
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
 
 	masked = TRUE;
     }
 
-    buf_sup = G_allocate_d_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
+    buf_null = G_allocate_d_raster_buf();
+    if (buf_null == NULL) {
+	G_fatal_error("malloc buf_null failed");
 	return RLI_ERRORE;
     }
 
-    G_set_d_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
+    /* the first time buf_sup is all null */
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
+    if (par != NULL) {	/* only 1 class */
+	char *sval;
 
-    for (j = 0; j < ad->rl; j++) {	/* for each raster row */
+	sval = par[0];
+	ptype = atof(sval);
+    }
+    else
+	G_set_d_null_value(&ptype, 1);
 
-	buf_corr = RLI_get_dcell_raster_row(fd, j + ad->y, ad);	/* read row of raster */
+    nedges = 0;
+    area = 0;
 
-	if (j > 0)		/* not first row */
-	    buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+    /* for each raster row */
+    for (i = 0; i < ad->rl; i++) {
 
+	/* read row of raster */
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
 
-	if ((j + 1) < ad->rl) {	/*not last row */
+	if (i > 0)		/* not first row */
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
 
-	    buf_inf = RLI_get_dcell_raster_row(fd, 1 + j + ad->y, ad);
-	}
-	else {
-	    buf_inf = G_allocate_d_raster_buf();
-	    if (buf_inf == NULL) {
-		G_fatal_error("malloc buf_inf failed");
+	/* read mask if needed */
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
 		return RLI_ERRORE;
-	    }
-
-	    G_set_d_null_value(buf_inf + ad->x, ad->cl);
 	}
 
-	/*read mask if needed */
-	if (masked) {
+	G_set_d_null_value(&precCell, 1);
 
-	    if (read(mask_fd, mask_corr, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("reading mask_corr");
-		return RLI_ERRORE;
-	    }
+	for (j = 0; j < ad->cl; j++) {
+	    corrCell = buf[j + ad->x];
 
-	    if ((j + 1) < ad->rl) {	/*not last row */
-		if (read(mask_fd, mask_inf, (ad->cl * sizeof(int))) < 0) {
-		    G_fatal_error("reading mask_inf");
-		    return RLI_ERRORE;
-		}
+	    if (masked && mask_buf[j] == 0) {
+		G_set_d_null_value(&corrCell, 1);
 	    }
 	    else {
-		int z = 0;
-
-		for (z = 0; z < ad->cl; z++)
-		    mask_inf[z + ad->x] = 0;
+		/* total sample area */
+		area++;
 	    }
-	}
 
-	G_set_d_null_value(&nextCell, 1);
-	G_set_d_null_value(&prevCell, 1);
-	G_set_d_null_value(&corrCell, 1);
-
-	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
-	    corrCell = buf_corr[i + ad->x];
-
-	    if (masked && mask_corr[i + ad->x] == 0) {
-		G_set_d_null_value(&corrCell, 1);
-		area--;
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
 	    }
 
-	    if (!(G_is_null_value(&corrCell, DCELL_TYPE))) {
-		if ((i + 1) == ad->cl)	/*last cell of the row */
-		    G_set_d_null_value(&nextCell, 1);
-		else if (masked && mask_corr[i + 1 + ad->x] == 0)
-		    G_set_d_null_value(&nextCell, 1);
-		else
-		    nextCell = buf_corr[i + 1 + ad->x];
-
-		supCell = buf_sup[i + ad->x];
-
-		if (masked && mask_inf[i + ad->x] == 0)
-		    G_set_d_null_value(&infCell, 1);
-		else
-		    infCell = buf_inf[i + ad->x];
-
-		/* calculate how many edge the cell has */
-
-		if ((G_is_null_value(&prevCell, DCELL_TYPE)) ||
-		    (corrCell != prevCell)) {
-		    bordoCorr++;
+	    if (!G_is_d_null_value(&ptype)) {
+		/* only one patch type */
+		if (!G_is_d_null_value(&corrCell) && corrCell == ptype) {
+		    if (corrCell != precCell)
+			nedges++;
+		    if (corrCell != supCell)
+			nedges++;
+		    /* right and bottom */
+		    if (i == ad->rl - 1)
+			nedges++;
+		    if (j == ad->cl - 1)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&supCell, DCELL_TYPE)) ||
-		    (corrCell != supCell)) {
-		    bordoCorr++;
+		if (!G_is_d_null_value(&precCell) && precCell == ptype) {
+		    if (corrCell != precCell)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&infCell, DCELL_TYPE)) ||
-		    (corrCell != infCell)) {
-		    bordoCorr++;
+		if (!G_is_d_null_value(&supCell) && supCell == ptype) {
+		    if (corrCell != supCell)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&nextCell, DCELL_TYPE)) ||
-		    (corrCell != nextCell)) {
-		    bordoCorr++;
-		}
-
-		/* store the result in the tree */
-		if (albero == NULL) {
-		    c1.val.dc = corrCell;
-		    albero = avl_make(c1, bordoCorr);
-		    if (albero == NULL) {
-			G_fatal_error("avl_make error");
-			return RLI_ERRORE;
+	    }
+	    else {
+		/* all patch types */
+		if (!G_is_d_null_value(&corrCell)) {
+		    if (corrCell != precCell) {
+			nedges++;
 		    }
-		    m++;
-		}
-		else {
-		    c1.val.dc = corrCell;
-		    ris = avl_add(&albero, c1, bordoCorr);
-
-		    switch (ris) {
-		    case AVL_ERR:
-			{
-			    G_fatal_error("avl_add error");
-			    return RLI_ERRORE;
-			}
-		    case AVL_ADD:
-			{
-			    m++;
-			    break;
-			}
-		    case AVL_PRES:
-			{
-			    break;
-			}
-		    default:
-			{
-			    G_fatal_error("avl_add unknown error");
-			    return RLI_ERRORE;
-			}
+		    if (corrCell != supCell) {
+			nedges++;
 		    }
+		    /* right and bottom */
+		    if (i == ad->rl - 1)
+			nedges++;
+		    if (j == ad->cl - 1)
+			nedges++;
 		}
-		bordoCorr = 0;
+		if (!G_is_d_null_value(&precCell) && corrCell != precCell) {
+		    nedges++;
+		}
+		if (!G_is_d_null_value(&supCell) && corrCell != supCell) {
+		    nedges++;
+		}
 	    }
-	    prevCell = buf_corr[i + ad->x];
+	    precCell = corrCell;
 	}
-	if (masked)
-	    mask_sup = mask_corr;
     }
 
     /* calculate index */
-    if (area == 0)
-	indice = -1;
-    else {
-	if (valore != NULL) {	/* only 1 class */
-	    char *sval;
-	    double val;
-	    DCELL cella;
+    if (area > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double elength, cell_size;
 
-	    sval = valore[0];
-	    val = (double)atof(sval);
-	    cella = val;
-	    c1.val.dc = cella;
-	    c1.t = DCELL_TYPE;
-	    e = (double)howManyCell(albero, c1);
-	    somma = e;
-	}
-	else {			/* all classes */
-	    array = G_malloc(m * sizeof(AVL_tableRow));
-	    if (array == NULL) {
-		G_fatal_error("malloc array failed");
-		return RLI_ERRORE;
-	    }
-	    tot = avl_to_array(albero, zero, array);
-	    if (tot != m) {
-		G_warning
-		    ("avl_to_array unexpected value. the result could be wrong");
-	    }
-	    for (i = 0; i < m; i++) {
-		e = (double)array[i]->tot;
-		somma = somma + e;
-	    }
-	    G_free(array);
-	}
-	indice = somma * 10000 / area;
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
+
+	elength = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols) + 
+	          (NS_DIST1 + NS_DIST2) / (2  * hd.rows)) / 2;
+
+	cell_size = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols)) *
+	            ((NS_DIST1 + NS_DIST2) / (2 * hd.rows));
+
+	*result = (double) nedges * elength * 10000 / (area * cell_size);
     }
+    else
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
     if (masked) {
-	G_free(mask_inf);
-	G_free(mask_corr);
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
     }
+    G_free(buf_null);
+
     return RLI_OK;
 }
 
-int calculateF(int fd, struct area_entry *ad, char **valore, double *result)
+int calculateF(int fd, struct area_entry *ad, char **par, double *result)
 {
-    double indice = 0;
-    double e = 0;
-    double somma = 0;
-    double area = 0;
-
-    FCELL *buf_corr, *buf_sup, *buf_inf;
-    FCELL prevCell, corrCell, supCell, infCell, nextCell;
-
-    AVL_table *array;
-
-    long tot = 0;
-    long zero = 0;
-    long m = 0;
-    long bordoCorr = 0;
-
-    avl_tree albero = NULL;
-
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    FCELL ptype;
+    long nedges, area; 
     int i, j;
-    int mask_fd = -1, *mask_corr, *mask_sup, *mask_inf;
-    int masked = FALSE;
-    int ris;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    generic_cell c1;
+    G_get_window(&hd);
 
-    c1.t = FCELL_TYPE;
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
-	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0) {
-	    G_fatal_error("Cannot open mask file");
-	    return RLI_ERRORE;  /* FIXME: can not return from a fatal error */
-	}
-
-	mask_corr = G_malloc(ad->cl * sizeof(int));
-	if (mask_corr == NULL) {
-	    G_fatal_error("malloc mask_corr failed");
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
 	}
-
-	mask_inf = G_malloc(ad->cl * sizeof(int));
-	if (mask_inf == NULL) {
-	    G_fatal_error("malloc mask_inf failed");
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
 
 	masked = TRUE;
     }
 
-    buf_sup = G_allocate_f_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
+    buf_null = G_allocate_f_raster_buf();
+    if (buf_null == NULL) {
+	G_fatal_error("malloc buf_null failed");
 	return RLI_ERRORE;
     }
 
     /* the first time buf_sup is all null */
-    G_set_f_null_value(buf_sup + ad->x, ad->cl);
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
+    if (par != NULL) {	/* only 1 class */
+	char *sval;
+
+	sval = par[0];
+	ptype = atof(sval);
+    }
+    else
+	G_set_f_null_value(&ptype, 1);
+
+    nedges = 0;
+    area = 0;
+
     /* for each raster row */
-    for (j = 0; j < ad->rl; j++) {
+    for (i = 0; i < ad->rl; i++) {
+
 	/* read row of raster */
-	buf_corr = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
 
-	if (j > 0)		/* not first row */
-	    buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+	if (i > 0)		/* not first row */
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
 
-	if ((j + 1) < ad->rl) {	/* not last row */
-	    buf_inf = RLI_get_fcell_raster_row(fd, 1 + j + ad->y, ad);
-	}
-	else {
-	    buf_inf = G_allocate_f_raster_buf();
-	    if (mask_inf == NULL) {
-		G_fatal_error("malloc mask_inf failed");
+	/* read mask if needed */
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
 		return RLI_ERRORE;
-	    }
-	    G_set_f_null_value(buf_inf + ad->x, ad->cl);
 	}
 
-	/* read mask if needed */
-	if (masked) {
+	G_set_f_null_value(&precCell, 1);
 
-	    if (read(mask_fd, mask_corr, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("reading mask_corr");
-		return RLI_ERRORE;
-	    }
+	for (j = 0; j < ad->cl; j++) {
+	    corrCell = buf[j + ad->x];
 
-	    if ((j + 1) < ad->rl) {	/*not last row */
-		if (read(mask_fd, mask_inf, (ad->cl * sizeof(int))) < 0) {
-		    G_fatal_error("reading mask_inf");
-		    return RLI_ERRORE;
-		}
+	    if (masked && mask_buf[j] == 0) {
+		G_set_f_null_value(&corrCell, 1);
 	    }
 	    else {
-		int z = 0;
-
-		for (z = 0; z < ad->cl; z++)
-		    mask_inf[z + ad->x] = 0;
+		/* total sample area */
+		area++;
 	    }
-	}
 
-	G_set_f_null_value(&nextCell, 1);
-	G_set_f_null_value(&prevCell, 1);
-	G_set_f_null_value(&corrCell, 1);
-
-	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
-	    corrCell = buf_corr[i + ad->x];
-
-
-	    if (masked && mask_corr[i + ad->x] == 0) {
-		G_set_f_null_value(&corrCell, 1);
-		area--;
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
 	    }
 
-	    if (!(G_is_null_value(&corrCell, FCELL_TYPE))) {
-
-		if ((i + 1) == ad->cl)	/*last cell of the row */
-		    G_set_f_null_value(&nextCell, 1);
-		else if (masked && mask_corr[i + 1 + ad->x] == 0)
-		    G_set_f_null_value(&nextCell, 1);
-		else
-		    nextCell = buf_corr[i + 1 + ad->x];
-
-		supCell = buf_sup[i + ad->x];
-
-		if (masked && mask_inf[i + ad->x] == 0)
-		    G_set_f_null_value(&infCell, 1);
-		else
-		    infCell = buf_inf[i + ad->x];
-
-		/* calculate how many edge the cell has */
-		if ((G_is_null_value(&prevCell, FCELL_TYPE)) ||
-		    (corrCell != prevCell)) {
-		    bordoCorr++;
+	    if (!G_is_f_null_value(&ptype)) {
+		/* only one patch type */
+		if (!G_is_f_null_value(&corrCell) && corrCell == ptype) {
+		    if (corrCell != precCell)
+			nedges++;
+		    if (corrCell != supCell)
+			nedges++;
+		    /* right and bottom */
+		    if (i == ad->rl - 1)
+			nedges++;
+		    if (j == ad->cl - 1)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&supCell, FCELL_TYPE)) ||
-		    (corrCell != supCell)) {
-		    bordoCorr++;
+		if (!G_is_f_null_value(&precCell) && precCell == ptype) {
+		    if (corrCell != precCell)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&infCell, FCELL_TYPE)) ||
-		    (corrCell != infCell)) {
-		    bordoCorr++;
+		if (!G_is_f_null_value(&supCell) && supCell == ptype) {
+		    if (corrCell != supCell)
+			nedges++;
 		}
-
-		if ((G_is_null_value(&nextCell, FCELL_TYPE)) ||
-		    (corrCell != nextCell)) {
-		    bordoCorr++;
-		}
-
-		/* store the result in the tree */
-		if (albero == NULL) {
-		    c1.val.c = corrCell;
-		    albero = avl_make(c1, bordoCorr);
-		    if (albero == NULL) {
-			G_fatal_error("avl_make error");
-			return RLI_ERRORE;
+	    }
+	    else {
+		/* all patch types */
+		if (!G_is_f_null_value(&corrCell)) {
+		    if (corrCell != precCell) {
+			nedges++;
 		    }
-		    m++;
-		}
-		else {
-		    c1.val.c = corrCell;
-		    ris = avl_add(&albero, c1, bordoCorr);
-
-		    switch (ris) {
-		    case AVL_ERR:
-			{
-			    G_fatal_error("avl_add error");
-			    return RLI_ERRORE;
-			}
-		    case AVL_ADD:
-			{
-			    m++;
-			    break;
-			}
-		    case AVL_PRES:
-			{
-			    break;
-			}
-		    default:
-			{
-			    G_fatal_error("avl_add unknown error");
-			    return RLI_ERRORE;
-			}
+		    if (corrCell != supCell) {
+			nedges++;
 		    }
+		    /* right and bottom */
+		    if (i == ad->rl - 1)
+			nedges++;
+		    if (j == ad->cl - 1)
+			nedges++;
 		}
-		bordoCorr = 0;
+		if (!G_is_f_null_value(&precCell) && corrCell != precCell) {
+		    nedges++;
+		}
+		if (!G_is_f_null_value(&supCell) && corrCell != supCell) {
+		    nedges++;
+		}
 	    }
-	    prevCell = buf_corr[i + ad->x];
+	    precCell = corrCell;
 	}
-	if (masked)
-	    mask_sup = mask_corr;
     }
 
     /* calculate index */
-    if (area == 0)
-	indice = -1;
-    else {
-	if (valore != NULL) {	/* only 1 class */
-	    char *sval;
-	    float val;
-	    FCELL cella;
+    if (area > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double elength, cell_size;
 
-	    sval = valore[0];
-	    val = (float)atof(sval);
-	    cella = val;
-	    c1.t = FCELL_TYPE;
-	    c1.val.fc = cella;
-	    e = (double)howManyCell(albero, c1);
-	    somma = e;
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-	}
-	else {			/* all classes */
-	    array = G_malloc(m * sizeof(AVL_tableRow));
-	    if (array == NULL) {
-		G_fatal_error("malloc array failederror");
-		return RLI_ERRORE;
-	    }
-	    tot = avl_to_array(albero, zero, array);
-	    if (tot != m) {
-		G_warning
-		    ("avl_to_array unaspected value. the result could be wrong");
-	    }
-	    for (i = 0; i < m; i++) {
-		e = (double)array[i]->tot;
-		somma = somma + e;
-	    }
-	    G_free(array);
-	}
-	indice = somma * 10000 / area;
+	elength = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols) + 
+	          (NS_DIST1 + NS_DIST2) / (2  * hd.rows)) / 2;
+
+	cell_size = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols)) *
+	            ((NS_DIST1 + NS_DIST2) / (2 * hd.rows));
+
+	*result = (double) nedges * elength * 10000 / (area * cell_size);
     }
+    else
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
-	G_free(mask_inf);
-	G_free(mask_corr);
+	G_free(mask_buf);
+	G_free(mask_sup);
     }
+    G_free(buf_null);
+
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.mpa/mpa.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.mpa/mpa.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.mpa/mpa.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,14 +1,19 @@
-
-/*
- * \brief calculates mean pixel attribute index
+/****************************************************************************
  *
- *  \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.mpa
+ * AUTHOR(S):    Serena Pallecchi (original contributor)
+ *                student of Computer Science University of Pisa (Italy)
+ *               Commission from Faunalia Pontedera (PI) www.faunalia.it
+ *               Rewrite: Markus Metz
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
+ * PURPOSE:      calculates mean pixel attribute index
+ * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
  *
- */
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
 
 #include <grass/gis.h>
 #include <grass/glocale.h>
@@ -21,7 +26,7 @@
 #include "../r.li.daemon/defs.h"
 #include "../r.li.daemon/daemon.h"
 
-
+rli_func meanPixelAttribute;
 int calculate(int fd, struct area_entry *ad, double *result);
 int calculateD(int fd, struct area_entry *ad, double *result);
 int calculateF(int fd, struct area_entry *ad, double *result);
@@ -58,15 +63,9 @@
 
 int meanPixelAttribute(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
     int ris = 0;
     double indice = 0;
-    struct Cell_head hd;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
@@ -105,11 +104,10 @@
     CELL *buf;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int masked = FALSE;
 
     double area = 0;
-    double indice = 0;
     double somma = 0;
 
     /* open mask if needed */
@@ -126,35 +124,32 @@
 	masked = TRUE;
     }
 
+    for (j = 0; j < ad->rl; j++) {
+	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
 
-    for (j = 0; j < ad->rl; j++) {	/*for each raster row */
-	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);	/*read raster row */
-
-	if (masked) {		/*read mask row if needed */
+	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
 		return RLI_ERRORE;
 	    }
 	}
 
-	for (i = 0; i < ad->cl; i++) {	/*for each cell in the row */
-	    area++;
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	for (i = 0; i < ad->cl; i++) {
+	    if (masked && mask_buf[i] == 0) {
 		G_set_c_null_value(&buf[i + ad->x], 1);
-		area--;
 	    }
-	    if (!(G_is_null_value(&buf[i + ad->x], CELL_TYPE))) {	/*if it's a cell to consider */
+	    if (!(G_is_c_null_value(&buf[i + ad->x]))) {
+		area++;
 		somma = somma + buf[i + ad->x];
 	    }
 	}
     }
 
-    if (area == 0)
-	indice = (double)-1;
+    if (area > 0)
+	*result = somma / area;
     else
-	indice = somma / area;
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
@@ -169,11 +164,10 @@
     DCELL *buf;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int masked = FALSE;
 
     double area = 0;
-    double indice = 0;
     double somma = 0;
 
     /* open mask if needed */
@@ -190,36 +184,32 @@
 	masked = TRUE;
     }
 
+    for (j = 0; j < ad->rl; j++) {
+	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
 
-
-    for (j = 0; j < ad->rl; j++) {	/*for each raster row */
-	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);	/*read raster row */
-
-	if (masked) {		/*read mask row if needed */
+	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
 		return RLI_ERRORE;
 	    }
 	}
 
-	for (i = 0; i < ad->cl; i++) {	/*for each cell in the row */
-	    area++;
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
-		area--;
+	for (i = 0; i < ad->cl; i++) {
+	    if (masked && mask_buf[i] == 0) {
 		G_set_d_null_value(&buf[i + ad->x], 1);
 	    }
-	    if (!(G_is_null_value(&buf[i + ad->x], DCELL_TYPE))) {
+	    if (!(G_is_d_null_value(&buf[i + ad->x]))) {
+		area++;
 		somma = somma + buf[i + ad->x];
 	    }
 	}
     }
 
-    if (area == 0)
-	indice = (double)-1;
+    if (area > 0)
+	*result = somma / area;
     else
-	indice = somma / area;
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
@@ -233,11 +223,10 @@
     FCELL *buf;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int masked = FALSE;
 
     double area = 0;
-    double indice = 0;
     double somma = 0;
 
     /* open mask if needed */
@@ -254,36 +243,32 @@
 	masked = TRUE;
     }
 
+    for (j = 0; j < ad->rl; j++) {
+	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
 
-    for (j = 0; j < ad->rl; j++) {	/*for each raster row */
-	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);	/*read raster row */
-
-	if (masked) {		/*read mask row if needed */
+	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
 		return RLI_ERRORE;
 	    }
 	}
 
-	for (i = 0; i < ad->cl; i++) {	/*for each cell in the row */
-	    area++;
-
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
-		area--;
+	for (i = 0; i < ad->cl; i++) {
+	    if (masked && mask_buf[i] == 0) {
 		G_set_f_null_value(&buf[i + ad->x], 1);
 	    }
-	    if (!(G_is_null_value(&buf[i + ad->x], FCELL_TYPE))) {
+	    if (!(G_is_f_null_value(&buf[i + ad->x]))) {
+		area++;
 		somma = somma + buf[i + ad->x];
 	    }
 	}
     }
 
-    if (area == 0)
-	indice = (double)-1;
+    if (area > 0)
+	*result = somma / area;
     else
-	indice = somma / area;
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.mps/mps.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.mps/mps.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.mps/mps.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -4,6 +4,8 @@
  * AUTHOR(S):    Serena Pallecchi (original contributor)
  *                student of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
+ *               Rewrite: Markus Metz
+ *               Patch identification: Michael Shapiro - CERL
  *
  * PURPOSE:      calculates mean patch size index
  * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
@@ -21,16 +23,22 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
 #include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
 
+/* template is patchnum */
 
-int calculate(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
-int calculateD(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
-int calculateF(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
+/* cell count and type of each patch */
+struct pst {
+    long count;
+    generic_cell type;
+};
 
+rli_func meanPatchSize;
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
 int main(int argc, char *argv[])
 {
     struct Option *raster, *conf, *output;
@@ -62,29 +70,23 @@
 
 int meanPatchSize(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
-    int ris = 0;
+    int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
-	    ris = calculate(fd, ad, hd, &indice);
+	    ris = calculate(fd, ad, &indice);
 	    break;
 	}
     case DCELL_TYPE:
 	{
-	    ris = calculateD(fd, ad, hd, &indice);
+	    ris = calculateD(fd, ad, &indice);
 	    break;
 	}
     case FCELL_TYPE:
 	{
-	    ris = calculateF(fd, ad, hd, &indice);
+	    ris = calculateF(fd, ad, &indice);
 	    break;
 	}
     default:
@@ -92,10 +94,11 @@
 	    G_fatal_error("data type unknown");
 	    return RLI_ERRORE;
 	}
-
     }
-    if (ris != RLI_OK)
+
+    if (ris != RLI_OK) {
 	return RLI_ERRORE;
+    }
 
     *result = indice;
 
@@ -103,40 +106,38 @@
 }
 
 
-int calculate(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
+int calculate(int fd, struct area_entry *ad, double *result)
 {
-    CELL *buf;
-    CELL *buf_sup;
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    CELL corrCell;
-    CELL precCell;
-    CELL supCell;
+    G_get_window(&hd);
 
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
+    buf_null = G_allocate_cell_buf();
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
 
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long uno = 1;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
 
-    double indice = 0;
-    double area = 0;		/*if all cells are null area=0 */
-    double areaCorrect = 0;
-    double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
-
-    avlID_tree albero = NULL;
-    avlID_table *array;
-
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -145,301 +146,156 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
 
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
 
-    buf_sup = G_allocate_cell_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-
-    buf = G_allocate_cell_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-
-    G_set_c_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-
-    /*for each raster row */
-
-    for (j = 0; j < ad->rl; j++) {
-	if (j > 0) {
-	    buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
-	G_set_c_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++) {	/*for each cell in the row */
 
-	    corrCell = buf[i + ad->x];
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
 
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
+	G_set_c_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
 	    }
 
-	    /*valid cell */
-	    if (!(G_is_null_value(&corrCell, CELL_TYPE))) {
-		area++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
+	    if (G_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
+	    }
 
-		if (j == 0)
-		    G_set_c_null_value(&supCell, 1);
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (!G_is_c_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
+	    if (!G_is_c_null_value(&supCell) && corrCell == supCell) {
 
-		if (corrCell != precCell) {
-		    if (corrCell != supCell) {
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {	/*not first patch */
-			    /* put in the tree previous values */
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, uno);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			    }
-			    else {	/* tree not null */
-
-				ris = avlID_add(&albero, idCorr, uno);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
-		    else {	/*current cell and upper cell are equal */
 
-			if ((corrCell == precCell) &&
-			    (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-			    r = avlID_sub(&albero, del);
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, uno);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (i < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-				else {
-				    r = ad->cl + 1;
-				}
-			    }
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
 			}
-
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, uno);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
 			}
-			else {	/* tree not null */
-
-			    ris = avlID_add(&albero, idCorr, uno);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previous cell are equal */
-
-
-		    if ((corrCell == supCell) &&
-			(mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			int l;
-
-			mask_patch_corr[i] = mask_patch_sup[i];
-			l = i - 1;
-			while (l >= 0) {
-			    if (mask_patch_corr[l] == idCorr) {
-				mask_patch_corr[l] = mask_patch_sup[i];
-				l--;
-			    }
-			    else {
-				l = (-1);
-			    }
-			}
-			lastId--;
-			idCorr = mask_patch_sup[i];
-		    }
 		    else {
-			mask_patch_corr[i] = idCorr;
+			pst[new_pid].count++;
 		    }
-
 		}
+		connected = 1;
 	    }
-	    else {		/*cell not to consider or cell is null */
 
-		mask_patch_corr[i] = 0;
-	    }
-	}
-	mask_patch_sup = mask_patch_corr;
-    }
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
 
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-    if (area != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, uno);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
-	    npatch++;
+	    precCell = corrCell;
 	}
-	else {
-	    ris = avlID_add(&albero, idCorr, uno);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
-	    }
-	}
+    }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
 
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0)
-		doppi++;
-	}
-	npatch = npatch - doppi;
-
-	/*calculate distance */
+	/* calculate distance */
 	G_begin_distance_calculations();
 	/* EW Dist at North edge */
 	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
@@ -450,60 +306,61 @@
 	/* NS Dist at West edge */
 	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-	areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
-	    (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
-	indice = areaCorrect / npatch;
-	G_free(array);
+	area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	    (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
+
+	*result = area_units / (npatch * 10000);
     }
-    else
-	indice = (double)(0);
+    else {
+	*result = 0;
+    }
 
-
-    *result = indice;
-
-
-    if (masked)
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    G_free(mask_patch_corr);
-
-    /* G_free(buf_sup); */   /* <-- why not free it? */
     return RLI_OK;
 }
 
 
-int calculateD(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
+int calculateD(int fd, struct area_entry *ad, double *result)
 {
-    DCELL *buf;
-    DCELL *buf_sup;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long uno = 1;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double area = 0;		/*if all cells are null area=0 */
-    double areaCorrect = 0;
-    double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    avlID_tree albero = NULL;
+    G_get_window(&hd);
 
-    avlID_table *array;
+    buf_null = G_allocate_d_raster_buf();
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
 
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
 
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -512,300 +369,156 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
 
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
 
-    buf_sup = G_allocate_d_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-
-    buf = G_allocate_d_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-
-    G_set_d_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-
-    /*read each row and put in an avlId tree cell value with the number of cells which have that value */
-    for (j = 0; j < ad->rl; j++) {
-	if (j > 0) {
-	    buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_d_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++) {	/*for each cell in the row */
 
-	    corrCell = buf[i + ad->x];
-
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
 	    }
 
-	    if (!(G_is_null_value(&corrCell, DCELL_TYPE))) {
-		area++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
+	    if (G_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
+	    }
 
-		if (j == 0)
-		    G_set_d_null_value(&supCell, 1);
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (!G_is_d_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-		if (corrCell != precCell) {
-		    if (corrCell != supCell) {
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {	/*not first patch */
-			    /* put in the tree previous value */
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, uno);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
+	    if (!G_is_d_null_value(&supCell) && corrCell == supCell) {
 
-			    }
-			    else {	/* tree not null */
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-				ris = avlID_add(&albero, idCorr, uno);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
-		    else {	/*current cell and upper cell are equal */
 
-			if ((corrCell == precCell) &&
-			    (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    r = avlID_sub(&albero, del);
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    ris = avlID_add(&albero, idCorr, uno);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (i < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-				else {
-				    r = ad->cl + 1;
-				}
-			    }
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
 			}
-
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, uno);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, uno);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previous cell are equals */
-
-
-		    if ((corrCell == supCell) &&
-			(mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			int l;
-
-			mask_patch_corr[i] = mask_patch_sup[i];
-			l = i - 1;
-			while (l >= 0) {
-			    if (mask_patch_corr[l] == idCorr) {
-				mask_patch_corr[l] = mask_patch_sup[i];
-				l--;
-			    }
-			    else {
-				l = (-1);
-			    }
-			}
-			lastId--;
-			idCorr = mask_patch_sup[i];
-		    }
 		    else {
-			mask_patch_corr[i] = idCorr;
+			pst[new_pid].count++;
 		    }
-
 		}
+		connected = 1;
 	    }
-	    else {		/*cell null or not to consider */
 
-		mask_patch_corr[i] = 0;
-	    }
-	}
-	mask_patch_sup = mask_patch_corr;
-    }
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
 
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-    if (area != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, uno);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
-	    npatch++;
+	    precCell = corrCell;
 	}
-	else {
-	    ris = avlID_add(&albero, idCorr, uno);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
-	    }
-	}
+    }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
 
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0)
-		doppi++;
-
-	}
-	npatch = npatch - doppi;
-
-	/*calculate distance */
+	/* calculate distance */
 	G_begin_distance_calculations();
 	/* EW Dist at North edge */
 	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
@@ -816,64 +529,61 @@
 	/* NS Dist at West edge */
 	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-	areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
-	    (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
-	indice = areaCorrect / npatch;
-	G_free(array);
+	area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	    (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
+
+	*result = area_units / (npatch * 10000);
     }
-    else
-	indice = (double)(0);
+    else {
+	*result = 0;
+    }
 
-
-    *result = indice;
-
-
-    if (masked)
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    G_free(mask_patch_corr);
-
     return RLI_OK;
 }
 
 
-int calculateF(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
+int calculateF(int fd, struct area_entry *ad, double *result)
 {
-    FCELL *buf;
-    FCELL *buf_sup;
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    FCELL corrCell;
-    FCELL precCell;
-    FCELL supCell;
+    G_get_window(&hd);
 
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
+    buf_null = G_allocate_f_raster_buf();
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
 
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long uno = 1;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
 
-    double indice = 0;
-    double area = 0;		/*if all cells are null area=0 */
-    double areaCorrect = 0;
-    double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
-
-    avlID_tree albero = NULL;
-
-    avlID_table *array;
-
-
-
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -882,297 +592,156 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
 
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
 
-    buf_sup = G_allocate_f_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-
-
-    buf = G_allocate_f_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-
-    G_set_f_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-    /*for each raster row */
-
-    for (j = 0; j < ad->rl; j++) {
-	if (j > 0) {
-	    buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_f_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++) {	/*for each cell in the row */
 
-
-	    corrCell = buf[i + ad->x];
-	    if (((masked) && (mask_buf[i + ad->x] == 0))) {
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
 	    }
-	    if (!(G_is_null_value(&corrCell, FCELL_TYPE))) {
-		area++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    G_set_f_null_value(&supCell, 1);
-		else
-		    supCell = buf_sup[i + ad->x];
 
+	    if (G_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
+	    }
 
-		if (corrCell != precCell) {
-		    if (corrCell != supCell) {
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {	/*not first patch */
-			    /* put in the tree previous value */
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, uno);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
+	    if (!G_is_f_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-			    }
-			    else {	/*tree not empty */
+	    if (!G_is_f_null_value(&supCell) && corrCell == supCell) {
 
-				ris = avlID_add(&albero, idCorr, uno);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
-		    else {	/*current cell and upper cell are equal */
 
-			if ((corrCell == precCell) &&
-			    (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-			    r = avlID_sub(&albero, del);
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, uno);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (i < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-				else {
-				    r = ad->cl + 1;
-				}
-			    }
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
 			}
-
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, uno);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
 			}
-			else {	/*the tree (albero) isn't null */
-
-			    ris = avlID_add(&albero, idCorr, uno);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previous cell are equal */
-
-		    if ((corrCell == supCell) &&
-			(mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			int l;
-
-			mask_patch_corr[i] = mask_patch_sup[i];
-			l = i - 1;
-			while (l >= 0) {
-			    if (mask_patch_corr[l] == idCorr) {
-				mask_patch_corr[l] = mask_patch_sup[i];
-				l--;
-			    }
-			    else {
-				l = (-1);
-			    }
-			}
-			lastId--;
-			idCorr = mask_patch_sup[i];
-		    }
 		    else {
-			mask_patch_corr[i] = idCorr;
+			pst[new_pid].count++;
 		    }
-
 		}
+		connected = 1;
 	    }
-	    else {		/*null cell or cell not to consider */
 
-		mask_patch_corr[i] = 0;
-	    }
-	}
-	mask_patch_sup = mask_patch_corr;
-    }
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
 
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-    if (area != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, uno);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
-	    npatch++;
+	    precCell = corrCell;
 	}
-	else {
-	    ris = avlID_add(&albero, idCorr, uno);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
-	    }
-	}
+    }
 
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
 
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0)
-		doppi++;
-
-	}
-	npatch = npatch - doppi;
-
-	/*calculate distance */
+	/* calculate distance */
 	G_begin_distance_calculations();
 	/* EW Dist at North edge */
 	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
@@ -1183,22 +752,24 @@
 	/* NS Dist at West edge */
 	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-	areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
-	    (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
-	indice = areaCorrect / npatch;
-	G_free(array);
+	area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	    (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
+
+	*result = area_units / (npatch * 10000);
     }
-    else
-	indice = (double)(0);
+    else {
+	*result = 0;
+    }
 
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
-
-    if (masked)
-	  G_free(mask_buf);
-/* TODO: fix if? */
-    G_free(mask_patch_corr);
-
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.padcv/padcv.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.padcv/padcv.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.padcv/padcv.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -5,6 +5,8 @@
  *                student of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
  *               Fixes: Markus Neteler <neteler itc.it>
+ *               Rewrite: Markus Metz
+ *               Patch identification: Michael Shapiro - CERL
  *
  * PURPOSE:      calculates coefficient of variation of patch areas
  * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
@@ -22,12 +24,18 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
-#include "../r.li.daemon/GenericCell.h"
 #include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
 
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+    long count;
+    generic_cell type;
+};
+
+rli_func patchAreaDistributionCV;
 int calculate(int fd, struct area_entry *ad, double *result);
 int calculateD(int fd, struct area_entry *ad, double *result);
 int calculateF(int fd, struct area_entry *ad, double *result);
@@ -61,14 +69,9 @@
 
 int patchAreaDistributionCV(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
     double indice = 0;
-    struct Cell_head hd;
     int ris = RLI_OK;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
@@ -105,39 +108,36 @@
 
 int calculate(int fd, struct area_entry *ad, double *result)
 {
-    CELL *buf;
-    CELL *buf_sup;
-    CELL corrCell;
-    CELL precCell;
-    CELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long np = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double somma = 0;
-    double area = 0;
-    double mn = 0;
-    double sd = 0;
-    double cv = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = CELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_cell_buf();
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -146,388 +146,241 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_cell_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_cell_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_c_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
 
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_c_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++)
-	    /* for each cell in the row */
-	{
-	    area++;
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    G_set_c_null_value(&supCell, 1);
 
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (G_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
+	    }
 
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first found patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+	    if (!G_is_c_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
+	    if (!G_is_c_null_value(&supCell) && corrCell == supCell) {
 
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
-			}
-		    }
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-		    else
-			/* current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
 
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {
-			    mask_patch_corr[i] = idCorr;
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
+		    else {
+			pst[new_pid].count++;
 		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
+	double area_p;
+	double cell_size_m;
+	double mps;
+	double psd;
+	double pcv;
+	double diff;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
 
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
+	/* calculate patch size standard deviation */
+	psd = 0;
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		diff = area_p - mps;
+		psd += diff * diff;
 	    }
 	}
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0) {
-		doppi++;
-	    }
-	}
-	np = npatch;
-	npatch = npatch - doppi;
-	mn = areaPatch / npatch;
-
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
-
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
-	    }
-	}
-	sd = sqrt(somma / npatch);
-	cv = sd * 100 / mn;
-	indice = cv;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	pcv = psd * 100 / mps;
+	*result = pcv;
     }
-
     else
-	indice = (double)(-1);
-    if (masked)
+	G_set_d_null_value(result, 1);
+
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
-    G_free(mask_patch_sup);
-    *result = indice;
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    /* G_free(buf_sup); */   /* <-- why not free it? */
     return RLI_OK;
 }
 
+
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
-    DCELL *buf;
-    DCELL *buf_sup;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long np = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double somma = 0;
-    double area = 0;
-    double mn = 0;
-    double sd = 0;
-    double cv = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = DCELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_d_raster_buf();
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -536,384 +389,241 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_d_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_d_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_d_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
 
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_d_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++) {
-	    /* for each dcell in the row */
-	    area++;
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    G_set_d_null_value(&supCell, 1);
 
-		else
-		    supCell = buf_sup[i + ad->x];
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
+	    if (G_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
+	    }
 
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+	    if (!G_is_d_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
+	    if (!G_is_d_null_value(&supCell) && corrCell == supCell) {
 
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
-			}
-		    }
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-		    else
-			/*current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
 
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {
-			    mask_patch_corr[i] = idCorr;
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
+		    else {
+			pst[new_pid].count++;
 		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
+	double area_p;
+	double cell_size_m;
+	double mps;
+	double psd;
+	double pcv;
+	double diff;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
-	    }
-	}
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0) {
-		doppi++;
-	    }
-	}
-	np = npatch;
-	npatch = npatch - doppi;
-	mn = areaPatch / npatch;
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
 
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
-
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
+	/* calculate patch size standard deviation */
+	psd = 0;
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		diff = area_p - mps;
+		psd += diff * diff;
 	    }
 	}
-	sd = sqrt(somma / npatch);
-	cv = sd * 100 / mn;
-	indice = cv;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	pcv = psd * 100 / mps;
+	*result = pcv;
     }
-
     else
-	indice = (double)(-1);
-    if (masked)
+	G_set_d_null_value(result, 1);
+
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
-    G_free(mask_patch_sup);
-    *result = indice;
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
     return RLI_OK;
 }
 
+
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
-    FCELL *buf;
-    FCELL *buf_sup;
-    FCELL corrCell;
-    FCELL precCell;
-    FCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    long npatch = 0;
-    long np = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double somma = 0;
-    double area = 0;
-    double mn = 0;
-    double sd = 0;
-    double cv = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = FCELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_f_raster_buf();
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -922,350 +632,204 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_f_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_f_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_f_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
 
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_f_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++) {
-	    /* for each fcell in the row */
-	    area++;
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    G_set_f_null_value(&supCell, 1);
 
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (G_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
+	    }
 
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell)
-			/*        3
-			 *      1 2
-			 * */
-		    {
+	    if (!G_is_f_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+	    if (!G_is_f_null_value(&supCell) && corrCell == supCell) {
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
 
-		    else
-			/*current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
-
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {
-			    mask_patch_corr[i] = idCorr;
-			}
+		    else {
+			pst[new_pid].count++;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
+	double area_p;
+	double cell_size_m;
+	double mps;
+	double psd;
+	double pcv;
+	double diff;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
 
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
+	/* calculate patch size standard deviation */
+	psd = 0;
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		diff = area_p - mps;
+		psd += diff * diff;
 	    }
 	}
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0) {
-		doppi++;
-	    }
-	}
-	np = npatch;
-	npatch = npatch - doppi;
-	mn = areaPatch / npatch;
-
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
-
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
-	    }
-	}
-	sd = sqrt(somma / npatch);
-	cv = sd * 100 / mn;
-	indice = cv;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	pcv = psd * 100 / mps;
+	*result = pcv;
     }
-
     else
-	indice = (double)(-1);
-    if (masked)
-	  G_free(mask_buf);
-/* TODO: fix if? */
-    G_free(mask_patch_sup);
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.padrange/padrange.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.padrange/padrange.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.padrange/padrange.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -5,6 +5,8 @@
  *                student of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
  *               Fixes: Markus Neteler <neteler itc.it>
+ *               Rewrite: Markus Metz
+ *               Patch identification: Michael Shapiro - CERL
  *
  * PURPOSE:      calculates calculates standard deviation of patch areas
  * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
@@ -22,12 +24,18 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
-#include "../r.li.daemon/GenericCell.h"
 #include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
 
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+    long count;
+    generic_cell type;
+};
+
+rli_func patchAreaDistributionRANGE;
 int calculate(int fd, struct area_entry *ad, double *result);
 int calculateD(int fd, struct area_entry *ad, double *result);
 int calculateF(int fd, struct area_entry *ad, double *result);
@@ -62,14 +70,9 @@
 int patchAreaDistributionRANGE(int fd, char **par, struct area_entry *ad,
 			       double *result)
 {
-    char *mapset;
     double indice = 0;
-    struct Cell_head hd;
     int ris = RLI_OK;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
@@ -105,38 +108,36 @@
 
 int calculate(int fd, struct area_entry *ad, double *result)
 {
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    CELL *buf;
-    CELL *buf_sup;
+    G_get_window(&hd);
 
-    CELL corrCell;
-    CELL precCell;
-    CELL supCell;
+    buf_null = G_allocate_cell_buf();
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    int area_max = 0, area_min = 0;
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
 
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
 
-    double indice = 0;
-    double rk = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
-    gc.t = CELL_TYPE;
-
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -145,397 +146,234 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
 
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
 
-    buf_sup = G_allocate_cell_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-
-    buf = G_allocate_cell_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-
-    G_set_c_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
 	}
 
-	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
-
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
 
 	G_set_c_null_value(&precCell, 1);
 
-	for (i = 0; i < ad->cl; i++)
-	    /* for each cell in the row */
-	{
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
 	    }
 
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
+	    if (G_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
+	    }
 
-		if (j == 0)
-		    G_set_c_null_value(&supCell, 1);
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (!G_is_c_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
+	    if (!G_is_c_null_value(&supCell) && corrCell == supCell) {
 
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0)
-			    /*first found patch */
-			{
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
-
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
 
-		    else
-			/* current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
-
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {
-			    mask_patch_corr[i] = idCorr;
-			}
+		    else {
+			pst[new_pid].count++;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_p;
+	double cell_size_m;
+	double min, max;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
-	    }
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
 
-
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-
-
-	for (i = 0; i < npatch; i++) {
-
-	    if (array[i]->tot != 0) {
-
-		if (array[i]->tot > area_max) {
-		    area_max = array[i]->tot;
-		}
-		if (array[i]->tot < area_min || area_min == 0) {
-		    area_min = array[i]->tot;
-		}
+	/* get min and max patch size */
+	min = 1.0 / 0.0;	/* inf */
+	max = -1.0 / 0.0;	/* -inf */
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		if (min > area_p)
+		    min = area_p;
+		if (max < area_p)
+		    max = area_p;
 	    }
 	}
-
-	rk = area_max - area_min;
-
-	indice = rk;
-
-	G_free(array);
+	*result = max - min;
     }
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-
-    if (masked)
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    G_free(mask_patch_sup);
-
-    *result = indice;
-
-    G_free(buf_sup);
     return RLI_OK;
 }
 
 
-
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
-    DCELL *buf;
-    DCELL *buf_sup;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    int area_max = 0, area_min = 0;
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double rk = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = DCELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_d_raster_buf();
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -544,381 +382,234 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_d_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_d_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_d_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
 
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_d_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++) {
-	    /* for each dcell in the row */
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
 	    }
 
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
+	    if (G_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
+	    }
 
-		if (j == 0)
-		    G_set_d_null_value(&supCell, 1);
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (!G_is_d_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
+	    if (!G_is_d_null_value(&supCell) && corrCell == supCell) {
 
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first found patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
-
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
 
-		    else
-			/* current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
-
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {
-			    mask_patch_corr[i] = idCorr;
-			}
+		    else {
+			pst[new_pid].count++;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_p;
+	double cell_size_m;
+	double min, max;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
-	    }
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
 
-
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-
-
-	for (i = 0; i < npatch; i++) {
-
-	    if (array[i]->tot != 0) {
-
-		if (array[i]->tot > area_max) {
-		    area_max = array[i]->tot;
-		}
-		if (array[i]->tot < area_min || area_min == 0) {
-		    area_min = array[i]->tot;
-		}
+	/* get min and max patch size */
+	min = 1.0 / 0.0;	/* inf */
+	max = -1.0 / 0.0;	/* -inf */
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		if (min > area_p)
+		    min = area_p;
+		if (max < area_p)
+		    max = area_p;
 	    }
 	}
-
-
-
-	rk = area_max - area_min;
-
-	indice = rk;
-
-	G_free(array);
+	*result = max - min;
     }
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-
-    if (masked)
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
-    G_free(mask_patch_sup);
-    *result = indice;
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
     return RLI_OK;
 }
 
 
-
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
-    FCELL *buf;
-    FCELL *buf_sup;
-    FCELL corrCell;
-    FCELL precCell;
-    FCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    int area_max = 0, area_min = 0;
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double rk = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = FCELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_f_raster_buf();
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -927,349 +618,197 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
-    }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_f_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_f_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_f_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
 
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
+    }
+
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_f_null_value(&precCell, 1);
 
-	for (i = 0; i < ad->cl; i++) {
-	    /* for each fcell in the row */
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
 	    }
 
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
+	    if (G_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
+	    }
 
-		if (j == 0)
-		    G_set_f_null_value(&supCell, 1);
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (!G_is_f_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
+	    if (!G_is_f_null_value(&supCell) && corrCell == supCell) {
 
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first found patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
-
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-				    {
-					break;
-				    }
-				default:
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
 
-		    else
-			/* current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
-
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {
-			    mask_patch_corr[i] = idCorr;
-			}
+		    else {
+			pst[new_pid].count++;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_p;
+	double cell_size_m;
+	double min, max;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-		{
-		    break;
-		}
-	    default:
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
-	    }
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
 
-
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-
-
-	for (i = 0; i < npatch; i++) {
-
-	    if (array[i]->tot != 0) {
-
-		if (array[i]->tot > area_max) {
-		    area_max = array[i]->tot;
-		}
-		if (array[i]->tot < area_min || area_min == 0) {
-		    area_min = array[i]->tot;
-		}
+	/* get min and max patch size */
+	min = 1.0 / 0.0;	/* inf */
+	max = -1.0 / 0.0;	/* -inf */
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		if (min > area_p)
+		    min = area_p;
+		if (max < area_p)
+		    max = area_p;
 	    }
 	}
-
-
-
-	rk = area_max - area_min;
-
-	indice = rk;
-
-	G_free(array);
+	*result = max - min;
     }
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-
-    if (masked)
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
-    G_free(mask_patch_sup);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.padsd/padsd.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.padsd/padsd.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.padsd/padsd.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -5,6 +5,8 @@
  *                student of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
  *               Fixes: Markus Neteler <neteler itc.it>
+ *               Rewrite: Markus Metz
+ *               Patch identification: Michael Shapiro - CERL
  *
  * PURPOSE:      calculates calculates standard deviation of patch areas
  * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
@@ -22,11 +24,18 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include "../r.li.daemon/defs.h"
-#include "../r.li.daemon/avlDefs.h"
-#include "../r.li.daemon/avlID.h"
-#include "../r.li.daemon/GenericCell.h"
 #include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
+
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+    long count;
+    generic_cell type;
+};
+
+rli_func patchAreaDistributionSD;
 int calculate(int fd, struct area_entry *ad, double *result);
 int calculateD(int fd, struct area_entry *ad, double *result);
 int calculateF(int fd, struct area_entry *ad, double *result);
@@ -60,14 +69,9 @@
 
 int patchAreaDistributionSD(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
     double indice = 0;
-    struct Cell_head hd;
     int ris = RLI_OK;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
@@ -103,38 +107,36 @@
 
 int calculate(int fd, struct area_entry *ad, double *result)
 {
-    CELL *buf;
-    CELL *buf_sup;
-    CELL corrCell;
-    CELL precCell;
-    CELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    long npatch = 0;
-    long np = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double somma = 0;
-    double area = 0;
-    double mn = 0;
-    double sd = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = CELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_cell_buf();
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -143,397 +145,239 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_cell_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_cell_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_c_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
 
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_c_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++)
-	    /* for each cell in the row */
-	{
-	    area++;
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    G_set_c_null_value(&supCell, 1);
 
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (G_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
+	    }
 
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0)
-			    /*first found patch */
+	    if (!G_is_c_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-			{
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+	    if (!G_is_c_null_value(&supCell) && corrCell == supCell) {
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
-
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
-
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-
-				    {
-					break;
-				    }
-				default:
-
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
 
-		    else
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
-
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {
-			    mask_patch_corr[i] = idCorr;
-			}
+		    else {
+			pst[new_pid].count++;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
+	double area_p;
+	double cell_size_m;
+	double mps;
+	double psd;
+	double diff;
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
 
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-
-		{
-		    break;
-		}
-	    default:
-
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
+	/* calculate patch size standard deviation */
+	psd = 0;
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		diff = area_p - mps;
+		psd += diff * diff;
 	    }
 	}
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0) {
-		doppi++;
-	    }
-	}
-	np = npatch;
-	npatch = npatch - doppi;
-	mn = areaPatch / npatch;
-
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
-
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
-	    }
-	}
-	sd = sqrt(somma / npatch);
-	indice = sd;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
-
     else
-	indice = (double)(-1);
-    if (masked)
+	G_set_d_null_value(result, 1);
+
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
-    G_free(mask_patch_sup);
-    *result = indice;
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    G_free(buf_sup);
-    G_free(buf);
     return RLI_OK;
 }
 
 
-
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
-    DCELL *buf;
-    DCELL *buf_sup;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    long npatch = 0;
-    long np = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    double indice = 0;
-    double somma = 0;
-    double area = 0;
-    double mn = 0;
-    double sd = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = DCELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_d_raster_buf();
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -542,390 +386,239 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_d_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_d_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_d_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
 
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_d_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++)
-	    /* for each dcell in the row */
-	{
-	    area++;
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    G_set_d_null_value(&supCell, 1);
 
-		else
-		    supCell = buf_sup[i + ad->x];
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+	    if (G_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
+	    }
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
+	    if (!G_is_d_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
+	    if (!G_is_d_null_value(&supCell) && corrCell == supCell) {
 
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-
-				    {
-					break;
-				    }
-				default:
-
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
 
-		    else
-			/*current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
-
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {
-			    mask_patch_corr[i] = idCorr;
-			}
+		    else {
+			pst[new_pid].count++;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
+	double area_p;
+	double cell_size_m;
+	double mps;
+	double psd;
+	double diff;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
 
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-
-		{
-		    break;
-		}
-	    default:
-
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
+	/* calculate patch size standard deviation */
+	psd = 0;
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		diff = area_p - mps;
+		psd += diff * diff;
 	    }
 	}
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0) {
-		doppi++;
-	    }
-	}
-	np = npatch;
-	npatch = npatch - doppi;
-	mn = areaPatch / npatch;
-
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
-
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
-	    }
-	}
-	sd = sqrt(somma / npatch);
-	indice = sd;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
-
     else
-	indice = (double)(-1);
-    if (masked)
+	G_set_d_null_value(result, 1);
+
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
-    G_free(mask_patch_sup);
-    *result = indice;
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
     return RLI_OK;
 }
 
+
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
-    FCELL *buf;
-    FCELL *buf_sup;
-    FCELL corrCell;
-    FCELL precCell;
-    FCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf;
-    int ris = 0;
-    int masked = FALSE;
-    int areaPatch = 0;		/*if all cells are null areaPatch=0 */
-    long npatch = 0;
-    long tot = 0;
-    long zero = 0;
-    long totCorr = 0;
-    long idCorr = 0;
-    long lastId = 0;
-    long doppi = 0;
-    long *mask_patch_sup;
-    long *mask_patch_corr;
-    long np = 0;
-    double indice = 0;
-    double somma = 0;
-    double area = 0;
-    double mn = 0;
-    double sd = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
 
-    gc.t = FCELL_TYPE;
+    G_get_window(&hd);
 
+    buf_null = G_allocate_f_raster_buf();
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(G_window_cols() * sizeof(long));
+    pid_sup = G_malloc(G_window_cols() * sizeof(long));
+
+    for (j = 0; j < G_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
@@ -934,351 +627,202 @@
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
 	masked = TRUE;
     }
-    mask_patch_sup = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_sup == NULL) {
-	G_fatal_error("malloc mask_patch_sup failed");
-	return RLI_ERRORE;
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
     }
-    mask_patch_corr = G_malloc(ad->cl * sizeof(long));
-    if (mask_patch_corr == NULL) {
-	G_fatal_error("malloc mask_patch_corr failed");
-	return RLI_ERRORE;
-    }
-    buf_sup = G_allocate_f_raster_buf();
-    if (buf_sup == NULL) {
-	G_fatal_error("malloc buf_sup failed");
-	return RLI_ERRORE;
-    }
-    buf = G_allocate_f_raster_buf();
-    if (buf == NULL) {
-	G_fatal_error("malloc buf failed");
-	return RLI_ERRORE;
-    }
-    G_set_f_null_value(buf_sup + ad->x, ad->cl);	/*the first time buf_sup is all null */
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 0;
-    }
-    for (j = 0; j < ad->rl; j++)
-	/*for each raster row */
 
-    {
-	if (j > 0) {
-	    buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
 	if (masked) {
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
-		G_fatal_error("mask read failed");
-		return RLI_ERRORE;
-	    }
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	G_set_f_null_value(&precCell, 1);
-	for (i = 0; i < ad->cl; i++) {
-	    /* for each fcell in the row */
-	    area++;
-	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(G_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    G_set_f_null_value(&supCell, 1);
 
-		else
-		    supCell = buf_sup[i + ad->x];
-		if (corrCell != precCell)
-		    /*        ?
-		     *      1 2
-		     * */
-		{
-		    if (corrCell != supCell) {
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
-			}
+	    if (G_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
+	    }
 
-			else
-			    /*not first patch */
-			    /* put in the tree the previous value */
-			{
-			    if (albero == NULL) {
-				albero = avlID_make(idCorr, totCorr);
-				if (albero == NULL) {
-				    G_fatal_error("avlID_make error");
-				    return RLI_ERRORE;
-				}
-				npatch++;
-			    }
+	    if (!G_is_f_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
+		connected = 1;
+		pst[pid_corr[j + ad->x]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
 
-			    else
-				/*tree not empty */
-			    {
-				ris = avlID_add(&albero, idCorr, totCorr);
-				switch (ris) {
-				case AVL_ERR:
+	    if (!G_is_f_null_value(&supCell) && corrCell == supCell) {
 
-				    {
-					G_fatal_error("avlID_add error");
-					return RLI_ERRORE;
-				    }
-				case AVL_ADD:
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-				    {
-					npatch++;
-					break;
-				    }
-				case AVL_PRES:
-
-				    {
-					break;
-				    }
-				default:
-
-				    {
-					G_fatal_error
-					    ("avlID_add unknown error");
-					return RLI_ERRORE;
-				    }
-				}
-			    }
-			    totCorr = 1;
-			    lastId++;
-			    idCorr = lastId;
-			    mask_patch_corr[i] = idCorr;
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
 			}
 		    }
 
-		    else
-			/*current cell and upper cell are equal */
-			/*        2
-			 *      1 2
-			 * */
-		    {
-			if (albero == NULL) {
-			    albero = avlID_make(idCorr, totCorr);
-			    if (albero == NULL) {
-				G_fatal_error("avlID_make error");
-				return RLI_ERRORE;
-			    }
-			    npatch++;
+		    old_pid = pid_corr[j + ad->x];
+		    new_pid = pid_sup[j + ad->x];
+		    pid_corr[j + ad->x] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k + ad->x] == old_pid)
+				pid_corr[k + ad->x] = new_pid;
 			}
-			else {	/*tree not null */
-
-			    ris = avlID_add(&albero, idCorr, totCorr);
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k + ad->x] == old_pid)
+				pid_sup[k + ad->x] = new_pid;
 			}
-
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
-
-		    if (corrCell == supCell) {	/*current cell and upper cell are equal */
-			/*        1
-			 *      1 1
-			 */
-			if (mask_patch_sup[i] != mask_patch_corr[i - 1]) {
-			    long r = 0;
-			    long del = mask_patch_sup[i];
-
-
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
-
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
-
-			    /*Remove one patch because it makes part of a patch already found */
-			    ris = avlID_add(&albero, idCorr, r);
-
-			    switch (ris) {
-			    case AVL_ERR:
-				{
-				    G_fatal_error("avlID_add error");
-				    return RLI_ERRORE;
-				}
-			    case AVL_ADD:
-				{
-				    npatch++;
-				    break;
-				}
-			    case AVL_PRES:
-				{
-				    break;
-				}
-			    default:
-				{
-				    G_fatal_error("avlID_add unknown error");
-				    return RLI_ERRORE;
-				}
-			    }
-			    r = i;
-			    while (r < ad->cl) {
-				if (mask_patch_sup[r] == del) {
-				    mask_patch_sup[r] = idCorr;
-				}
-
-				r++;
-			    }
-
-			    mask_patch_corr[i] = idCorr;
-			}
-			else {
-			    mask_patch_corr[i] = idCorr;
-			}
+		    else {
+			pst[new_pid].count++;
 		    }
-		    else {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
 		}
+		connected = 1;
 	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-	    }
-	}
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-	{
-	    int ii;
-	    long c;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
 
-	    for (ii = 0; ii < ad->cl; ii++) {
-		c = mask_patch_corr[ii];
-		mask_patch_sup[ii] = c;
-		mask_patch_corr[ii] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
-
-
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
+	double area_p;
+	double cell_size_m;
+	double mps;
+	double psd;
+	double diff;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	else {
-	    ris = avlID_add(&albero, idCorr, totCorr);
-	    switch (ris) {
-	    case AVL_ERR:
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
 
-		{
-		    G_fatal_error("avlID_add error");
-		    return RLI_ERRORE;
-		}
-	    case AVL_ADD:
-
-		{
-		    npatch++;
-		    break;
-		}
-	    case AVL_PRES:
-
-		{
-		    break;
-		}
-	    default:
-
-		{
-		    G_fatal_error("avlID_add unknown error");
-		    return RLI_ERRORE;
-		}
+	/* calculate patch size standard deviation */
+	psd = 0;
+	for (old_pid = 1; old_pid <= pid; old_pid++) {
+	    if (pst[old_pid].count > 0) {
+		area_p = cell_size_m * pst[old_pid].count / 10000;
+		diff = area_p - mps;
+		psd += diff * diff;
 	    }
 	}
-	array = G_malloc(npatch * sizeof(avlID_tableRow));
-	if (array == NULL) {
-	    G_fatal_error("malloc array failed");
-	    return RLI_ERRORE;
-	}
-	tot = avlID_to_array(albero, zero, array);
-	if (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot == 0) {
-		doppi++;
-	    }
-	}
-	np = npatch;
-	npatch = npatch - doppi;
-	mn = areaPatch / npatch;
-
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
-
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
-	    }
-	}
-	sd = sqrt(somma / npatch);
-	indice = sd;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
-
     else
-	indice = (double)(-1);
-    if (masked)
+	G_set_d_null_value(result, 1);
+
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
-    G_free(mask_patch_sup);
-    *result = indice;
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.patchdensity/main.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.patchdensity/main.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.patchdensity/main.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -6,6 +6,9 @@
  *                students of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
  *               Fixes: Serena Pallecchi, Markus Neteler <neteler itc.it>
+ *               Rewrite: Markus Metz
+ *               Patch identification: Michael Shapiro - CERL
+ *
  * PURPOSE:      calculates patch density index
  * COPYRIGHT:    (C) 2006-2014 by the GRASS Development Team
  *
@@ -20,7 +23,21 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 #include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
 
+/* template is patchnum */
+
+/* cell count and type of each patch */
+struct pst {
+    long count;
+    generic_cell type;
+};
+
+rli_func patch_density;
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
 int main(int argc, char *argv[])
 {
     struct Option *raster, *conf, *output;
@@ -53,152 +70,712 @@
 
 int patch_density(int fd, char **par, struct area_entry *ad, double *result)
 {
-    CELL *buf, *sup;
-    int count = 0, i, j, connected = 0, complete_line = 1, other_above = 0;
-    double area;
-    char *mapset;
+    int ris = RLI_OK;
+    double indice = 0;
+
+    switch (ad->data_type) {
+    case CELL_TYPE:
+	{
+	    ris = calculate(fd, ad, &indice);
+	    break;
+	}
+    case DCELL_TYPE:
+	{
+	    ris = calculateD(fd, ad, &indice);
+	    break;
+	}
+    case FCELL_TYPE:
+	{
+	    ris = calculateF(fd, ad, &indice);
+	    break;
+	}
+    default:
+	{
+	    G_fatal_error("data type unknown");
+	    return RLI_ERRORE;
+	}
+    }
+
+    if (ris != RLI_OK) {
+	return RLI_ERRORE;
+    }
+
+    *result = indice;
+
+    return RLI_OK;
+}
+
+
+int calculate(int fd, struct area_entry *ad, double *result)
+{
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
     struct Cell_head hd;
-    CELL complete_value;
-    double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
-    int mask_fd = -1, *mask_buf, *mask_sup, null_count = 0;
 
-    G_debug(1, "begin patch_density() index");
+    G_get_window(&hd);
 
-    G_set_c_null_value(&complete_value, 1);
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return 0;
+    buf_null = G_allocate_cell_buf();
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
 
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
-	    return 0;
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
 
-	mask_buf = malloc(ad->cl * sizeof(int));
-	mask_sup = malloc(ad->cl * sizeof(int));
+	masked = TRUE;
     }
 
-    sup = G_allocate_cell_buf();
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /* calculate distance */
-    G_begin_distance_calculations();
-    /* EW Dist at North edge */
-    EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
-    /* EW Dist at South Edge */
-    EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
-    /* NS Dist at East edge */
-    NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
-    /* NS Dist at West edge */
-    NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
+    }
 
-
-    /* calculate number of patch */
-
     for (i = 0; i < ad->rl; i++) {
 	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
-
 	if (i > 0) {
-	    sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
 	}
 
-	/* mask values */
-	if (ad->mask == 1) {
-	    int k;
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
 
-	    if (i > 0) {
-		int *tmp;
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
 
-		tmp = mask_sup;
-		mask_buf = mask_sup;
+	G_set_c_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_c_null_value(&corrCell, 1);
 	    }
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
-		return 0;
-	    for (k = 0; k < ad->cl; k++) {
-		if (mask_buf[k] == 0) {
-		    G_set_c_null_value(mask_buf + k, 1);
-		    null_count++;
+	    else {
+		/* total landscape area */
+		area++;
+	    }
+
+	    if (G_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
+	    }
+
+	    if (!G_is_c_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_c_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
+
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
+		    }
+		    else {
+			pst[new_pid].count++;
+		    }
 		}
+		connected = 1;
 	    }
 
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
+	    }
+	    precCell = corrCell;
 	}
+    }
 
+    if (area > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
 
-	if (complete_line) {
-	    if (!G_is_null_value(&(buf[ad->x]), CELL_TYPE) &&
-		buf[ad->x] != complete_value)
-		count++;
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
 
-	    for (j = 0; j < ad->cl - 1; j++) {
+	area_units = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols)) *
+	             ((NS_DIST1 + NS_DIST2) / (2 * hd.rows)) * area;
 
-		if (buf[j + ad->x] != buf[j + 1 + ad->x]) {
-		    complete_line = 0;
-		    if (!G_is_null_value(&(buf[j + 1 + ad->x]), CELL_TYPE) &&
-			buf[j + 1 + ad->x] != complete_value)
-			count++;
-		}
+	*result = (npatch / area_units) * 1000000;
+    }
+    else {
+	G_set_d_null_value(result, 1);
+    }
 
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
+    return RLI_OK;
+}
+
+
+int calculateD(int fd, struct area_entry *ad, double *result)
+{
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
+
+    G_get_window(&hd);
+
+    buf_null = G_allocate_d_raster_buf();
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
+    /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
+    if (ad->mask == 1) {
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
+	masked = TRUE;
+    }
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
+    }
+
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
+	}
+
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_d_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_d_null_value(&corrCell, 1);
 	    }
-	    if (complete_line) {
-		complete_value = buf[ad->x];
+	    else {
+		/* total landscape area */
+		area++;
 	    }
-	}
-	else {
-	    complete_line = 1;
-	    connected = 0;
-	    other_above = 0;
-	    for (j = 0; j < ad->cl; j++) {
-		if (sup[j + ad->x] == buf[j + ad->x]) {
-		    connected = 1;
-		    if (other_above) {
-			other_above = 0;
-			count--;
+
+	    if (G_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
+	    }
+
+	    if (!G_is_d_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_d_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
 		    }
-		}
-		else {
-		    if (connected &&
-			!G_is_null_value(&(buf[j + ad->x]), CELL_TYPE))
-			other_above = 1;
-		}
-		if (j < ad->cl - 1 && buf[j + ad->x] != buf[j + 1 + ad->x]) {
-		    complete_line = 0;
-		    if (!connected &&
-			!G_is_null_value(&(buf[j + ad->x]), CELL_TYPE)) {
 
-			count++;
-			connected = 0;
-			other_above = 0;
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
 		    else {
-			connected = 0;
-			other_above = 0;
+			pst[new_pid].count++;
 		    }
 		}
+		connected = 1;
 	    }
-	    if (!connected &&
-		sup[ad->cl - 1 + ad->x] != buf[ad->cl - 1 + ad->x]) {
-		if (!G_is_null_value(&(buf[ad->cl - 1 + ad->x]), CELL_TYPE)) {
-		    count++;
-		    complete_line = 0;
+
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
 		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
+	}
+    }
 
-	    if (complete_line)
-		complete_value = buf[ad->x];
+    if (area > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
 
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
+
+	area_units = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols)) *
+	             ((NS_DIST1 + NS_DIST2) / (2 * hd.rows)) * area;
+
+	*result = (npatch / area_units) * 1000000;
+    }
+    else {
+	G_set_d_null_value(result, 1);
+    }
+
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
+    return RLI_OK;
+}
+
+
+int calculateF(int fd, struct area_entry *ad, double *result)
+{
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
+
+    G_get_window(&hd);
+
+    buf_null = G_allocate_f_raster_buf();
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
+    /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
+    if (ad->mask == 1) {
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
 
+	masked = TRUE;
     }
 
-    area = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
-	(((NS_DIST1 + NS_DIST2) / 2) / hd.rows) *
-	(ad->rl *ad->cl - null_count);
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    if (area != 0)
-	*result = (count / area) * 1000000;
-    else
-	*result = -1;
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
+    }
 
-    G_free(sup);
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
+	}
 
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_f_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_f_null_value(&corrCell, 1);
+	    }
+	    else {
+		/* total landscape area */
+		area++;
+	    }
+
+	    if (G_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
+	    }
+
+	    if (!G_is_f_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_f_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
+
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
+		    }
+		    else {
+			pst[new_pid].count++;
+		    }
+		}
+		connected = 1;
+	    }
+
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
+	    }
+	    precCell = corrCell;
+	}
+    }
+
+    if (area > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
+
+	/* calculate distance */
+	G_begin_distance_calculations();
+	/* EW Dist at North edge */
+	EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
+	/* EW Dist at South Edge */
+	EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
+	/* NS Dist at East edge */
+	NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
+	/* NS Dist at West edge */
+	NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
+
+	area_units = ((EW_DIST1 + EW_DIST2) / (2 * hd.cols)) *
+	             ((NS_DIST1 + NS_DIST2) / (2 * hd.rows)) * area;
+
+	*result = (npatch / area_units) * 1000000;
+    }
+    else {
+	G_set_d_null_value(result, 1);
+    }
+
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.patchnum/main.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.patchnum/main.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.patchnum/main.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,4 +1,3 @@
-
 /****************************************************************************
  *
  * MODULE:       r.li.patchnum
@@ -6,6 +5,8 @@
  *                students of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
  *               Fixes: Markus Neteler <neteler itc.it>
+ *               Rewrite: Markus Metz
+ *               Patch identification: Michael Shapiro - CERL
  *
  * PURPOSE:      calculates patch number index
  * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
@@ -21,8 +22,21 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 #include "../r.li.daemon/daemon.h"
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/GenericCell.h"
 
+/* template for patch density, mps, padcv, padrange, padsd */
+
+/* cell count and type of each patch */
+struct pst {
+    long count;
+    generic_cell type;
+};
+
+rli_func patch_number;
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
 int main(int argc, char *argv[])
 {
     struct Option *raster, *conf, *output;
@@ -52,126 +66,643 @@
 			  output->answer);
 }
 
+
 int patch_number(int fd, char **par, struct area_entry *ad, double *result)
 {
-    CELL *buf, *sup;
-    int count = 0, i, j, connected = 0, complete_line = 1, other_above = 0;
-    char *mapset;
+    int ris = RLI_OK;
+    double indice = 0;
+
+    switch (ad->data_type) {
+    case CELL_TYPE:
+	{
+	    ris = calculate(fd, ad, &indice);
+	    break;
+	}
+    case DCELL_TYPE:
+	{
+	    ris = calculateD(fd, ad, &indice);
+	    break;
+	}
+    case FCELL_TYPE:
+	{
+	    ris = calculateF(fd, ad, &indice);
+	    break;
+	}
+    default:
+	{
+	    G_fatal_error("data type unknown");
+	    return RLI_ERRORE;
+	}
+    }
+
+    if (ris != RLI_OK) {
+	return RLI_ERRORE;
+    }
+
+    *result = indice;
+
+    return RLI_OK;
+}
+
+
+int calculate(int fd, struct area_entry *ad, double *result)
+{
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
     struct Cell_head hd;
-    CELL complete_value;
-    int mask_fd = -1, *mask_buf, *mask_sup, null_count = 0;
 
-    G_set_c_null_value(&complete_value, 1);
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return 0;
-    sup = G_allocate_cell_buf();
+    G_get_window(&hd);
 
+    buf_null = G_allocate_cell_buf();
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
-	    return 0;
-	mask_buf = malloc(ad->cl * sizeof(int));
-	mask_sup = malloc(ad->cl * sizeof(int));
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
+	masked = TRUE;
     }
 
-    /*calculate number of patch */
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
+    }
+
     for (i = 0; i < ad->rl; i++) {
 	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
 	if (i > 0) {
-	    sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
 	}
-	/* mask values */
-	if (ad->mask == 1) {
-	    int k;
 
-	    if (i > 0) {
-		int *tmp;
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
 
-		tmp = mask_sup;
-		mask_buf = mask_sup;
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_c_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_c_null_value(&corrCell, 1);
 	    }
-	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
-		return 0;
-	    for (k = 0; k < ad->cl; k++) {
-		if (mask_buf[k] == 0) {
-		    G_set_c_null_value(mask_buf + k, 1);
-		    null_count++;
+
+	    if (G_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
+	    }
+
+	    if (!G_is_c_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_c_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
+
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
+		    }
+		    else {
+			pst[new_pid].count++;
+		    }
 		}
+		connected = 1;
 	    }
 
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
+	    }
+	    precCell = corrCell;
 	}
+    }
 
+    *result = npatch;
 
-	if (complete_line) {
-	    if (!G_is_null_value(&(buf[ad->x]), CELL_TYPE) &&
-		buf[ad->x] != complete_value)
-		count++;
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-	    for (j = 0; j < ad->cl - 1; j++) {
+    return RLI_OK;
+}
 
-		if (buf[j + ad->x] != buf[j + 1 + ad->x]) {
-		    complete_line = 0;
-		    if (!G_is_null_value(&(buf[j + 1 + ad->x]), CELL_TYPE) &&
-			buf[j + 1 + ad->x] != complete_value)
-			count++;
-		}
 
+int calculateD(int fd, struct area_entry *ad, double *result)
+{
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
+
+    G_get_window(&hd);
+
+    buf_null = G_allocate_d_raster_buf();
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
+    /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
+    if (ad->mask == 1) {
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
+	masked = TRUE;
+    }
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
+    }
+
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
+	}
+
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
+
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_d_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_d_null_value(&corrCell, 1);
 	    }
-	    if (complete_line) {
-		complete_value = buf[ad->x];
+
+	    if (G_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
 	    }
-	}
-	else {
-	    complete_line = 1;
-	    connected = 0;
-	    other_above = 0;
-	    for (j = 0; j < ad->cl; j++) {
-		if (sup[j + ad->x] == buf[j + ad->x]) {
-		    connected = 1;
-		    if (other_above) {
-			other_above = 0;
-			count--;
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
+	    }
+
+	    if (!G_is_d_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_d_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
 		    }
-		}
-		else {
-		    if (connected &&
-			!G_is_null_value(&(buf[j + ad->x]), CELL_TYPE))
-			other_above = 1;
-		}
-		if (j < ad->cl - 1 && buf[j + ad->x] != buf[j + 1 + ad->x]) {
-		    complete_line = 0;
-		    if (!connected &&
-			!G_is_null_value(&(buf[j + ad->x]), CELL_TYPE)) {
 
-			count++;
-			connected = 0;
-			other_above = 0;
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
 		    }
 		    else {
-			connected = 0;
-			other_above = 0;
+			pst[new_pid].count++;
 		    }
 		}
+		connected = 1;
 	    }
-	    if (!connected &&
-		sup[ad->cl - 1 + ad->x] != buf[ad->cl - 1 + ad->x]) {
-		if (!G_is_null_value(&(buf[ad->cl - 1 + ad->x]), CELL_TYPE)) {
-		    count++;
-		    complete_line = 0;
+
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
 		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
+	}
+    }
 
-	    if (complete_line)
-		complete_value = buf[ad->x];
+    *result = npatch;
 
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
+    return RLI_OK;
+}
+
+
+int calculateF(int fd, struct area_entry *ad, double *result)
+{
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+    struct Cell_head hd;
+
+    G_get_window(&hd);
+
+    buf_null = G_allocate_f_raster_buf();
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
+    /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
+    if (ad->mask == 1) {
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
 	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
 
+	masked = TRUE;
     }
 
-    *result = count;
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    G_free(sup);
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].count = 0;
+    }
+
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
+	}
+
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_f_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_f_null_value(&corrCell, 1);
+	    }
+
+	    if (G_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
+	    }
+
+	    if (!G_is_f_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].count++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_f_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
+
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].count += pst[old_pid].count;
+			pst[old_pid].count = 0;
+			
+			if (old_pid == pid)
+			    pid--;
+		    }
+		    else {
+			pst[new_pid].count++;
+		    }
+		}
+		connected = 1;
+	    }
+
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
+		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
+	    }
+	    precCell = corrCell;
+	}
+    }
+
+    *result = npatch;
+
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.pielou/pielou.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.pielou/pielou.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.pielou/pielou.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -7,6 +7,7 @@
  *
  * AUTHOR(S):	Luca Delucchi, Fondazione Edmund Mach         
  *		Serena Pallecchi student of Computer Science University of Pisa (Italy)
+ *              Rewrite: Markus Metz
  *            	
  * COPYRIGHT:
  *		This program is free software under the GPL (>=v2)
@@ -21,36 +22,20 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/daemon.h"
 #include "../r.li.daemon/avlDefs.h"
 #include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
 
 /* template is shannon */
 
+rli_func pielou;
 int calculate(int fd, struct area_entry *ad, double *result);
-
 int calculateD(int fd, struct area_entry *ad, double *result);
-
 int calculateF(int fd, struct area_entry *ad, double *result);
 
-/*This function is used to sort the values in the moving window */
-static int cmp(const void *pa, const void *pb)
-{
-    int *p1 = (int *)pa;
-    int *p2 = (int *)pb;
-
-    if (*p1 < *p2)
-	return -1;
-    if (*p1 > *p2)
-	return 1;
-    return 0;
-}
-
 int main(int argc, char *argv[])
 {
     struct Option *raster, *conf, *output;
-
     struct GModule *module;
 
     G_gisinit(argv[0]);
@@ -78,32 +63,26 @@
 			  output->answer);
 }
 
+
 int pielou(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
-
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
-	    calculate(fd, ad, &indice);
+	    ris = calculate(fd, ad, &indice);
 	    break;
 	}
     case DCELL_TYPE:
 	{
-	    calculateD(fd, ad, &indice);
+	    ris = calculateD(fd, ad, &indice);
 	    break;
 	}
     case FCELL_TYPE:
 	{
-	    calculateF(fd, ad, &indice);
+	    ris = calculateF(fd, ad, &indice);
 	    break;
 	}
     default:
@@ -130,34 +109,22 @@
     CELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
+
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long totCorr = 1;
 
-    /* add to compute the number of class */
-    long *array_copy;
-    int totNumClass = 1;
-    double logTotNumClass;
+    long area = 0;
 
-    generic_cell cc;
-
-    generic_cell cc_passage;	/*add to compute the number of class */
-
     avl_tree albero = NULL;
     AVL_table *array;
+    generic_cell uc;
 
-    cc.t = CELL_TYPE;
+    uc.t = CELL_TYPE;
 
     /* open mask if needed */
     if (ad->mask == 1) {
@@ -172,11 +139,7 @@
     }
 
     G_set_c_null_value(&precCell, 1);
-
-    /*for each row */
-    for (j = 0; j < ad->rl; j++) {
-	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
-
+    for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
@@ -184,77 +147,74 @@
 	    }
 	}
 
+	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
 
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, cc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, cc.t)) {
-		    precCell = corrCell;
-		}
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
 
-		if (corrCell != precCell) {
-		    if (albero == NULL) {
-			cc.val.c = precCell;
-			albero = avl_make(cc, totCorr);
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
 
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
+		    if (albero == NULL) {
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			else
+		    case AVL_ADD:
+			{
 			    m++;
-		    }
-		    else {
-			cc.val.c = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-		precCell = corrCell;
-	    }
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
 
-	}			/* end for */
-    }				/* end for */
-
-
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.c = precCell;
-	    albero = avl_make(cc, totCorr);
-
+	    uc.val.c = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -262,8 +222,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.c = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.c = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -288,59 +248,40 @@
 	}
     }
 
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
+    if (area > 0 && m > 1) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    array_copy = G_malloc(m * sizeof(AVL_tableRow));
-    for (i = 0; i < m; i++) {
-	cc_passage = array[i]->k;
-	array_copy[i] = cc_passage.val.c;
-    }
-
-    qsort(array_copy, m, sizeof(int), cmp);
-
-    for (i = 1; i < m; i++) {
-	if (array_copy[i - 1] != array_copy[i]) {
-	    totNumClass++;
+	/* calculate shannon */
+	shannon = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
 	}
-    }
+	G_free(array);
 
-    /* calculate summary */
-    for (i = 0; i < m; i++) {
-	t = (double)array[i]->tot;
-	percentuale = (double)(t / area);
-	logaritmo = (double)log(percentuale);
-	somma = somma + (percentuale * logaritmo);
+	*result = -shannon / log(m);
     }
+    else
+	G_set_d_null_value(result, 1);
 
-    logTotNumClass = (double)log(totNumClass);
-    /*if a is 0, that is all cell are null, i put index=-1 */
-    if (a != 0) {
-	indice = ((-1) * somma) / logTotNumClass;
-    }
-    else {
-	indice = (double)(-1);
-    }
-
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
-    }
-    G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
-	    somma, logTotNumClass, indice);
-
-    *result = indice;
-
-    G_free(array);
+    avl_destroy(albero);
     if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
     }
 
@@ -348,42 +289,29 @@
 }
 
 
-
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
-
     DCELL *buf;
     DCELL corrCell;
     DCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
 
-    int a = 0;			/* a=0 if all cells are null */
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long totCorr = 1;
 
-    /*add to compute the number of class */
-    long *array_copy;
-    int totNumClass = 1;
-    double logTotNumClass;
+    long area = 0;
 
     avl_tree albero = NULL;
     AVL_table *array;
-    generic_cell cc;
-    generic_cell cc_passage;	/*add to compute the number of class */
+    generic_cell uc;
 
-    cc.t = DCELL_TYPE;
+    uc.t = DCELL_TYPE;
 
     /* open mask if needed */
     if (ad->mask == 1) {
@@ -397,14 +325,8 @@
 	masked = TRUE;
     }
 
-
     G_set_d_null_value(&precCell, 1);
-
-    /*for each row */
-    for (j = 0; j < ad->rl; j++) {
-	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
-
-
+    for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
@@ -412,76 +334,74 @@
 	    }
 	}
 
+	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, DCELL_TYPE))) {
-		a = 1;
-		if (G_is_null_value(&precCell, DCELL_TYPE)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			cc.val.dc = precCell;
-			albero = avl_make(cc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			cc.val.dc = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-		precCell = corrCell;
-	    }
-
-	}			/*close for */
-    }				/*close for */
-
-    if (masked) {
-	G_free(mask_buf);
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.dc = precCell;
-	    albero = avl_make(cc, totCorr);
+	    uc.val.dc = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -489,8 +409,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.fc = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.dc = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -513,7 +433,12 @@
 		}
 	    }
 	}
+    }
 
+    if (area > 0 && m > 1) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
 	array = G_malloc(m * sizeof(AVL_tableRow));
 	if (array == NULL) {
@@ -521,92 +446,59 @@
 	    return RLI_ERRORE;
 	}
 	tot = avl_to_array(albero, zero, array);
-
 	if (tot != m) {
-	    G_warning
-		("avl_to_array unaspected value. the result could be wrong");
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
 	    return RLI_ERRORE;
 	}
 
-	array_copy = G_malloc(m * sizeof(AVL_tableRow));
-
+	/* calculate shannon */
+	shannon = 0;
 	for (i = 0; i < m; i++) {
-	    cc_passage = array[i]->k;
-	    array_copy[i] = cc_passage.val.c;
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
 	}
-
-	qsort(array_copy, m, sizeof(int), cmp);
-
-	for (i = 1; i < m; i++) {
-	    if (array_copy[i - 1] != array_copy[i]) {
-		totNumClass++;
-	    }
-	}
-
-
-	/* calculate summary */
-	for (i = 0; i < m; i++) {
-	    t = (double)array[i]->tot;
-	    percentuale = (double)(t / area);
-	    logaritmo = (double)log(percentuale);
-	    somma = somma + (percentuale * logaritmo);
-	}
-
 	G_free(array);
 
-	logTotNumClass = (double)log(totNumClass);
-
-	indice = (-1) * somma / logTotNumClass;
+	*result = -shannon / log(m);
     }
-    else {
-	/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = ((double)(-1));
-    }
+    else
+	G_set_d_null_value(result, 1);
 
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
     }
-    G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
-	    somma, logTotNumClass, indice);
 
-    *result = indice;
-
     return RLI_OK;
 }
 
 
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
-
     FCELL *buf;
     FCELL corrCell;
     FCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
+
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
-    long *array_copy;
-    int totNumClass = 1;
-    double logTotNumClass;
+    long totCorr = 1;
 
+    long area = 0;
+
     avl_tree albero = NULL;
     AVL_table *array;
-    generic_cell cc;
-    generic_cell cc_passage;
+    generic_cell uc;
 
-    cc.t = FCELL_TYPE;
+    uc.t = FCELL_TYPE;
 
     /* open mask if needed */
     if (ad->mask == 1) {
@@ -620,15 +512,8 @@
 	masked = TRUE;
     }
 
-
     G_set_f_null_value(&precCell, 1);
-
-
-    /*for each row */
-    for (j = 0; j < ad->rl; j++) {
-	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
-
-
+    for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
@@ -636,71 +521,74 @@
 	    }
 	}
 
-	for (i = 0; i < ad->cl; i++) {	/* for each fcell in the row */
-	    area++;
+	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, cc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, cc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			cc.val.fc = precCell;
-			albero = avl_make(cc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			cc.val.fc = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-
-		precCell = corrCell;
-	    }
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.fc = precCell;
-	    albero = avl_make(cc, totCorr);
+	    uc.val.fc = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -708,8 +596,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.fc = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.fc = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -734,63 +622,42 @@
 	}
     }
 
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
+    if (area > 0 && m > 1) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    array_copy = G_malloc(m * sizeof(AVL_tableRow));
-
-    for (i = 0; i < m; i++) {
-	cc_passage = array[i]->k;
-	array_copy[i] = cc_passage.val.c;
-    }
-
-    qsort(array_copy, m, sizeof(int), cmp);
-
-    for (i = 1; i < m; i++) {
-	if (array_copy[i - 1] != array_copy[i]) {
-	    totNumClass++;
+	/* calculate shannon */
+	shannon = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
 	}
-    }
+	G_free(array);
 
-    /* calculate summary */
-    for (i = 0; i < m; i++) {
-	t = (double)array[i]->tot;
-	percentuale = (double)(t / area);
-	logaritmo = (double)log(percentuale);
-	somma = somma + (percentuale * logaritmo);
+	*result = -shannon / log(m);
     }
+    else
+	G_set_d_null_value(result, 1);
 
-    logTotNumClass = (double)log(totNumClass);
-
-
-    /*if a is 0, that is all cell are null, i put index=-1 */
-    if (a != 0) {
-	indice = ((-1) * somma) / logTotNumClass;
-    }
-    else {
-	indice = (double)(-1);
-    }
-
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
-    }
-    G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
-	    somma, logTotNumClass, indice);
-
-    *result = indice;
-
-    G_free(array);
+    avl_destroy(albero);
     if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
     }
+
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.renyi/renyi.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.renyi/renyi.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.renyi/renyi.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -3,10 +3,11 @@
  *
  * MODULE:	r.li.renyi
  *
- * PURPOSE:	brief calculates renyi's diversity index
+ * PURPOSE:	calculates renyi's diversity index
  *
  * AUTHOR(S):	Luca Delucchi, Fondazione Edmund Mach         
  *		Serena Pallecchi student of Computer Science University of Pisa (Italy)
+ *              Rewrite: Markus Metz
  *            	
  * COPYRIGHT:
  *		This program is free software under the GPL (>=v2)
@@ -21,17 +22,17 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/daemon.h"
 #include "../r.li.daemon/avlDefs.h"
 #include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
 
-double calculate(struct area_entry *ad, int fd, char **par, double *result);
+/* template is shannon */
 
-double calculateD(struct area_entry *ad, int fd, char **par, double *result);
+rli_func renyi;
+int calculate(int fd, struct area_entry *ad, char **par, double *result);
+int calculateD(int fd, struct area_entry *ad, char **par, double *result);
+int calculateF(int fd, struct area_entry *ad, char **par, double *result);
 
-double calculateF(struct area_entry *ad, int fd, char **par, double *result);
-
 int main(int argc, char *argv[])
 {
     struct Option *raster, *conf, *output, *alpha;
@@ -49,11 +50,9 @@
 
     raster = G_define_standard_option(G_OPT_R_MAP);
 
-    conf = G_define_option();
+    conf = G_define_standard_option(G_OPT_F_INPUT);
     conf->key = "conf";
     conf->description = _("Configuration file");
-    conf->type = TYPE_STRING;
-    conf->gisprompt = "old_file,file,input";
     conf->required = YES;
 
     alpha = G_define_option();
@@ -68,7 +67,7 @@
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
-    if (atoi(alpha->answer) == 1) {
+    if (atof(alpha->answer) == 1) {
 	G_fatal_error
 	    ("If alpha = 1 Renyi index is not defined. (Ricotta et al., 2003, Environ. Model. Softw.)");
 	exit(RLI_ERRORE);
@@ -83,34 +82,31 @@
     }
     return calculateIndex(conf->answer, renyi, par, raster->answer,
 			  output->answer);
-
 }
 
+
 int renyi(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
+    if (!par)
+	G_fatal_error("par is NULL");
 
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
-	    ris = calculate(ad, fd, par, &indice);
+	    ris = calculate(fd, ad, par, &indice);
 	    break;
 	}
     case DCELL_TYPE:
 	{
-	    ris = calculateD(ad, fd, par, &indice);
+	    ris = calculateD(fd, ad, par, &indice);
 	    break;
 	}
     case FCELL_TYPE:
 	{
-	    ris = calculateF(ad, fd, par, &indice);
+	    ris = calculateF(fd, ad, par, &indice);
 	    break;
 	}
     default:
@@ -118,41 +114,36 @@
 	    G_fatal_error("data type unknown");
 	    return RLI_ERRORE;
 	}
-
     }
 
-    if (ris != RLI_OK)
+    if (ris != RLI_OK) {
 	return RLI_ERRORE;
+    }
 
     *result = indice;
 
     return RLI_OK;
-
 }
 
 
-
-double calculate(struct area_entry *ad, int fd, char **par, double *result)
+int calculate(int fd, struct area_entry *ad, char **par, double *result)
 {
     CELL *buf;
     CELL corrCell;
     CELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
+
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
-    double indice = 0;
-    double somma = 0;
-    double p = 0;
-    double area = 0;
-    double t;
+    long totCorr = 1;
 
+    long area = 0;
+
     avl_tree albero = NULL;
     AVL_table *array;
     generic_cell uc;
@@ -172,8 +163,6 @@
     }
 
     G_set_c_null_value(&precCell, 1);
-
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -183,70 +172,70 @@
 	}
 
 	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf[i + ad->x];
 
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
+		    if (albero == NULL) {
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
 		}
-		if (corrCell != precCell) {
-		    if (albero == NULL) {
-			uc.val.c = precCell;
-			albero = avl_make(uc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+		else {
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			else
+		    case AVL_ADD:
+			{
 			    m++;
-		    }
-		    else {
-			uc.val.c = precCell;
-			ris = avl_add(&albero, uc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
-		}		/* endif not equal cells */
-		else {		/*equal cells */
-
-		    totCorr++;
 		}
-		precCell = corrCell;
-	    }
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.c = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -282,69 +271,80 @@
 	    }
 	}
     }
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
 
-    char *sval;
+    if (area > 0) {
+	double alpha;
+	double pi;
+	double t;
+	double sum, sum2;
 
-    sval = par[0];
-    double alpha_double;
+	alpha = atof(par[0]);
 
-    alpha_double = (double)atof(sval);
-    /* claculate index summary */
-    for (i = 0; i < m; i++) {
-	t = (double)(array[i]->tot);
-	p = t / area;
-	G_debug(1, "Valore p: %g, valore pow: %g", p, pow(p, alpha_double));
-	somma = somma + pow(p, alpha_double);
-    }
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    indice = (1 / (1 - alpha_double)) * log(somma);
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
-    }
-    G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
+	/* calculate renyi index */
+	sum = 0;
+	sum2 = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    pi = t / area;
+	    sum += pow(pi, alpha);
+	    sum2 += pi;
+	}
+	G_free(array);
 
-    *result = indice;
+	/* correction for numerical instability */
+	if (sum2 != 1)
+	    sum += 1 - sum2;
 
+	if ((alpha < 1 && sum < 1) || (alpha > 1 && sum > 1)) {
+	    G_warning("Renyi index calculation reached numerical instability. "
+	              "This can happen with alpha close to 1. The result will be set to zero.");
+	    sum = 1;
+	}
 
-    G_free(array);
-    if (masked)
+	*result = (1 / (1 - alpha)) * log(sum);
+    }
+    else
+	G_set_d_null_value(result, 1);
+
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
     return RLI_OK;
 }
 
 
-double calculateD(struct area_entry *ad, int fd, char **par, double *result)
+int calculateD(int fd, struct area_entry *ad, char **par, double *result)
 {
     DCELL *buf;
     DCELL corrCell;
     DCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
+
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
-    double indice = 0;
-    double somma = 0;
-    double p = 0;
-    double area = 0;
-    double t;
+    long totCorr = 1;
 
+    long area = 0;
+
     avl_tree albero = NULL;
     AVL_table *array;
     generic_cell uc;
@@ -357,14 +357,13 @@
 	    return RLI_ERRORE;
 	mask_buf = G_malloc(ad->cl * sizeof(int));
 	if (mask_buf == NULL) {
-	    G_fatal_error("malloc mask_buffailed");
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
 	masked = TRUE;
     }
 
     G_set_d_null_value(&precCell, 1);
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -375,71 +374,69 @@
 
 	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
+		/* total patch area */
+		area++;
+	    }
 
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
+		    if (albero == NULL) {
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
 		}
-		if (corrCell != precCell) {
-		    if (albero == NULL) {
-			uc.val.dc = precCell;
-			albero = avl_make(uc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+		else {
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			uc.val.dc = precCell;
-			ris = avl_add(&albero, uc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
-		}		/* endif not equal dcells */
-		else {		/*equal dcells */
-
-		    totCorr++;
 		}
-		precCell = corrCell;
-	    }
-
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.dc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -475,71 +472,80 @@
 	    }
 	}
     }
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
 
-    char *sval;
+    if (area > 0) {
+	double alpha;
+	double pi;
+	double t;
+	double sum, sum2;
 
-    sval = par[0];
-    double alpha_double;
+	alpha = atof(par[0]);
 
-    alpha_double = (double)atof(sval);
-    /* claculate index summary */
-    for (i = 0; i < m; i++) {
-	t = (double)(array[i]->tot);
-	p = t / area;
-	G_debug(1, "Valore p: %g, valore pow: %g", p, pow(p, alpha_double));
-	somma = somma + pow(p, alpha_double);
-    }
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    indice = (1 / (1 - alpha_double)) * log(somma);
+	/* calculate renyi index */
+	sum = 0;
+	sum2 = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    pi = t / area;
+	    sum += pow(pi, alpha);
+	    sum += pi;
+	}
+	G_free(array);
 
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
-    }
+	/* correction for numerical instability */
+	if (sum2 != 1)
+	    sum += 1 - sum2;
 
-    G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
+	if ((alpha < 1 && sum < 1) || (alpha > 1 && sum > 1)) {
+	    G_warning("Renyi index calculation reached numerical instability. "
+	              "This can happen with alpha close to 1. The result will be set to zero.");
+	    sum = 1;
+	}
 
-    *result = indice;
+	*result = (1 / (1 - alpha)) * log(sum);
+    }
+    else
+	G_set_d_null_value(result, 1);
 
-    G_free(array);
-    if (masked)
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
     return RLI_OK;
 }
 
 
-
-double calculateF(struct area_entry *ad, int fd, char **par, double *result)
+int calculateF(int fd, struct area_entry *ad, char **par, double *result)
 {
     FCELL *buf;
     FCELL corrCell;
     FCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
+
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
-    double indice = 0;
-    double somma = 0;
-    double p = 0;
-    double area = 0;
-    double t;
+    long totCorr = 1;
 
+    long area = 0;
+
     avl_tree albero = NULL;
     AVL_table *array;
     generic_cell uc;
@@ -559,8 +565,6 @@
     }
 
     G_set_f_null_value(&precCell, 1);
-
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -571,72 +575,69 @@
 
 	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
 
-
-	for (i = 0; i < ad->cl; i++) {	/* for each fcell in the row */
-
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
+		    if (albero == NULL) {
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
 		}
-		if (corrCell != precCell) {
-		    if (albero == NULL) {
-			uc.val.fc = precCell;
-			albero = avl_make(uc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+		else {
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			uc.val.fc = precCell;
-			ris = avl_add(&albero, uc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
-		}		/* endif not equal fcells */
-		else {		/*equal fcells */
-
-		    totCorr++;
 		}
-		precCell = corrCell;
-	    }
-
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.fc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -673,45 +674,56 @@
 	}
     }
 
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+    if (area > 0) {
+	double alpha;
+	double pi;
+	double t;
+	double sum, sum2;
 
-    char *sval;
+	alpha = atof(par[0]);
 
-    sval = par[0];
-    double alpha_double;
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    alpha_double = (double)atof(sval);
-    /* calculate index summary */
-    for (i = 0; i < m; i++) {
-	t = (double)(array[i]->tot);
-	p = t / area;
-	G_debug(1, "Valore p: %g, valore pow: %g", p, pow(p, alpha_double));
-	somma = somma + pow(p, alpha_double);
-    }
+	/* calculate renyi index */
+	sum = 0;
+	sum2 = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    pi = t / area;
+	    sum += pow(pi, alpha);
+	    sum2 += pi;
+	}
+	G_free(array);
 
-    indice = (1 / (1 - alpha_double)) * log(somma);
+	/* correction for numerical instability */
+	if (sum2 != 1)
+	    sum += 1 - sum2;
 
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
+	if ((alpha < 1 && sum < 1) || (alpha > 1 && sum > 1)) {
+	    G_warning("Renyi index calculation reached numerical instability. "
+	              "This can happen with alpha close to 1. The result will be set to zero.");
+	    sum = 1;
+	}
+
+	*result = (1 / (1 - alpha)) * log(sum);
     }
+    else
+	G_set_d_null_value(result, 1);
 
-    G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
-
-    *result = indice;
-
-    G_free(array);
-    if (masked)
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
     return RLI_OK;
-
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.richness/richness.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.richness/richness.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.richness/richness.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -1,30 +1,34 @@
-
-/*
- * \brief calculates richness diversity index
+/****************************************************************************
  *
- *  \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:	r.li.ritchness
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
+ * PURPOSE:	calculates richness diversity index
  *
- */
+ * AUTHOR(S):	Serena Pallecchi student of Computer Science University of Pisa (Italy)
+ *              Commission from Faunalia Pontedera (PI) www.faunalia.it
+ *              Rewrite: Markus Metz
+ *            	
+ * COPYRIGHT:
+ *		This program is free software under the GPL (>=v2)
+ *		Read the COPYING file that comes with GRASS for details.
+ *
+ ***************************************************************************/
 
-#include <grass/gis.h>
-#include <grass/glocale.h>
-
 #include <stdlib.h>
 #include <fcntl.h>
 #include <math.h>
 
-#include "../r.li.daemon/defs.h"
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+#include "../r.li.daemon/daemon.h"
 #include "../r.li.daemon/avlDefs.h"
 #include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
 
-double calculate(struct area_entry *ad, int fd, double *result);
-double calculateD(struct area_entry *ad, int fd, double *result);
-double calculateF(struct area_entry *ad, int fd, double *result);
+rli_func richness;
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
 
 int main(int argc, char *argv[])
 {
@@ -34,9 +38,9 @@
     G_gisinit(argv[0]);
     module = G_define_module();
     module->description =
-	_("Calculates dominance's diversity index on a raster map");
+	_("Calculates richness index on a raster map");
     module->keywords =
-	_("raster, landscape structure analysis, dominance index");
+	_("raster, landscape structure analysis, diversity index");
 
     /* define options */
 
@@ -52,36 +56,29 @@
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
-    return calculateIndex(conf->answer, dominance, NULL, raster->answer,
+    return calculateIndex(conf->answer, richness, NULL, raster->answer,
 			  output->answer);
-
 }
 
-int dominance(int fd, char **par, struct area_entry *ad, double *result)
+int richness(int fd, char **par, struct area_entry *ad, double *result)
 {
-    char *mapset;
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return RLI_ERRORE;
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
-	    ris = calculate(ad, fd, &indice);
+	    ris = calculate(fd, ad, &indice);
 	    break;
 	}
     case DCELL_TYPE:
 	{
-	    ris = calculateD(ad, fd, &indice);
+	    ris = calculateD(fd, ad, &indice);
 	    break;
 	}
     case FCELL_TYPE:
 	{
-	    ris = calculateF(ad, fd, &indice);
+	    ris = calculateF(fd, ad, &indice);
 	    break;
 	}
     default:
@@ -89,33 +86,30 @@
 	    G_fatal_error("data type unknown");
 	    return RLI_ERRORE;
 	}
-
     }
 
-    if (ris != RLI_OK)
+    if (ris != RLI_OK) {
 	return RLI_ERRORE;
+    }
 
     *result = indice;
 
     return RLI_OK;
-
 }
 
 
-
-double calculate(struct area_entry *ad, int fd, double *result)
+int calculate(int fd, struct area_entry *ad, double *result)
 {
     CELL *buf;
     CELL corrCell;
     CELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
     long m = 0;
-    double indice = 0;
+    long area = 0;
     avl_tree albero = NULL;
     generic_cell uc;
 
@@ -134,8 +128,6 @@
     }
 
     G_set_c_null_value(&precCell, 1);
-
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -145,67 +137,62 @@
 	}
 
 	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
 	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
 
-	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		 corrCell != precCell) {
+
+		if (albero == NULL) {
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, (long)1);
 		    if (albero == NULL) {
-			uc.val.c = precCell;
-			albero = avl_make(uc, (long)1);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, (long)1);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			else
+		    case AVL_ADD:
+			{
 			    m++;
-		    }
-		    else {
-			uc.val.c = precCell;
-			ris = avl_add(&albero, uc, (long)1);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		}		/* endif not equal cells */
-		else {		/*equal cells */
-
-		    ;
 		}
-		precCell = corrCell;
-	    }
-
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (!(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.c = precCell;
 	    albero = avl_make(uc, (long)1);
@@ -242,36 +229,34 @@
 	}
     }
 
-    if (a != 0) {
-	indice = m;
-    }
-    else			/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+    if (area)
+	*result = m;
+    else
+	G_set_d_null_value(result, 1);
 
-    if (masked)
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
-    *result = indice;
-
     return RLI_OK;
 }
 
 
-double calculateD(struct area_entry *ad, int fd, double *result)
+int calculateD(int fd, struct area_entry *ad, double *result)
 {
     DCELL *buf;
     DCELL corrCell;
     DCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
     long m = 0;
-    double indice = 0;
+    long area = 0;
     avl_tree albero = NULL;
-
     generic_cell uc;
 
     uc.t = DCELL_TYPE;
@@ -282,14 +267,13 @@
 	    return RLI_ERRORE;
 	mask_buf = G_malloc(ad->cl * sizeof(int));
 	if (mask_buf == NULL) {
-	    G_fatal_error("malloc mask_buffailed");
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
 	masked = TRUE;
     }
 
     G_set_d_null_value(&precCell, 1);
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -303,66 +287,58 @@
 	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
 	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
 
-	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		 corrCell != precCell) {
 
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+		if (albero == NULL) {
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, (long)1);
 		    if (albero == NULL) {
-			uc.val.dc = precCell;
-			albero = avl_make(uc, (long)1);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, (long)1);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			uc.val.dc = precCell;
-			ris = avl_add(&albero, uc, (long)1);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-
-		}		/* endif not equal dcells */
-		else {		/*equal dcells */
-
-		    ;
 		}
-		precCell = corrCell;
-	    }
-
-
+	    }		/* endif not equal dcells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (!(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.dc = precCell;
 	    albero = avl_make(uc, (long)1);
@@ -399,41 +375,34 @@
 	}
     }
 
-
-    if (a != 0) {		/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = m;
-    }
+    if (area)
+	*result = m;
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-
-    if (masked)
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
-    *result = indice;
     return RLI_OK;
 }
 
 
-
-double calculateF(struct area_entry *ad, int fd, double *result)
+int calculateF(int fd, struct area_entry *ad, double *result)
 {
     FCELL *buf;
     FCELL corrCell;
     FCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
-
     long m = 0;
-
-    double indice = 0;
-
+    long area = 0;
     avl_tree albero = NULL;
-
     generic_cell uc;
 
     uc.t = FCELL_TYPE;
@@ -451,8 +420,6 @@
     }
 
     G_set_f_null_value(&precCell, 1);
-
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -463,70 +430,63 @@
 
 	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
 
-
 	for (i = 0; i < ad->cl; i++) {	/* for each fcell in the row */
 
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
 	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
 
-	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		 corrCell != precCell) {
+
+		if (albero == NULL) {
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, (long)1);
 		    if (albero == NULL) {
-			uc.val.fc = precCell;
-			albero = avl_make(uc, (long)1);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, (long)1);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			uc.val.fc = precCell;
-			ris = avl_add(&albero, uc, (long)1);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-
-		}		/* endif not equal fcells */
-		else {		/*equal fcells */
-
-		    ;
 		}
-		precCell = corrCell;
-	    }
 
-
+	    }		/* endif not equal fcells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (!(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.fc = precCell;
 	    albero = avl_make(uc, (long)1);
@@ -563,19 +523,16 @@
 	}
     }
 
-
-
-    if (a != 0) {		/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = m;
-    }
+    if (area)
+	*result = m;
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-
-    if (masked)
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
-
-    *result = indice;
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.shannon/shannon.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.shannon/shannon.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.shannon/shannon.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -4,6 +4,7 @@
  * AUTHOR(S):    Serena Pallecchi (original contributor)
  *                student of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
+ *               Rewrite: Markus Metz
  *
  * PURPOSE:      calculates Shannon's diversity index
  * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
@@ -14,20 +15,20 @@
  *
  *****************************************************************************/
 
-#include <grass/gis.h>
-#include <grass/glocale.h>
-
 #include <stdlib.h>
 #include <fcntl.h>
 #include <math.h>
 
-#include "../r.li.daemon/defs.h"
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+#include "../r.li.daemon/daemon.h"
 #include "../r.li.daemon/avlDefs.h"
 #include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
 
 /* template for dominance, renyi, pielou, simpson */
 
+rli_func shannon;
 int calculate(int fd, struct area_entry *ad, double *result);
 int calculateD(int fd, struct area_entry *ad, double *result);
 int calculateF(int fd, struct area_entry *ad, double *result);
@@ -63,7 +64,7 @@
 }
 
 
-int shannon(int fd, char **par, struct area_entry * ad, double *result)
+int shannon(int fd, char **par, struct area_entry *ad, double *result)
 {
     char *mapset;
     int ris = RLI_OK;
@@ -78,17 +79,17 @@
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
-	    calculate(fd, ad, &indice);
+	    ris = calculate(fd, ad, &indice);
 	    break;
 	}
     case DCELL_TYPE:
 	{
-	    calculateD(fd, ad, &indice);
+	    ris = calculateD(fd, ad, &indice);
 	    break;
 	}
     case FCELL_TYPE:
 	{
-	    calculateF(fd, ad, &indice);
+	    ris = calculateF(fd, ad, &indice);
 	    break;
 	}
     default:
@@ -115,29 +116,22 @@
     CELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
-    generic_cell cc;
-
     avl_tree albero = NULL;
     AVL_table *array;
+    generic_cell uc;
 
-    cc.t = CELL_TYPE;
+    uc.t = CELL_TYPE;
 
     /* open mask if needed */
     if (ad->mask == 1) {
@@ -151,15 +145,8 @@
 	masked = TRUE;
     }
 
-
     G_set_c_null_value(&precCell, 1);
-
-
-    /*for each row */
-    for (j = 0; j < ad->rl; j++) {
-	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
-
-
+    for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
@@ -167,76 +154,74 @@
 	    }
 	}
 
+	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
 
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, CELL_TYPE))) {
-		a = 1;
-		if (G_is_null_value(&precCell, cc.t)) {
-		    precCell = corrCell;
-		}
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
 
-		if (corrCell != precCell) {
-		    if (albero == NULL) {
-			cc.val.c = precCell;
-			albero = avl_make(cc, totCorr);
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
 
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
+		    if (albero == NULL) {
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			cc.val.c = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-		precCell = corrCell;
-	    }
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
 
-	}			/* end for */
-    }				/* end for */
-
-
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.c = precCell;
-	    albero = avl_make(cc, totCorr);
-
+	    uc.val.c = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -244,8 +229,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.c = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.c = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -270,37 +255,40 @@
 	}
     }
 
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    /* calculate summary */
-    for (i = 0; i < m; i++) {
-	t = (double)array[i]->tot;
-	percentuale = (double)(t / area);
-	logaritmo = (double)log(percentuale);
-	somma = somma + (percentuale * logaritmo);
-    }
+	/* calculate shannon */
+	shannon = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
+	}
+	G_free(array);
 
-
-    /*if a is 0, that is all cell are null, i put index=-1 */
-    if (a != 0)
-	indice = (-1) * somma;
+	*result = -shannon;
+    }
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-    *result = indice;
-
-    G_free(array);
+    avl_destroy(albero);
     if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
     }
 
@@ -308,40 +296,30 @@
 }
 
 
-
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
-
     DCELL *buf;
     DCELL corrCell;
     DCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
     avl_tree albero = NULL;
-
     AVL_table *array;
+    generic_cell uc;
 
-    generic_cell cc;
+    uc.t = DCELL_TYPE;
 
-    cc.t = DCELL_TYPE;
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -354,14 +332,8 @@
 	masked = TRUE;
     }
 
-
     G_set_d_null_value(&precCell, 1);
-
-    /*for each row */
-    for (j = 0; j < ad->rl; j++) {
-	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
-
-
+    for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
@@ -369,76 +341,74 @@
 	    }
 	}
 
+	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, DCELL_TYPE))) {
-		a = 1;
-		if (G_is_null_value(&precCell, DCELL_TYPE)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			cc.val.dc = precCell;
-			albero = avl_make(cc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			cc.val.dc = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-		precCell = corrCell;
-	    }
-
-	}			/*close for */
-    }				/*close for */
-
-    if (masked) {
-	G_free(mask_buf);
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.dc = precCell;
-	    albero = avl_make(cc, totCorr);
+	    uc.val.dc = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -446,8 +416,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.fc = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.dc = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -470,7 +440,12 @@
 		}
 	    }
 	}
+    }
 
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
 	array = G_malloc(m * sizeof(AVL_tableRow));
 	if (array == NULL) {
@@ -478,73 +453,60 @@
 	    return RLI_ERRORE;
 	}
 	tot = avl_to_array(albero, zero, array);
-
 	if (tot != m) {
-	    G_warning
-		("avl_to_array unaspected value. the result could be wrong");
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
 	    return RLI_ERRORE;
 	}
 
-	/* calculate summary */
+	/* calculate shannon */
+	shannon = 0;
 	for (i = 0; i < m; i++) {
-	    t = (double)array[i]->tot;
-	    percentuale = (double)(t / area);
-	    logaritmo = (double)log(percentuale);
-	    somma = somma + (percentuale * logaritmo);
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
 	}
-
 	G_free(array);
 
-
-	indice = (-1) * somma;
+	*result = -shannon;
     }
     else
-	/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+    }
 
-    *result = indice;
-
-
-
-
     return RLI_OK;
 }
 
 
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
-
     FCELL *buf;
     FCELL corrCell;
     FCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
     avl_tree albero = NULL;
-
     AVL_table *array;
+    generic_cell uc;
 
-    generic_cell cc;
+    uc.t = FCELL_TYPE;
 
-    cc.t = FCELL_TYPE;
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -557,15 +519,8 @@
 	masked = TRUE;
     }
 
-
     G_set_f_null_value(&precCell, 1);
-
-
-    /*for each row */
-    for (j = 0; j < ad->rl; j++) {
-	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
-
-
+    for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
 		G_fatal_error("mask read failed");
@@ -573,73 +528,74 @@
 	    }
 	}
 
+	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each fcell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
-	    if (masked && mask_buf[i + ad->x] == 0) {
+
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(G_is_null_value(&corrCell, FCELL_TYPE))) {
-		a = 1;
-		if (G_is_null_value(&precCell, FCELL_TYPE)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&corrCell, uc.t))) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			cc.val.fc = precCell;
-			albero = avl_make(cc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			cc.val.fc = precCell;
-			ris = avl_add(&albero, cc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_add unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
 		}
-		else {
-		    totCorr++;
-		}
-
-		precCell = corrCell;
-	    }
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
-	    cc.val.fc = precCell;
-	    albero = avl_make(cc, totCorr);
+	    uc.val.fc = precCell;
+	    albero = avl_make(uc, totCorr);
 	    if (albero == NULL) {
 		G_fatal_error("avl_make error");
 		return RLI_ERRORE;
@@ -647,8 +603,8 @@
 	    m++;
 	}
 	else {
-	    cc.val.fc = precCell;
-	    ris = avl_add(&albero, cc, totCorr);
+	    uc.val.fc = precCell;
+	    ris = avl_add(&albero, uc, totCorr);
 	    switch (ris) {
 	    case AVL_ERR:
 		{
@@ -673,39 +629,42 @@
 	}
     }
 
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;
 
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    /* calculate summary */
-    for (i = 0; i < m; i++) {
-	t = (double)array[i]->tot;
-	percentuale = (double)(t / area);
-	logaritmo = (double)log(percentuale);
-	somma = somma + (percentuale * logaritmo);
-    }
+	/* calculate shannon */
+	shannon = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    perc = t / area;
+	    logarithm = log(perc);
+	    shannon += perc * logarithm;
+	}
+	G_free(array);
 
-    /*if a is 0, that is all cell are null, i put index=-1 */
-    if (a != 0)
-	indice = (-1) * somma;
+	*result = -shannon;
+    }
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-
-    *result = indice;
-
-
-    G_free(array);
+    avl_destroy(albero);
     if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
     }
+
     return RLI_OK;
 }

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.shape/main.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.shape/main.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.shape/main.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -6,10 +6,11 @@
  *                students of Computer Science University of Pisa (Italy)
  *               Commission from Faunalia Pontedera (PI) www.faunalia.it
  *               Fixes: Markus Neteler <neteler itc.it>
- *               
- * PURPOSE:      calculates shape index
- * COPYRIGHT:    (C) 2006-2007 by the GRASS Development Team
+ *               Rewrite: Markus Metz
  *
+ * PURPOSE:      calculates patch number index
+ * COPYRIGHT:    (C) 2007-2014 by the GRASS Development Team
+ *
  *               This program is free software under the GNU General Public
  *               License (>=v2). Read the file COPYING that comes with GRASS
  *               for details.
@@ -18,10 +19,26 @@
 
 #include <stdlib.h>
 #include <fcntl.h>
+#include <math.h>
 #include <grass/gis.h>
+#include <grass/raster.h>
 #include <grass/glocale.h>
 #include "../r.li.daemon/daemon.h"
+#include "../r.li.daemon/GenericCell.h"
 
+
+/* type, cell count and edge count of each patch */
+struct pst {
+    generic_cell type;
+    long cells;
+    long edges;
+};
+
+rli_func shape_index;
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
+
 int main(int argc, char *argv[])
 {
     struct Option *raster, *conf, *output;
@@ -54,55 +71,754 @@
 
 int shape_index(int fd, char **par, struct area_entry *ad, double *result)
 {
-    double area;
-    char *mapset;
-    struct Cell_head hd;
-    CELL complete_value;
-    double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
-    int mask_fd = -1, null_count = 0;
-    int i = 0, k = 0;
-    int *mask_buf;
+    int ris = RLI_OK;
+    double indice = 0;
 
-    G_set_c_null_value(&complete_value, 1);
+    switch (ad->data_type) {
+    case CELL_TYPE:
+	{
+	    ris = calculate(fd, ad, &indice);
+	    break;
+	}
+    case DCELL_TYPE:
+	{
+	    ris = calculateD(fd, ad, &indice);
+	    break;
+	}
+    case FCELL_TYPE:
+	{
+	    ris = calculateF(fd, ad, &indice);
+	    break;
+	}
+    default:
+	{
+	    G_fatal_error("data type unknown");
+	    return RLI_ERRORE;
+	}
+    }
 
-    mapset = G_find_cell(ad->raster, "");
-    if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
-	return 0;
+    if (ris != RLI_OK) {
+	return RLI_ERRORE;
+    }
 
+    *result = indice;
 
+    return RLI_OK;
+}
+
+
+int calculate(int fd, struct area_entry *ad, double *result)
+{
+    CELL *buf, *buf_sup, *buf_null;
+    CELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+
+    buf_null = G_allocate_cell_buf();
+    G_set_c_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
-	    return 0;
-	mask_buf = malloc(ad->cl * sizeof(int));
-	for (i = 0; i < ad->rl; i++) {
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
+	masked = TRUE;
+    }
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].cells = 0;
+	pst[k].edges = 0;
+    }
+
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
+	}
+
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
 		return 0;
-	    for (k = 0; k < ad->cl; k++) {
-		if (mask_buf[k] == 0) {
-		    null_count++;
+	}
+
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_c_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_c_null_value(&corrCell, 1);
+	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
+
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_c_null_value(&supCell, 1);
+	    }
+
+	    if (G_is_c_null_value(&corrCell)) {
+		if (!G_is_c_null_value(&precCell))
+		    pst[pid_corr[j - 1]].edges++;
+		if (!G_is_c_null_value(&supCell))
+		    pst[pid_sup[j]].edges++;
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+
+	    if (!G_is_c_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].cells++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_c_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
+
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].cells += pst[old_pid].cells;
+			pst[old_pid].cells = 0;
+			pst[new_pid].edges += pst[old_pid].edges;
+			pst[old_pid].edges = 0;
+			
+			if (old_pid == pid)
+			    pid--;
+		    }
+		    else {
+			pst[new_pid].cells++;
+		    }
 		}
+		connected = 1;
 	    }
+
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++) {
+			pst[k].cells = 0;
+			pst[k].edges = 0;
+		    }
+			
+		    nalloc = pid + incr;
+		}
+
+		pst[pid].cells = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
+	    }
+	    /* update edge count for corr */
+	    if (G_is_c_null_value(&precCell) || precCell != corrCell)
+		pst[pid_corr[j]].edges++;
+	    if (G_is_c_null_value(&supCell) || supCell != corrCell)
+		pst[pid_corr[j]].edges++;
+	    if (i == ad->rl - 1)
+		pst[pid_corr[j]].edges++;
+	    if (j == ad->cl - 1)
+		pst[pid_corr[j]].edges++;
+	    /* update edge count for prec */
+	    if (!G_is_c_null_value(&precCell) && precCell != corrCell)
+		pst[pid_corr[j - 1]].edges++;
+	    /* update edge count for sup */
+	    if (!G_is_c_null_value(&supCell) && supCell != corrCell)
+		pst[pid_sup[j]].edges++;
+
+	    precCell = corrCell;
 	}
-	/* todo? free(mask_buf); */
     }
 
-    /* calculate distance */
-    G_begin_distance_calculations();
-    /* EW Dist at North edge */
-    EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
-    /* EW Dist at South Edge */
-    EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
-    /* NS Dist at East edge */
-    NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
-    /* NS Dist at West edge */
-    NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
+    if (npatch > 0) {
+	double edges, cells;
 
-    area = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
-	(((NS_DIST1 + NS_DIST2) / 2) / hd.rows) *
-	(ad->rl * ad->cl - null_count);
+	edges = cells = 0;
+	
+	for (i = 1; i <= pid; i++) {
+	    cells += pst[i].cells;
+	    edges += pst[i].edges;
+	}
 
-    *result = area;
+	*result = 0.25 * edges / sqrt(cells);
+    }
+    else {
+	G_set_d_null_value(result, 1);
+    }
 
-    return 1;
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
+    return RLI_OK;
 }
+
+
+int calculateD(int fd, struct area_entry *ad, double *result)
+{
+    DCELL *buf, *buf_sup, *buf_null;
+    DCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+
+    buf_null = G_allocate_d_raster_buf();
+    G_set_d_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
+    /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
+    if (ad->mask == 1) {
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
+	masked = TRUE;
+    }
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].cells = 0;
+	pst[k].edges = 0;
+    }
+
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
+	}
+
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
+
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_d_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_d_null_value(&corrCell, 1);
+	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
+
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_d_null_value(&supCell, 1);
+	    }
+
+	    if (G_is_d_null_value(&corrCell)) {
+		if (!G_is_d_null_value(&precCell))
+		    pst[pid_corr[j - 1]].edges++;
+		if (!G_is_d_null_value(&supCell))
+		    pst[pid_sup[j]].edges++;
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+
+	    if (!G_is_d_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].cells++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_d_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
+
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].cells += pst[old_pid].cells;
+			pst[old_pid].cells = 0;
+			pst[new_pid].edges += pst[old_pid].edges;
+			pst[old_pid].edges = 0;
+			
+			if (old_pid == pid)
+			    pid--;
+		    }
+		    else {
+			pst[new_pid].cells++;
+		    }
+		}
+		connected = 1;
+	    }
+
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++) {
+			pst[k].cells = 0;
+			pst[k].edges = 0;
+		    }
+			
+		    nalloc = pid + incr;
+		}
+
+		pst[pid].cells = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
+	    }
+	    /* update edge count for corr */
+	    if (G_is_d_null_value(&precCell) || precCell != corrCell)
+		pst[pid_corr[j]].edges++;
+	    if (G_is_d_null_value(&supCell) || supCell != corrCell)
+		pst[pid_corr[j]].edges++;
+	    if (i == ad->rl - 1)
+		pst[pid_corr[j]].edges++;
+	    if (j == ad->cl - 1)
+		pst[pid_corr[j]].edges++;
+	    /* update edge count for prec */
+	    if (!G_is_d_null_value(&precCell) && precCell != corrCell)
+		pst[pid_corr[j - 1]].edges++;
+	    /* update edge count for sup */
+	    if (!G_is_d_null_value(&supCell) && supCell != corrCell)
+		pst[pid_sup[j]].edges++;
+
+	    precCell = corrCell;
+	}
+    }
+
+    if (npatch > 0) {
+	double edges, cells;
+
+	edges = cells = 0;
+	
+	for (i = 1; i <= pid; i++) {
+	    cells += pst[i].cells;
+	    edges += pst[i].edges;
+	}
+
+	*result = 0.25 * edges / sqrt(cells);
+    }
+    else {
+	G_set_d_null_value(result, 1);
+    }
+
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
+    return RLI_OK;
+}
+
+
+int calculateF(int fd, struct area_entry *ad, double *result)
+{
+    FCELL *buf, *buf_sup, *buf_null;
+    FCELL corrCell, precCell, supCell;
+    long npatch, area; 
+    long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
+    struct pst *pst;
+    long nalloc, incr;
+    int i, j, k;
+    int connected;
+    int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
+
+    buf_null = G_allocate_f_raster_buf();
+    G_set_f_null_value(buf_null, G_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(ad->cl * sizeof(long));
+    pid_sup = G_malloc(ad->cl * sizeof(long));
+
+    for (j = 0; j < ad->cl; j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
+    /* open mask if needed */
+    mask_fd = -1;
+    mask_buf = mask_sup = NULL;
+    masked = FALSE;
+    if (ad->mask == 1) {
+	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
+	    return RLI_ERRORE;
+	mask_buf = G_malloc(ad->cl * sizeof(int));
+	if (mask_buf == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	mask_sup = G_malloc(ad->cl * sizeof(int));
+	if (mask_sup == NULL) {
+	    G_fatal_error("malloc mask_buf failed");
+	    return RLI_ERRORE;
+	}
+	for (j = 0; j < ad->cl; j++)
+	    mask_buf[j] = 0;
+
+	masked = TRUE;
+    }
+
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
+
+    /* patch size and type */
+    incr = 1024;
+    if (incr > ad->rl)
+	incr = ad->rl;
+    if (incr > ad->cl)
+	incr = ad->cl;
+    if (incr < 2)
+	incr = 2;
+    nalloc = incr;
+    pst = G_malloc(nalloc * sizeof(struct pst));
+    for (k = 0; k < nalloc; k++) {
+	pst[k].cells = 0;
+	pst[k].edges = 0;
+    }
+
+    for (i = 0; i < ad->rl; i++) {
+	buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
+	if (i > 0) {
+	    buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
+	}
+
+	if (masked) {
+	    mask_tmp = mask_sup;
+	    mask_sup = mask_buf;
+	    mask_buf = mask_tmp;
+	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
+		return 0;
+	}
+
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	G_set_f_null_value(&precCell, 1);
+
+	connected = 0;
+	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j] == 0)) {
+		G_set_f_null_value(&corrCell, 1);
+	    }
+	    else {
+		/* total sample area */
+		area++;
+	    }
+
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j] == 0)) {
+		G_set_f_null_value(&supCell, 1);
+	    }
+
+	    if (G_is_f_null_value(&corrCell)) {
+		if (!G_is_f_null_value(&precCell))
+		    pst[pid_corr[j - 1]].edges++;
+		if (!G_is_f_null_value(&supCell))
+		    pst[pid_sup[j]].edges++;
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+
+	    if (!G_is_f_null_value(&precCell) && corrCell == precCell) {
+		pid_corr[j] = pid_corr[j - 1];
+		connected = 1;
+		pst[pid_corr[j]].cells++;
+	    }
+	    else {
+		connected = 0;
+	    }
+
+	    if (!G_is_f_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j] != pid_sup[j]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
+
+		    old_pid = pid_corr[j];
+		    new_pid = pid_sup[j];
+		    pid_corr[j] = new_pid;
+		    if (old_pid > 0) {
+			/* merge */
+			/* update left side of the current row */
+			for (k = 0; k < j; k++) {
+			    if (pid_corr[k] == old_pid)
+				pid_corr[k] = new_pid;
+			}
+			/* update right side of the previous row */
+			for (k = j + 1; k < ad->cl; k++) {
+			    if (pid_sup[k] == old_pid)
+				pid_sup[k] = new_pid;
+			}
+			pst[new_pid].cells += pst[old_pid].cells;
+			pst[old_pid].cells = 0;
+			pst[new_pid].edges += pst[old_pid].edges;
+			pst[old_pid].edges = 0;
+			
+			if (old_pid == pid)
+			    pid--;
+		    }
+		    else {
+			pst[new_pid].cells++;
+		    }
+		}
+		connected = 1;
+	    }
+
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j] = pid;
+
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
+
+		    for (k = nalloc; k < pid + incr; k++) {
+			pst[k].cells = 0;
+			pst[k].edges = 0;
+		    }
+			
+		    nalloc = pid + incr;
+		}
+
+		pst[pid].cells = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
+	    }
+	    /* update edge count for corr */
+	    if (G_is_f_null_value(&precCell) || precCell != corrCell)
+		pst[pid_corr[j]].edges++;
+	    if (G_is_f_null_value(&supCell) || supCell != corrCell)
+		pst[pid_corr[j]].edges++;
+	    if (i == ad->rl - 1)
+		pst[pid_corr[j]].edges++;
+	    if (j == ad->cl - 1)
+		pst[pid_corr[j]].edges++;
+	    /* update edge count for prec */
+	    if (!G_is_f_null_value(&precCell) && precCell != corrCell)
+		pst[pid_corr[j - 1]].edges++;
+	    /* update edge count for sup */
+	    if (!G_is_f_null_value(&supCell) && supCell != corrCell)
+		pst[pid_sup[j]].edges++;
+
+	    precCell = corrCell;
+	}
+    }
+
+    if (npatch > 0) {
+	double edges, cells;
+
+	edges = cells = 0;
+	
+	for (i = 1; i <= pid; i++) {
+	    cells += pst[i].cells;
+	    edges += pst[i].edges;
+	}
+
+	*result = 0.25 * edges / sqrt(cells);
+    }
+    else {
+	G_set_d_null_value(result, 1);
+    }
+
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
+	G_free(mask_sup);
+    }
+    G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
+
+    return RLI_OK;
+}

Modified: grass/branches/releasebranch_6_4/raster/r.li/r.li.simpson/simpson.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.li/r.li.simpson/simpson.c	2014-03-24 11:40:14 UTC (rev 59304)
+++ grass/branches/releasebranch_6_4/raster/r.li/r.li.simpson/simpson.c	2014-03-24 11:43:14 UTC (rev 59305)
@@ -22,16 +22,16 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#include "../r.li.daemon/defs.h"
+#include "../r.li.daemon/daemon.h"
 #include "../r.li.daemon/avlDefs.h"
 #include "../r.li.daemon/avl.h"
-#include "../r.li.daemon/daemon.h"
 
 /* template is shannon */
 
-double calculate(struct area_entry *ad, int fd, double *result);
-double calculateD(struct area_entry *ad, int fd, double *result);
-double calculateF(struct area_entry *ad, int fd, double *result);
+rli_func simpson;
+int calculate(int fd, struct area_entry *ad, double *result);
+int calculateD(int fd, struct area_entry *ad, double *result);
+int calculateF(int fd, struct area_entry *ad, double *result);
 
 int main(int argc, char *argv[])
 {
@@ -49,7 +49,7 @@
 
     raster = G_define_standard_option(G_OPT_R_MAP);
 
-    conf = G_define_option();
+    conf = G_define_standard_option(G_OPT_F_INPUT);
     conf->key = "conf";
     conf->description = _("Configuration file");
     conf->required = YES;
@@ -63,6 +63,7 @@
 			  output->answer);
 }
 
+
 int simpson(int fd, char **par, struct area_entry *ad, double *result)
 {
     char *mapset;
@@ -74,20 +75,21 @@
     if (G_get_cellhd(ad->raster, mapset, &hd) == -1)
 	return RLI_ERRORE;
 
+
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
-	    ris = calculate(ad, fd, &indice);
+	    ris = calculate(fd, ad, &indice);
 	    break;
 	}
     case DCELL_TYPE:
 	{
-	    ris = calculateD(ad, fd, &indice);
+	    ris = calculateD(fd, ad, &indice);
 	    break;
 	}
     case FCELL_TYPE:
 	{
-	    ris = calculateF(ad, fd, &indice);
+	    ris = calculateF(fd, ad, &indice);
 	    break;
 	}
     default:
@@ -97,8 +99,9 @@
 	}
     }
 
-    if (ris != RLI_OK)
+    if (ris != RLI_OK) {
 	return RLI_ERRORE;
+    }
 
     *result = indice;
 
@@ -106,28 +109,23 @@
 }
 
 
-double calculate(struct area_entry *ad, int fd, double *result)
+int calculate(int fd, struct area_entry *ad, double *result)
 {
     CELL *buf;
     CELL corrCell;
     CELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double p = 0;
-    double area = 0;
-    double t;
+    long area = 0;
 
     avl_tree albero = NULL;
     AVL_table *array;
@@ -148,8 +146,6 @@
     }
 
     G_set_c_null_value(&precCell, 1);
-
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -159,70 +155,70 @@
 	}
 
 	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
 	    corrCell = buf[i + ad->x];
 
-	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			uc.val.c = precCell;
-			albero = avl_make(uc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			else
+		    case AVL_ADD:
+			{
 			    m++;
-		    }
-		    else {
-			uc.val.c = precCell;
-			ris = avl_add(&albero, uc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
-		}		/* endif not equal cells */
-		else {		/*equal cells */
-
-		    totCorr++;
 		}
-		precCell = corrCell;
-	    }
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.c = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -258,63 +254,64 @@
 	    }
 	}
     }
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
 
-    /* calculate index summary */
-    for (i = 0; i < m; i++) {
-	t = (double)(array[i]->tot);
-	p = t / area;
-	somma = somma + (p * p);
-    }
+    if (area > 0) {
+	double t;
+	double p;
+	double simpson;
 
-    if (a != 0) {
-	indice = 1 - somma;
-    }
-    else			/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
+	/* calculate simpson */
+	simpson = 0;
+	for (i = 0; i < m; i++) {
+	    t = (double)(array[i]->tot);
+	    p = t / area;
+	    simpson += (p * p);
+	}
+	G_free(array);
 
-    G_free(array);
-    if (masked)
+	*result = 1 - simpson;
+    }
+    else
+	G_set_d_null_value(result, 1);
+
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
-    *result = indice;
-
     return RLI_OK;
 }
 
 
-double calculateD(struct area_entry *ad, int fd, double *result)
+int calculateD(int fd, struct area_entry *ad, double *result)
 {
     DCELL *buf;
     DCELL corrCell;
     DCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double p = 0;
-    double area = 0;
-    double t;
+    long area = 0;
 
     avl_tree albero = NULL;
     AVL_table *array;
@@ -328,14 +325,13 @@
 	    return RLI_ERRORE;
 	mask_buf = G_malloc(ad->cl * sizeof(int));
 	if (mask_buf == NULL) {
-	    G_fatal_error("malloc mask_buffailed");
+	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
 	}
 	masked = TRUE;
     }
 
     G_set_d_null_value(&precCell, 1);
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -346,71 +342,69 @@
 
 	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
+		/* total patch area */
+		area++;
+	    }
 
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			uc.val.dc = precCell;
-			albero = avl_make(uc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			uc.val.dc = precCell;
-			ris = avl_add(&albero, uc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
-		}		/* endif not equal dcells */
-		else {		/*equal dcells */
-
-		    totCorr++;
 		}
-		precCell = corrCell;
-	    }
-
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.dc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -446,66 +440,67 @@
 	    }
 	}
     }
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
 
-    /* claculate index summary */
-    for (i = 0; i < m; i++) {
-	t = (double)(array[i]->tot);
-	p = t / area;
-	somma = somma + (p * p);
-    }
+    if (area > 0) {
+	double t;
+	double p;
+	double simpson;
 
-    if (a != 0) {		/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = 1 - somma;
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
+
+	/* calculate simpson */
+	simpson = 0;
+	for (i = 0; i < m; i++) {
+	    t = (double)(array[i]->tot);
+	    p = t / area;
+	    simpson += (p * p);
+	}
+	G_free(array);
+
+	*result = 1 - simpson;
     }
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-    G_free(array);
-    if (masked)
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+    }
 
-    *result = indice;
     return RLI_OK;
 }
 
 
-double calculateF(struct area_entry *ad, int fd, double *result)
+int calculateF(int fd, struct area_entry *ad, double *result)
 {
     FCELL *buf;
     FCELL corrCell;
     FCELL precCell;
 
     int i, j;
-    int mask_fd = -1, *mask_buf;
+    int mask_fd = -1, *mask_buf = NULL;
     int ris = 0;
     int masked = FALSE;
-    int a = 0;			/* a=0 if all cells are null */
 
     long m = 0;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double p = 0;
-    double area = 0;
-    double t;
+    long area = 0;
 
     avl_tree albero = NULL;
-
     AVL_table *array;
-
     generic_cell uc;
 
     uc.t = FCELL_TYPE;
@@ -523,7 +518,6 @@
     }
 
     G_set_f_null_value(&precCell, 1);
-
     for (j = 0; j < ad->rl; j++) {	/* for each row */
 	if (masked) {
 	    if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
@@ -534,69 +528,69 @@
 
 	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each fcell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
-	    if (masked && mask_buf[i + ad->x] == 0) {
+	    if ((masked) && (mask_buf[i] == 0)) {
 		G_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(G_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (G_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+		/* total patch area */
+		area++;
+	    }
+
+	    if (!(G_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(G_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
+		if (albero == NULL) {
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
-			uc.val.fc = precCell;
-			albero = avl_make(uc, totCorr);
-			if (albero == NULL) {
-			    G_fatal_error("avl_make error");
+			G_fatal_error("avl_make error");
+			return RLI_ERRORE;
+		    }
+		    m++;
+		}
+		else {
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
+		    switch (ris) {
+		    case AVL_ERR:
+			{
+			    G_fatal_error("avl_add error");
 			    return RLI_ERRORE;
 			}
-			m++;
-		    }
-		    else {
-			uc.val.fc = precCell;
-			ris = avl_add(&albero, uc, totCorr);
-			switch (ris) {
-			case AVL_ERR:
-			    {
-				G_fatal_error("avl_add error");
-				return RLI_ERRORE;
-			    }
-			case AVL_ADD:
-			    {
-				m++;
-				break;
-			    }
-			case AVL_PRES:
-			    {
-				break;
-			    }
-			default:
-			    {
-				G_fatal_error("avl_make unknown error");
-				return RLI_ERRORE;
-			    }
+		    case AVL_ADD:
+			{
+			    m++;
+			    break;
 			}
+		    case AVL_PRES:
+			{
+			    break;
+			}
+		    default:
+			{
+			    G_fatal_error("avl_make unknown error");
+			    return RLI_ERRORE;
+			}
 		    }
-		    totCorr = 1;
-		}		/* endif not equal fcells */
-		else {		/*equal fcells */
-
-		    totCorr++;
 		}
-		precCell = corrCell;
-	    }
-
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
 	}
     }
 
-    /*last closing */
-    if (a != 0) {
+    /* last closing */
+    if (area > 0 && !(G_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.fc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -633,37 +627,41 @@
 	}
     }
 
-    array = G_malloc(m * sizeof(AVL_tableRow));
-    if (array == NULL) {
-	G_fatal_error("malloc array failed");
-	return RLI_ERRORE;
-    }
-    tot = avl_to_array(albero, zero, array);
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+    if (area > 0) {
+	double t;
+	double p;
+	double simpson;
 
-    /* calculate index summary */
-    for (i = 0; i < m; i++) {
-	t = (double)(array[i]->tot);
-	p = t / area;
-	somma = somma + (p * p);
-    }
+	array = G_malloc(m * sizeof(AVL_tableRow));
+	if (array == NULL) {
+	    G_fatal_error("malloc array failed");
+	    return RLI_ERRORE;
+	}
+	tot = avl_to_array(albero, zero, array);
+	if (tot != m) {
+	    G_warning("avl_to_array unexpected value. the result could be wrong");
+	    return RLI_ERRORE;
+	}
 
-    if (a != 0) {		/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = 1 - somma;
+	/* calculate simpson */
+	simpson = 0;
+	for (i = 0; i < m; i++) {
+	    t = (double)(array[i]->tot);
+	    p = t / area;
+	    simpson += (p * p);
+	}
+	G_free(array);
+
+	*result = 1 - simpson;
     }
     else
-	indice = (double)(-1);
+	G_set_d_null_value(result, 1);
 
-
-    G_free(array);
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
 
-    *result = indice;
     return RLI_OK;
 }



More information about the grass-commit mailing list