[GRASS-SVN] r59072 - in grass/trunk/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 Feb 17 02:05:22 PST 2014


Author: mmetz
Date: 2014-02-17 02:05:22 -0800 (Mon, 17 Feb 2014)
New Revision: 59072

Modified:
   grass/trunk/raster/r.li/r.li.cwed/cwed.c
   grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html
   grass/trunk/raster/r.li/r.li.daemon/daemon.c
   grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html
   grass/trunk/raster/r.li/r.li.dominance/dominance.c
   grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html
   grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c
   grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html
   grass/trunk/raster/r.li/r.li.mpa/mpa.c
   grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html
   grass/trunk/raster/r.li/r.li.mps/mps.c
   grass/trunk/raster/r.li/r.li.mps/r.li.mps.html
   grass/trunk/raster/r.li/r.li.padcv/padcv.c
   grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html
   grass/trunk/raster/r.li/r.li.padrange/padrange.c
   grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html
   grass/trunk/raster/r.li/r.li.padsd/padsd.c
   grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html
   grass/trunk/raster/r.li/r.li.patchdensity/main.c
   grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html
   grass/trunk/raster/r.li/r.li.patchnum/main.c
   grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html
   grass/trunk/raster/r.li/r.li.pielou/pielou.c
   grass/trunk/raster/r.li/r.li.renyi/renyi.c
   grass/trunk/raster/r.li/r.li.richness/richness.c
   grass/trunk/raster/r.li/r.li.shannon/shannon.c
   grass/trunk/raster/r.li/r.li.shape/main.c
   grass/trunk/raster/r.li/r.li.simpson/simpson.c
Log:
r.li overhaul

Modified: grass/trunk/raster/r.li/r.li.cwed/cwed.c
===================================================================
--- grass/trunk/raster/r.li/r.li.cwed/cwed.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.cwed/cwed.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -347,16 +347,16 @@
 	Rast_set_c_null_value(&prevCell, 1);
 	Rast_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--;
 		Rast_set_c_null_value(&corrCell, 1);
 	    }
 	    if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
+		area++;
+
 		supCell = buf_sup[i + ad->x];
+
 		/* calculate how many edges the cell has */
-
 		if (((!Rast_is_null_value(&prevCell, CELL_TYPE))) &&
 		    (corrCell != prevCell)) {
 		    int r = 0;
@@ -478,15 +478,15 @@
 	Rast_set_d_null_value(&prevCell, 1);
 	Rast_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) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 	    if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
+		area++;
 		supCell = buf_sup[i + ad->x];
-		/* calculate how many edge the cell has */
+
+		/* calculate how many edges the cell has */
 		if (((!Rast_is_null_value(&prevCell, DCELL_TYPE))) &&
 		    (corrCell != prevCell)) {
 		    int r = 0;
@@ -609,15 +609,16 @@
 	Rast_set_f_null_value(&prevCell, 1);
 	Rast_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) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 	    if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
+		area++;
+
 		supCell = buf_sup[i + ad->x];
 
+		/* calculate how many edges the cell has */
 		if (((!Rast_is_null_value(&prevCell, FCELL_TYPE))) &&
 		    (corrCell != prevCell)) {
 		    int r = 0;

Modified: grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html
===================================================================
--- grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.cwed/r.li.cwed.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -28,7 +28,7 @@
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
 <!-- TODO: verify next: -->
-If the input raster map contains only NULL values it is considered to
+If the sample area contains only NULL values it is considered to
 have 0 patch and CWED=0. If Area is 0 <em>r.li.cwed</em> returns -1.
 This is only possible if the map is masked.<br>
 If you want to change these -1 values to NULL, run subsequently on the resulting map:
@@ -67,7 +67,8 @@
 
 <h2>AUTHORS</h2>
 Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
 
 <p>
 <i>Last changed: $Date$</i></p>

Modified: grass/trunk/raster/r.li/r.li.daemon/daemon.c
===================================================================
--- grass/trunk/raster/r.li/r.li.daemon/daemon.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.daemon/daemon.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -565,7 +565,7 @@
 	char s[100];
 	int len;
 
-	sprintf(s, "RESULT %i|%f\n", m.f.f_d.aid, m.f.f_d.res);
+	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)

Modified: grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html
===================================================================
--- grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.daemon/r.li.daemon.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -87,7 +87,8 @@
 Claudio Porta and Lucio Davide Spano, students of Computer Science 
 University of Pisa (Italy).<br>
 Commission from Faunalia Pontedera (PI)<br>
-Rewritten from "r.le.setup" by William L. Baker
+Rewritten from "r.le.setup" by William L. Baker<br>
+Rewritten to produce correct results by Markus Metz<br>
 This program is free software under the GPL (>=v2)
 Read the COPYING file that comes with GRASS for details.
 

Modified: grass/trunk/raster/r.li/r.li.dominance/dominance.c
===================================================================
--- grass/trunk/raster/r.li/r.li.dominance/dominance.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.dominance/dominance.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,19 @@
-/*
- * \brief calculates dominance's diversity index
+/****************************************************************************
  *
- *   \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.dominance
+ * 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 dominance diversity 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/raster.h>
@@ -17,10 +23,9 @@
 #include <fcntl.h>
 #include <math.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 */
 
@@ -101,42 +106,31 @@
 {
     CELL *buf;
     CELL corrCell;
+    CELL precCell;
 
     int i, j;
     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 = 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;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
-	mask_buf = G_malloc(Rast_window_cols() * sizeof(int));
+	mask_buf = G_malloc(ad->cl * sizeof(int));
 	if (mask_buf == NULL) {
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
@@ -144,10 +138,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -155,31 +146,42 @@
 	    }
 	}
 
+	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+	Rast_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) {
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.c = corrCell;
-		    albero = avl_make(cc, 1);
-
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.c = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -197,56 +199,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
-	    }
-	}			/* end for */
-    }				/* end for */
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
 
     /*last closing */
-    if (a != 0 && albero != NULL) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	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;
+		}
+	    case AVL_ADD:
+		{
+		    m++;
+		    break;
+		}
+	    case AVL_PRES:
+		{
+		    break;
+		}
+	    default:
+		{
+		    G_fatal_error("avl_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
+    }
 
-	array = G_malloc(m * sizeof(AVL_tableRow *));
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
+	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");
+	    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);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }
@@ -256,37 +293,26 @@
 {
     DCELL *buf;
     DCELL corrCell;
+    DCELL precCell;
 
     int i, j;
     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 = 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 = DCELL_TYPE;
+    uc.t = DCELL_TYPE;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -299,10 +325,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -310,30 +333,42 @@
 	    }
 	}
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+	Rast_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) {
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.dc = corrCell;
-		    albero = avl_make(cc, 1);
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.dc = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -351,56 +386,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
+
+    /*last closing */
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	if (albero == NULL) {
+	    uc.val.dc = precCell;
+	    albero = avl_make(uc, totCorr);
+	    if (albero == NULL) {
+		G_fatal_error("avl_make error");
+		return RLI_ERRORE;
 	    }
-	}			/*close for */
-    }				/*close for */
+	    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_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
+    }
 
-    /*last closing */
-    if (a != 0 && albero != NULL) {
-	array = G_malloc(m * sizeof(AVL_tableRow *));
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
+	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");
+	    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);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }
@@ -410,37 +480,26 @@
 {
     FCELL *buf;
     FCELL corrCell;
+    FCELL precCell;
 
     int i, j;
     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 = 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 = FCELL_TYPE;
+    uc.t = FCELL_TYPE;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -453,10 +512,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -464,29 +520,42 @@
 	    }
 	}
 
-	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);
+	Rast_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) {
+
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.fc = corrCell;
-		    albero = avl_make(cc, 1);
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.fc = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -504,55 +573,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
+
+    /*last closing */
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	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++;
 	}
+	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_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
     }
 
-    /*last closing */
-    if (a != 0 && albero != NULL) {
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
 	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");
+	    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);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html
===================================================================
--- grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.dominance/r.li.dominance.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -18,13 +18,8 @@
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
 <!-- TODO: verify next: -->
-If the input raster map contains only NULL values then <em>r.li.dominance</em>
-returns -1.<br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+If the input raster map contains only NULL values then 
+<em>r.li.dominance</em> returns NULL.<br>
 
 <h2>EXAMPLES</h2>
 To calculate the dominance diversity index on map <em>my_map</em>, using
@@ -53,7 +48,8 @@
 
 <h2>AUTHORS</h2>
 Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
 
 <p>
 <i>Last changed: $Date$</i></p>

Modified: grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c
===================================================================
--- grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.edgedensity/edgedensity.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -116,7 +116,6 @@
 
 int calculate(int fd, struct area_entry *ad, char **valore, double *result)
 {
-    double indice = 0;
     double e = 0;
     double somma = 0;
     double area = 0;
@@ -204,9 +203,8 @@
 	    buf_inf = buf_null;
 	}
 
-	/*read mask if needed */
+	/* read mask if needed */
 	if (masked) {
-
 	    mask_tmp = mask_sup;
 	    mask_sup = mask_corr;
 	    mask_corr = mask_inf;
@@ -230,16 +228,15 @@
 	Rast_set_c_null_value(&prevCell, 1);
 	Rast_set_c_null_value(&corrCell, 1);
 
-	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
-	    area++;
+	for (i = 0; i < ad->cl; i++) {
 	    corrCell = buf_corr[i + ad->x];
 
 	    if (masked && mask_corr[i + ad->x] == 0) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
+		area++;
 		if ((i + 1) == ad->cl)	/*last cell of the row */
 		    Rast_set_c_null_value(&nextCell, 1);
 		else if (masked && mask_corr[i + 1 + ad->x] == 0)
@@ -258,7 +255,6 @@
 		    infCell = buf_inf[i + ad->x];
 
 		/* calculate how many edges the cell has */
-
 		if ((Rast_is_null_value(&prevCell, CELL_TYPE)) ||
 		    (corrCell != prevCell)) {
 		    bordoCorr++;
@@ -274,13 +270,12 @@
 		    bordoCorr++;
 		}
 
-
 		if ((Rast_is_null_value(&nextCell, CELL_TYPE)) ||
 		    (corrCell != nextCell)) {
 		    bordoCorr++;
 		}
 
-		/*store the result in the tree */
+		/* store the result in the tree */
 		if (albero == NULL) {
 		    c1.val.c = corrCell;
 		    albero = avl_make(c1, bordoCorr);
@@ -316,18 +311,14 @@
 			}
 		    }
 		}
-
 		bordoCorr = 0;
 	    }
-
 	    prevCell = corrCell;
 	}
     }
 
     /* calculate index */
-    if (area == 0)
-	indice = -1;
-    else {
+    if (area > 0) {
 	if (valore != NULL) {	/* only 1 class */
 	    char *sval;
 	    int val;
@@ -340,10 +331,8 @@
 	    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");
@@ -361,10 +350,11 @@
 	    G_free(array);
 	}
 
-	indice = somma * 10000 / area;
+	*result = somma * 10000 / area;
     }
+    else
+	Rast_set_d_null_value(result);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_inf);
@@ -380,7 +370,6 @@
 
 int calculateD(int fd, struct area_entry *ad, char **valore, double *result)
 {
-    double indice = 0;
     double e = 0;
     double somma = 0;
     double area = 0;
@@ -472,7 +461,7 @@
 	    buf_inf = buf_null;
 	}
 
-	/*read mask if needed */
+	/* read mask if needed */
 	if (masked) {
 
 	    mask_tmp = mask_sup;
@@ -499,17 +488,14 @@
 	Rast_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) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
-
+		area++;
 		if ((i + 1) == ad->cl)	/*last cell of the row */
 		    Rast_set_d_null_value(&nextCell, 1);
 		else if (masked && mask_corr[i + 1 + ad->x] == 0)
@@ -549,7 +535,7 @@
 		    bordoCorr++;
 		}
 
-		/*store the result in the tree */
+		/* store the result in the tree */
 		if (albero == NULL) {
 		    c1.val.dc = corrCell;
 		    albero = avl_make(c1, bordoCorr);
@@ -585,19 +571,14 @@
 			}
 		    }
 		}
-
 		bordoCorr = 0;
-
 	    }
-
 	    prevCell = corrCell;
 	}
     }
 
     /* calculate index */
-    if (area == 0)
-	indice = -1;
-    else {
+    if (area > 0) {
 	if (valore != NULL) {	/* only 1 class */
 	    char *sval;
 	    double val;
@@ -628,10 +609,11 @@
 	    }
 	    G_free(array);
 	}
-	indice = somma * 10000 / area;
+	*result = somma * 10000 / area;
     }
+    else
+	Rast_set_d_null_value(result);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_inf);
@@ -647,7 +629,6 @@
 
 int calculateF(int fd, struct area_entry *ad, char **valore, double *result)
 {
-    double indice = 0;
     double e = 0;
     double somma = 0;
     double area = 0;
@@ -731,16 +712,14 @@
 	    buf_sup = RLI_get_fcell_raster_row(fd, j - 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 = buf_null;
 	}
 
-	/*read mask if needed */
+	/* read mask if needed */
 	if (masked) {
-
 	    mask_tmp = mask_sup;
 	    mask_sup = mask_corr;
 	    mask_corr = mask_inf;
@@ -765,16 +744,14 @@
 	Rast_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) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
-
+		area++;
 		if ((i + 1) == ad->cl)	/*last cell of the row */
 		    Rast_set_f_null_value(&nextCell, 1);
 		else if (masked && mask_corr[i + 1 + ad->x] == 0)
@@ -792,8 +769,7 @@
 		else
 		    infCell = buf_inf[i + ad->x];
 
-		/* calculate how many edge the cell has */
-
+		/* calculate how many edges the cell has */
 		if ((Rast_is_null_value(&prevCell, FCELL_TYPE)) ||
 		    (corrCell != prevCell)) {
 		    bordoCorr++;
@@ -814,9 +790,9 @@
 		    bordoCorr++;
 		}
 
-		/*store the result in the tree */
+		/* store the result in the tree */
 		if (albero == NULL) {
-		    c1.val.c = corrCell;
+		    c1.val.fc = corrCell;
 		    albero = avl_make(c1, bordoCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
@@ -825,7 +801,7 @@
 		    m++;
 		}
 		else {
-		    c1.val.c = corrCell;
+		    c1.val.fc = corrCell;
 		    ris = avl_add(&albero, c1, bordoCorr);
 
 		    switch (ris) {
@@ -850,19 +826,14 @@
 			}
 		    }
 		}
-
 		bordoCorr = 0;
-
 	    }
-
 	    prevCell = corrCell;
 	}
     }
 
     /* calculate index */
-    if (area == 0)
-	indice = -1;
-    else {
+    if (area > 0) {
 	if (valore != NULL) {	/* only 1 class */
 	    char *sval;
 	    float val;
@@ -894,10 +865,11 @@
 	    }
 	    G_free(array);
 	}
-	indice = somma * 10000 / area;
+	*result = somma * 10000 / area;
     }
+    else
+	Rast_set_d_null_value(result);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_inf);

Modified: grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html
===================================================================
--- grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.edgedensity/r.li.edgedensity.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -3,10 +3,11 @@
 <em>r.li.edgedensity </em>calculates:<br>
 <br>
 <ul>
-   <li> the density of all the edge of patch i
+   <li> the density of all edges of patch type <em>k</em>
 	<img alt="rliEdgeDensity formula1" src="rliEdgeDensity_formula1.png">
 	, or
-   <li> the density of all the edge in the sampling area if i isn't specified,
+   <li> the density of all edges in the sampling area if <em>k</em> is 
+        not specified,
 	<img alt="rliEdgeDensity formula2" src="rliEdgeDensity_formula2.png">
 </ul>
 <p>with:
@@ -14,7 +15,8 @@
 <li><b>k</b>: patch type</li>
 <li><b>m</b>: number of patch types</li>
 <li><b>n</b>: number of edge segments of patch type k</li>
-<li><b>e<small><small>ik </small></small></b>:total length of edge in landscape involving patch type k</li>
+<li><b>e<small><small>ik </small></small></b>:total edge length in 
+the landscape involving patch type k</li>
 <li> <b>Area</b>: total landscape area</li>
 </ul>
 
@@ -70,7 +72,8 @@
 
 <h2>AUTHORS</h2>
 Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
 
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.li/r.li.mpa/mpa.c
===================================================================
--- grass/trunk/raster/r.li/r.li.mpa/mpa.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mpa/mpa.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -106,7 +106,6 @@
     int masked = FALSE;
 
     double area = 0;
-    double indice = 0;
     double somma = 0;
 
     /* open mask if needed */
@@ -123,44 +122,41 @@
 	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++;
+	for (i = 0; i < ad->cl; i++) {
 	    if (masked && mask_buf[i + ad->x] == 0) {
 		Rast_set_c_null_value(&buf[i + ad->x], 1);
-		area--;
 	    }
-	    if (!(Rast_is_null_value(&buf[i + ad->x], CELL_TYPE))) {	/*if it's a cell to consider */
+	    if (!(Rast_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;
+	Rast_set_d_null_value(result);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
+
     return RLI_OK;
 }
 
+
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
     DCELL *buf;
@@ -170,7 +166,6 @@
     int masked = FALSE;
 
     double area = 0;
-    double indice = 0;
     double somma = 0;
 
     /* open mask if needed */
@@ -187,39 +182,37 @@
 	masked = TRUE;
     }
 
-    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 */
+    for (j = 0; j < ad->rl; j++) {
+	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
 
-	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 + ad->x] == 0) {
 		Rast_set_d_null_value(&buf[i + ad->x], 1);
 	    }
-	    if (!(Rast_is_null_value(&buf[i + ad->x], DCELL_TYPE))) {
+	    if (!(Rast_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;
+	Rast_set_d_null_value(result);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
+
     return RLI_OK;
 }
 
@@ -232,7 +225,6 @@
     int masked = FALSE;
 
     double area = 0;
-    double indice = 0;
     double somma = 0;
 
     /* open mask if needed */
@@ -249,39 +241,36 @@
 	masked = TRUE;
     }
 
-    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 */
+    for (j = 0; j < ad->rl; j++) {
+	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
 
-	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 + ad->x] == 0) {
 		Rast_set_f_null_value(&buf[i + ad->x], 1);
 	    }
-	    if (!(Rast_is_null_value(&buf[i + ad->x], FCELL_TYPE))) {
+	    if (!(Rast_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;
+	Rast_set_d_null_value(result);
 
-    *result = indice;
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
+
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html
===================================================================
--- grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mpa/r.li.mpa.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -56,7 +56,8 @@
 
 <h2>AUTHORS</h2>
 Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)<br>
+Markus Metz
 
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.li/r.li.mps/mps.c
===================================================================
--- grass/trunk/raster/r.li/r.li.mps/mps.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mps/mps.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,20 @@
-/*
- * \brief calculates mean patch size index
+/****************************************************************************
  *
- *  \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.patchnum
+ * 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
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
+ * PURPOSE:      calculates mean patch size 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 <stdlib.h>
 #include <fcntl.h>
@@ -17,16 +24,21 @@
 #include <grass/raster.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;
+};
 
+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,24 +74,21 @@
 {
     int ris = 0;
     double indice = 0;
-    struct Cell_head hd;
 
-    Rast_get_cellhd(ad->raster, "", &hd);
-
     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:
@@ -98,39 +107,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, *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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    int ris = 0;
-    int masked = FALSE;
+    buf_null = Rast_allocate_c_buf();
+    Rast_set_c_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
 
-    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;
-    long *ltmp;
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
 
-    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;
+    for (j = 0; j < Rast_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
 
-    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;
@@ -139,289 +147,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_null = Rast_allocate_c_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
-
-    /*the first time buf_sup is all null */
-    Rast_set_c_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_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;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	Rast_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 + ad->x] == 0)) {
 		Rast_set_c_null_value(&corrCell, 1);
 	    }
 
-	    /*valid cell */
-	    if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
-		area++;
+	    if (Rast_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_c_null_value(&supCell, 1);
+	    }
 
-		supCell = buf_sup[i + ad->x];
+	    if (!Rast_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) {
-		    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 (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
 
-			    }
-			    else {	/* tree not null */
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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];
-
-			    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 + 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;
 			}
-
-			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 + ad->x] == old_pid)
+				pid_sup[k + ad->x] = 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;
+	    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));
+
+		    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;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    if (area != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, uno);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
-	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);
@@ -432,60 +307,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) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-
-    G_free(mask_patch_corr);
-    G_free(mask_patch_sup);
     G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    avlID_destroy(albero);
-
     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, *buf_sup, *buf_null;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    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 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;
-    avlID_table *array;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_d_buf();
+    Rast_set_d_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -494,289 +370,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_null = Rast_allocate_d_buf();
-
-    /*the first time buf_sup is all null */
-    Rast_set_d_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_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;
+
 	Rast_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 + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
-		area++;
+	    if (Rast_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&supCell, 1);
+	    }
 
-		supCell = buf_sup[i + ad->x];
+	    if (!Rast_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) {
-		    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 (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
 
-			    }
-			    else {	/* tree not null */
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 + 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;
 			}
-
-			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 + ad->x] == old_pid)
+				pid_sup[k + ad->x] = 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 {
+			pst[new_pid].count++;
+		    }
 		}
-		else {		/*current cell and previous cell are equals */
+		connected = 1;
+	    }
 
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-		    if ((corrCell == supCell) &&
-			(mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			int l;
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-			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;
-		    }
-
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
 		}
-	    }
-	    else {		/*cell null or not to consider */
 
-		mask_patch_corr[i] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
 	    precCell = corrCell;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
 
-    if (area != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, uno);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
-	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 (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);
@@ -787,65 +530,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) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-
-    G_free(mask_patch_corr);
-    G_free(mask_patch_sup);
     G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    avlID_destroy(albero);
-
     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, *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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    int ris = 0;
-    int masked = FALSE;
+    buf_null = Rast_allocate_f_buf();
+    Rast_set_f_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
 
-    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;
-    long *ltmp;
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
 
-    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;
+    for (j = 0; j < Rast_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
 
-    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;
@@ -854,284 +593,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_null = Rast_allocate_f_buf();
-
-    /*the first time buf_sup is all null */
-    Rast_set_f_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_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;
+
 	Rast_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 + ad->x] = 0;
+	    
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
 	    }
-	    if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
-		area++;
 
-		supCell = buf_sup[i + ad->x];
+	    if (Rast_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_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 (!Rast_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 */
+	    if (!Rast_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 + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 + 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;
 			}
-
-			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 + ad->x] == old_pid)
+				pid_sup[k + ad->x] = 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 {
+			pst[new_pid].count++;
+		    }
 		}
-		else {		/*current cell and previous cell are equal */
+		connected = 1;
+	    }
 
-		    if ((corrCell == supCell) &&
-			(mask_patch_sup[i] != mask_patch_corr[i - 1])) {
-			int l;
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-			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;
-		    }
+		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;
 		}
-	    }
-	    else {		/*null cell or cell not to consider */
 
-		mask_patch_corr[i] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
 	    precCell = corrCell;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    if (area != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, uno);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
-	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);
@@ -1142,26 +753,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;
+    }
 
-    *result = indice;
-
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-
-    G_free(mask_patch_corr);
-    G_free(mask_patch_sup);
     G_free(buf_null);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    avlID_destroy(albero);
-
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.mps/r.li.mps.html
===================================================================
--- grass/trunk/raster/r.li/r.li.mps/r.li.mps.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.mps/r.li.mps.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,7 +1,7 @@
 <h2>DESCRIPTION</h2>
 
-<em>r.li.mps</em> (mean patch size) calculates the mean size of the patches
-in the sampling area as:<br>
+<em>r.li.mps</em> (mean patch size) calculates the mean size of the 
+patches in the sampling area as:<br>
 <img src="rlimps_formula.png" alt="rliMps formula"><br>
 
 with:
@@ -10,6 +10,12 @@
   <li><b>Npatch</b>: number of patches</li>
 </ul>
 
+The unit of the mean size is hectare.
+
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells 
+are ignored when tracing a patch.
+
 <h2>NOTES</h2>
 
 Do not use absolute path names for the <b>output</b> map/file.
@@ -17,14 +23,8 @@
 output will be a raster map, otherwise an ASCII file will be generated in
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
-<!-- TODO: verify next: -->
-If the input raster contains NULL value cells, <em>r.li.mps</em>
-returns 0 for these cells. <br>
-If you want to change these 0 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=0 input=my_map
-</pre></div>
-after index calculation.
+If the sample area contains only NULL value cells, <em>r.li.mps</em>
+returns 0 (zero). <br>
 
 <h2>EXAMPLES</h2>
 To calculate mean path size index on map <em>my_map</em>, using
@@ -52,8 +52,8 @@
 Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
 
 <h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
 
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.li/r.li.padcv/padcv.c
===================================================================
--- grass/trunk/raster/r.li/r.li.padcv/padcv.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padcv/padcv.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,21 @@
-/*
- * \brief calculates coefficient of variation of patch area 
+/****************************************************************************
  *
- *   \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.padcv
+ * AUTHOR(S):    Serena Pallecchi (original contributor)
+ *                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
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
+ * PURPOSE:      calculates coefficient of variation of patch areas
+ * 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 <stdlib.h>
 #include <fcntl.h>
@@ -17,12 +25,17 @@
 #include <grass/raster.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;
+};
+
 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);
@@ -94,41 +107,39 @@
     return RLI_OK;
 }
 
+
 int calculate(int fd, struct area_entry *ad, double *result)
 {
     CELL *buf, *buf_sup, *buf_null;
-    CELL corrCell;
-    CELL precCell;
-    CELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    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 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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_c_buf();
+    Rast_set_c_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -137,366 +148,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;
-    }
-    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_null = Rast_allocate_c_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_c_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 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;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	Rast_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 + ad->x] == 0)) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
 
-		supCell = buf_sup[i + ad->x];
+	    if (Rast_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_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;
-			}
-			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;
-			}
-		    }
-		    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++;
-			}
-			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;
-				}
-			    }
-			}
+	    if (!Rast_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;
+	    }
 
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
-		    }
-		}
-		else {		/*current cell and previuos cell are equal */
-		    /*        ?
-		     *      1 1
-		     */
+	    if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
 
-		    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];
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
 
-			    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));
+
+		    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;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+    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;
 
-	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;
+	/* 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);
 
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
+
+	/* 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);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }
 
+
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
-    DCELL *buf , *buf_sup, *buf_null;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_d_buf();
+    Rast_set_d_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -505,367 +391,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;
-    }
-    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_null = Rast_allocate_d_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_d_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 each raster row */
-    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;
+
 	Rast_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 + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
 
-		supCell = buf_sup[i + ad->x];
+	    if (Rast_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&supCell, 1);
+	    }
 
-		if (corrCell != precCell) {
-		    /*        ?
-		     *      1 2
-		     * */
-		    if (corrCell != supCell) {
+	    if (!Rast_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;
+	    }
 
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
+	    if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 {
-			    /*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;
-			}
 		    }
-		    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++;
-			}
-			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));
+
+		    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;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+    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;
 
-	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;
+	/* 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);
 
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
+
+	/* 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);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }
 
+
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
     FCELL *buf, *buf_sup, *buf_null;
-    FCELL corrCell;
-    FCELL precCell;
-    FCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    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 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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_f_buf();
+    Rast_set_f_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -874,331 +634,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;
-    }
-    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_null = Rast_allocate_f_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_f_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 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;
+
 	Rast_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 + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
-		if (i > 0)
-		    precCell = buf[i - 1 + ad->x];
-		if (j == 0)
-		    Rast_set_f_null_value(&supCell, 1);
 
-		else
-		    supCell = buf_sup[i + ad->x];
+	    if (Rast_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_f_null_value(&supCell, 1);
+	    }
 
-		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;
-			}
-			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;
-			}
-		    }
-		    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++;
-			}
-			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;
-				}
-			    }
-			}
+	    if (!Rast_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;
+	    }
 
-			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];
+	    if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
 
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
 
-			    /*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));
+
+		    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;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    if (areaPatch != 0) {
-	if (albero == NULL) {
-	    albero = avlID_make(idCorr, totCorr);
-	    if (albero == NULL) {
-		G_fatal_error("avlID_make error");
-		return RLI_ERRORE;
-	    }
-	    npatch++;
-	}
+    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;
 
-	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;
+	/* 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);
 
-	/* calculate summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    double diff;
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	    if (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
+
+	/* 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);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html
===================================================================
--- grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padcv/r.li.padcv.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,7 +1,7 @@
 <h2>DESCRIPTION</h2>
 
-<em>r.li.padcv</em> (patch area distribution coefficient of variation) calculates
-as:<br>
+<em>r.li.padcv</em> calculates the coefficient of variation of patch 
+area sizes in hectares as:<br>
 <img src="rlipadcv_formula1.png" alt="rlipadcv formula"> <br>
 with:<br>
 <ul>
@@ -9,7 +9,7 @@
   <img src="rlipadcv_formula2.png">  </li>
   <li><b>MPS</b>: mean patch area size </li>
   <li><b>a<small><small>i</small></small></b>: area of patch i</li>
-  <li><b>N<small>patch</small></b>: number of patch</li>
+  <li><b>N<small>patch</small></b>: number of patches</li>
 </ul>
 
 <h2>NOTES</h2>
@@ -19,13 +19,7 @@
 output will be a raster map, otherwise an ASCII file will be generated in
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
-If input raster is not full of null values <em>r.li.padcv</em> returns a value >=0 that is PADcv. <br>
-If the input raster map contains only NULL values then <em>r.li.padcv</em> returns -1. <br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+The result is NULL if the sample area contains only NULL values.
 
 <h2>EXAMPLES</h2>
 To calculate patch area distribution coefficient of variation index on map <em>my_map</em>, using
@@ -53,8 +47,8 @@
 Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
 
 <h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
 
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.li/r.li.padrange/padrange.c
===================================================================
--- grass/trunk/raster/r.li/r.li.padrange/padrange.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padrange/padrange.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,28 +1,41 @@
-/*
- * \brief calculates range of patch area size
+/****************************************************************************
  *
- * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *          Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.padrange
+ * AUTHOR(S):    Serena Pallecchi (original contributor)
+ *                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
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
+ * PURPOSE:      calculates calculates standard deviation of patch areas
+ * 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/raster.h>
-#include <grass/glocale.h>
-
 #include <stdlib.h>
 #include <fcntl.h>
 #include <math.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 <grass/gis.h>
+#include <grass/raster.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;
+};
+
 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);
@@ -98,33 +111,35 @@
 int calculate(int fd, struct area_entry *ad, double *result)
 {
     CELL *buf, *buf_sup, *buf_null;
-    CELL corrCell;
-    CELL precCell;
-    CELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    double indice = 0;
-    double rk = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_c_buf();
+    Rast_set_c_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -133,325 +148,198 @@
 	    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_null = Rast_allocate_c_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
-
-    /*the first time buf_sup is all null */
-    Rast_set_c_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_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;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
 
 	Rast_set_c_null_value(&precCell, 1);
 
-	/* for each cell in the row */
-	for (i = 0; i < ad->cl; i++) {
-	    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 + ad->x] == 0)) {
 		Rast_set_c_null_value(&corrCell, 1);
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
+	    if (Rast_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_c_null_value(&supCell, 1);
+	    }
 
-		supCell = buf_sup[i + ad->x];
+	    if (!Rast_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) {
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {
-			    /*first found patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
+	    if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 {
-			    /*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;
-			}
 		    }
-		    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 {
+			pst[new_pid].count++;
+		    }
 		}
-		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];
+		connected = 1;
+	    }
 
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-			    /*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 {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
+		    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;
 	    }
-	    else {		/*cell is null or is not to consider */
-		mask_patch_corr[i] = 0;
-	    }
 	    precCell = corrCell;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    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;
-		}
-	    }
-	}
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_p;
+	double cell_size_m;
+	double min, max;
 
-	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);
+	/* 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 (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
 
-	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);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }
 
@@ -459,33 +347,35 @@
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
     DCELL *buf, *buf_sup, *buf_null;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    double indice = 0;
-    double rk = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_d_buf();
+    Rast_set_d_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -494,319 +384,203 @@
 	    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_null = Rast_allocate_d_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_d_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 (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;
+
 	Rast_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 + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
+	    if (Rast_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&supCell, 1);
+	    }
 
-		supCell = buf_sup[i + ad->x];
+	    if (!Rast_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) {
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first found patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
+	    if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 {
-			    /*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;
-			}
 		    }
-		    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 {
+			pst[new_pid].count++;
+		    }
 		}
-		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];
+		connected = 1;
+	    }
 
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-			    /*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 {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
 		}
-	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
 	    precCell = corrCell;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    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;
-		}
-	    }
-	}
+    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;
 
-	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);
+	/* 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 (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	for (i = 0; i < npatch; i++) {
-	    if (array[i]->tot != 0) {
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
 
-		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;
-		}
+	/* 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;
 	    }
 	}
-
-	rk = area_max - area_min;
-
-	indice = rk;
-
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
     else
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }
 
@@ -814,33 +588,35 @@
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
     FCELL *buf, *buf_sup, *buf_null;
-    FCELL corrCell;
-    FCELL precCell;
-    FCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    double indice = 0;
-    double rk = 0;
-    avlID_tree albero = NULL;
-    avlID_table *array = NULL;
-    generic_cell gc;
+    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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_f_buf();
+    Rast_set_f_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -849,318 +625,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;
-    }
-    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_null = Rast_allocate_f_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_f_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 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;
+
 	Rast_set_f_null_value(&precCell, 1);
 
-	/* for each fcell in the row */
-	for (i = 0; i < ad->cl; i++) {
-	    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 + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
+	    if (Rast_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_f_null_value(&supCell, 1);
+	    }
 
-		supCell = buf_sup[i + ad->x];
+	    if (!Rast_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) {
-			/*        3
-			 *      1 2
-			 * */
-			/*new patch */
-			if (idCorr == 0) {	/*first found patch */
-			    lastId = 1;
-			    idCorr = 1;
-			    totCorr = 1;
-			    mask_patch_corr[i] = idCorr;
+	    if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 {
-			    /*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;
-			}
 		    }
-		    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 {
+			pst[new_pid].count++;
+		    }
 		}
-		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];
+		connected = 1;
+	    }
 
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
+	    if (!connected) {
+		/* start new patch */
+		npatch++;
+		pid++;
+		pid_corr[j + ad->x] = pid;
 
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
+		if (pid >= nalloc) {
+		    pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
 
-			    /*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 {	/*current cell and upper cell are not equal */
-			/*        2
-			 *      1 1
-			 */
-			mask_patch_corr[i] = idCorr;
-		    }
-
-		    totCorr++;
+		    for (k = nalloc; k < pid + incr; k++)
+			pst[k].count = 0;
+			
+		    nalloc = pid + incr;
 		}
-	    }
-	    else {		/*cell is null or is not to consider */
 
-		mask_patch_corr[i] = 0;
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
 	    precCell = corrCell;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    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;
-		}
-	    }
-	}
+    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;
 
-	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);
+	/* 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 (tot != npatch) {
-	    G_warning
-		("avlID_to_array unaspected value. the result could be wrong");
-	    return RLI_ERRORE;
-	}
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
 
-	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;
-		}
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
+
+	/* 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;
 	    }
 	}
-
-	rk = area_max - area_min;
-
-	indice = rk;
-
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
     else
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html
===================================================================
--- grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padrange/r.li.padrange.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,7 +1,7 @@
 <h2>DESCRIPTION</h2>
 
-<em>r.li.padrange</em> (patch area distribution range) calculates
-as:<br>
+<em>r.li.padrange</em> calculates the range of patch area sizes in 
+hectares as:<br>
 <img src="rlipadrange_formula.png" alt="rlipadrange formula"> <br>
 with:<br>
 <ul>
@@ -9,6 +9,10 @@
   <li><b>a<small><small>min</small></small></b>: min patch area size</li>
 </ul>
 
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells 
+are ignored when tracing a patch.
+
 <h2>NOTES</h2>
 
 Do not use absolute path names for the <b>output</b> map/file.
@@ -16,14 +20,8 @@
 output will be a raster map, otherwise an ASCII file will be generated in
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
-<!-- TODO: verify next: -->
-If the input raster map contains only NULL values then <em>r.li.padrange</em>
-returns -1.<br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+If the sample area contains only NULL values then <em>r.li.padrange</em>
+returns NULL.<br>
 
 <h2>EXAMPLES</h2>
 To calculate range of patch area size index on map <em>my_map</em>, using
@@ -51,8 +49,8 @@
 Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
 
 <h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
 
 <p>
 <i>Last changed: $Date$</i></p>

Modified: grass/trunk/raster/r.li/r.li.padsd/padsd.c
===================================================================
--- grass/trunk/raster/r.li/r.li.padsd/padsd.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padsd/padsd.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,28 +1,41 @@
-/*
- * \brief calculates standard deviation of patch area
+/****************************************************************************
  *
- *   \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.padsd
+ * AUTHOR(S):    Serena Pallecchi (original contributor)
+ *                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
  *
- *   This program is free software under the GPL (>=v2)
- *   Read the COPYING file that comes with GRASS for details.
- *       
- */
+ * PURPOSE:      calculates calculates standard deviation of patch areas
+ * 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/raster.h>
-#include <grass/glocale.h>
-
 #include <stdlib.h>
 #include <fcntl.h>
 #include <math.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 <grass/gis.h>
+#include <grass/raster.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;
+};
+
 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);
@@ -93,40 +106,39 @@
     return RLI_OK;
 }
 
+
 int calculate(int fd, struct area_entry *ad, double *result)
 {
     CELL *buf, *buf_sup, *buf_null;
-    CELL corrCell;
-    CELL precCell;
-    CELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    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 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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_c_buf();
+    Rast_set_c_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -135,324 +147,203 @@
 	    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_null = Rast_allocate_c_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_c_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 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;
 	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
 	Rast_set_c_null_value(&precCell, 1);
-	/* for each cell in the row */
-	for (i = 0; i < ad->cl; i++) {
-	    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 + ad->x] == 0)) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
 
-		supCell = buf_sup[i + ad->x];
+	    if (Rast_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_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;
-			}
-			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;
-			}
-		    }
-		    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++;
-			}
-			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;
-				}
-			    }
-			}
+	    if (!Rast_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;
+	    }
 
-			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];
+	    if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
 
-			    r = avlID_sub(&albero, del);	/*r=number of cell of patch removed */
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
+		    if (connected) {
+			npatch--;
 
-			    if (r == 0) {
-				G_fatal_error("avlID_sub error");
-				return RLI_ERRORE;
-			    }
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
+		    }
 
-			    /*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));
+
+		    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;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    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;
-		}
-	    }
-	}
-	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;
+    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 summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    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 (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
+
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
+
+	/* 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);
-	indice = sd;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
     else
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }
 
@@ -460,37 +351,35 @@
 int calculateD(int fd, struct area_entry *ad, double *result)
 {
     DCELL *buf, *buf_sup, *buf_null;
-    DCELL corrCell;
-    DCELL precCell;
-    DCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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;
-    long *ltmp;
-    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 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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_d_buf();
+    Rast_set_d_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -499,362 +388,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;
-    }
-    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_null = Rast_allocate_d_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_d_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 each raster row */
-    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;
+
 	Rast_set_d_null_value(&precCell, 1);
-	/* for each dcell in the row */
-	for (i = 0; i < ad->cl; i++) {
-	    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 + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
 
-		supCell = buf_sup[i + ad->x];
+	    if (Rast_is_d_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&supCell, 1);
+	    }
 
-		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;
-			}
-			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;
-			}
-		    }
-		    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++;
-			}
-			else {	/*tree not null */
+	    if (!Rast_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;
+	    }
 
-			    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;
-				}
-			    }
-			}
+	    if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
 
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 {		/*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));
+
+		    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;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    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;
-		}
-	    }
-	}
-	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;
+    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 summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    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 (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
+
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
+
+	/* 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);
-	indice = sd;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
     else
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }
 
+
 int calculateF(int fd, struct area_entry *ad, double *result)
 {
     FCELL *buf, *buf_sup, *buf_null;
-    FCELL corrCell;
-    FCELL precCell;
-    FCELL supCell;
-    int i, j;
-    int mask_fd = -1, *mask_buf = NULL;
-    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 *ltmp;
-    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 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;
+    Rast_get_cellhd(ad->raster, "", &hd);
 
+    buf_null = Rast_allocate_f_buf();
+    Rast_set_f_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
@@ -863,324 +629,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;
-    }
-    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_null = Rast_allocate_f_buf();
-    if (buf_null == NULL) {
-	G_fatal_error("malloc buf_null failed");
-	return RLI_ERRORE;
-    }
+    /* calculate number of patches */
+    npatch = 0;
+    area = 0;
+    pid = 0;
 
-    /*the first time buf_sup is all null */
-    Rast_set_f_null_value(buf_null, Rast_window_cols());
-    buf_sup = buf_null;
-    buf = buf_null;
-
-    for (i = 0; i < ad->cl; i++) {
-	mask_patch_sup[i] = 0;
-	mask_patch_corr[i] = 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 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;
+
 	Rast_set_f_null_value(&precCell, 1);
-	/* for each fcell in the row */
-	for (i = 0; i < ad->cl; i++) {
-	    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 + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
-	    if (!(Rast_is_null_value(&corrCell, gc.t))) {
-		areaPatch++;
 
-		supCell = buf_sup[i + ad->x];
+	    if (Rast_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_f_null_value(&supCell, 1);
+	    }
 
-		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;
-			}
-			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;
-			}
-		    }
-		    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++;
-			}
-			else {	/*tree not null */
+	    if (!Rast_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;
+	    }
 
-			    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;
-				}
-			    }
-			}
+	    if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
 
-			idCorr = mask_patch_sup[i];
-			mask_patch_corr[i] = idCorr;
-			totCorr = 1;
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 {		/*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));
+
+		    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;
 	}
-	ltmp = mask_patch_sup;
-	mask_patch_sup = mask_patch_corr;
-	mask_patch_corr = ltmp;
     }
 
-    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;
-		}
-	    }
-	}
-	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;
+    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 summary */
-	for (i = 0; i < np; i++) {
-	    long areaPi = 0;
-	    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 (array[i]->tot != 0) {
-		ris = ris + array[i]->tot;
-		areaPi = (double)array[i]->tot;
-		diff = areaPi - mn;
-		somma = somma + (diff * diff);
+	cell_size_m = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	              (((NS_DIST1 + NS_DIST2) / 2) / hd.rows);
+	area_units = cell_size_m * area;
+
+	/* mean patch size in hectares */
+	mps = area_units / (npatch * 10000);
+
+	/* 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);
-	indice = sd;
-	G_free(array);
+	psd = sqrt(psd / npatch);
+	*result = psd;
     }
     else
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(mask_patch_sup);
-    G_free(mask_patch_corr);
     G_free(buf_null);
-    avlID_destroy(albero);
+    G_free(pid_corr);
+    G_free(pid_sup);
+    G_free(pst);
 
-    *result = indice;
-
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html
===================================================================
--- grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.padsd/r.li.padsd.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,14 +1,19 @@
 <h2>DESCRIPTION</h2>
 
-<em>r.li.padsd</em> (patch area distribution standard deviation) calculates as:<br>
+<em>r.li.padsd</em> calculates the standard deviation of patch 
+area sizes in hectares as:<br>
 <img src="rlipadsd_formula.png" alt="rlipadsd formula"> <br>
 with:<br>
 <ul>
   <li><b>MPS</b>: mean patch area size</li>
   <li><b>a<small><small>i</small></small></b>: area of patch i</li>
-  <li><b>N<small>patch</small></b>: number of patch</li>
+  <li><b>N<small>patch</small></b>: number of patches</li>
 </ul>
 
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells 
+are ignored when tracing a patch.
+
 <h2>NOTES</h2>
 
 Do not use absolute path names for the <b>output</b> map/file.
@@ -16,14 +21,7 @@
 output will be a raster map, otherwise an ASCII file will be generated in
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
-If input raster is not full of null values <em>r.li.padsd</em> returns a
-value >=0 that is PADsd. <br>
-If the input raster map contains only NULL values then <em>r.li.padsd</em> returns -1. <br>
-If you want to change these -1 values to NULL, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=-1 input=my_map
-</pre></div>
-after index calculation.
+The result is NULL if the sample area contains only NULL values.
 
 <h2>EXAMPLES</h2>
 To calculate patch area distribution standard deviation index on map <em>my_map</em>, using
@@ -50,8 +48,8 @@
 Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
 
 <h2>AUTHORS</h2>
-Serena Pallecchi student of Computer Science University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI), Italy (www.faunalia.it)
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
 
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.li/r.li.patchdensity/main.c
===================================================================
--- grass/trunk/raster/r.li/r.li.patchdensity/main.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchdensity/main.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -6,8 +6,11 @@
  *                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-2007 by the GRASS Development Team
+ * 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
@@ -21,7 +24,20 @@
 #include <grass/raster.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;
+};
+
+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;
@@ -46,168 +62,716 @@
 
     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, patch_density, NULL, raster->answer,
 			  output->answer);
-
 }
 
 
 int patch_density(int fd, char **par, struct area_entry *ad, double *result)
 {
-    CELL *buf, *sup, *cnull;
-    CELL pid, old_pid, *pid_curr, *pid_sup, *ctmp;
-    int count, i, j, k, connected, other_above;
+    int ris = RLI_OK;
+    double indice = 0;
+
+    switch (ad->data_type) {
+    case CELL_TYPE:
+	{
+	    calculate(fd, ad, &indice);
+	    break;
+	}
+    case DCELL_TYPE:
+	{
+	    calculateD(fd, ad, &indice);
+	    break;
+	}
+    case FCELL_TYPE:
+	{
+	    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;
-    int mask_fd, *mask_buf, null_count;
-    double area;
-    double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
 
     Rast_get_cellhd(ad->raster, "", &hd);
 
-    cnull = Rast_allocate_c_buf();
-    Rast_set_c_null_value(cnull, Rast_window_cols());
-    sup = cnull;
+    buf_null = Rast_allocate_c_buf();
+    Rast_set_c_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
 
     /* initialize patch ids */
-    pid_curr = Rast_allocate_c_buf();
-    Rast_set_c_null_value(pid_curr, Rast_window_cols());
-    pid_sup = Rast_allocate_c_buf();
-    Rast_set_c_null_value(pid_sup, Rast_window_cols());
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
 
+    for (j = 0; j < Rast_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
     mask_fd = -1;
-    mask_buf = NULL;
-    null_count = 0;
+    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;
+
+	masked = TRUE;
     }
 
-    /* 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);
-
     /* calculate number of patches */
-    count = 0;
-    connected = 0;
-    other_above = 0;
+    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) {
+
+	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 (j = 0; j < ad->cl; j++) {
-		if (mask_buf[j + ad->x] == 0) {
-		    Rast_set_c_null_value(&buf[j + ad->x], 1);
-		    null_count++;
+	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	Rast_set_c_null_value(&precCell, 1);
+
+	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 + ad->x] == 0)) {
+		Rast_set_c_null_value(&corrCell, 1);
+	    }
+
+	    if (Rast_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_c_null_value(&supCell, 1);
+	    }
+
+	    if (!Rast_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 (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 + 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;
+			}
+			/* 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 {
+			pst[new_pid].count++;
+		    }
 		}
+		connected = 1;
 	    }
+
+	    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));
+
+		    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 (npatch > 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) * (ad->rl * ad->cl);
+
+	*result = (npatch / area_units) * 1000000;
+    }
+    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);
+
+    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;
+
+    Rast_get_cellhd(ad->raster, "", &hd);
+
+    buf_null = Rast_allocate_d_buf();
+    Rast_set_d_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
+	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;
+	}
 	
-	ctmp = pid_sup;
-	pid_sup = pid_curr;
-	pid_curr = ctmp;
-	Rast_set_c_null_value(pid_curr, Rast_window_cols());
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
 
+	Rast_set_d_null_value(&precCell, 1);
+
 	connected = 0;
-	other_above = 1;
 	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
 	    
-	    if (Rast_is_null_value(&(buf[j + ad->x]), CELL_TYPE)) {
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&corrCell, 1);
+	    }
+
+	    if (Rast_is_d_null_value(&corrCell)) {
 		connected = 0;
-		other_above = 1;
+		precCell = corrCell;
 		continue;
 	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&supCell, 1);
+	    }
 
-	    if (sup[j + ad->x] == buf[j + ad->x]) {
-		
-		if (!connected) {
-		    pid_curr[j + ad->x] = pid_sup[j + ad->x];
-		}
-		
-		if (pid_curr[j + ad->x] != pid_sup[j + ad->x]) {
+	    if (!Rast_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 (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
 		    if (connected) {
-			count--;
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
 		    }
-		    if (other_above) {
-			pid_curr[j + ad->x] = pid_sup[j + ad->x];
-			for (k = j + ad->x - 1; k >= ad->x; k--) {
-			    if (buf[k] != buf[j + ad->x])
-				break;
-			    pid_curr[k] = pid_sup[j + ad->x];
+
+		    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;
 			}
+			/* 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 {
-			old_pid = pid_sup[j + ad->x];
-			pid_sup[j + ad->x] = pid_curr[j + ad->x];
+			pst[new_pid].count++;
+		    }
+		}
+		connected = 1;
+	    }
+
+	    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));
+
+		    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 (npatch > 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) * (ad->rl * ad->cl);
+
+	*result = (npatch / area_units) * 1000000;
+    }
+    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);
+
+    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;
+
+    Rast_get_cellhd(ad->raster, "", &hd);
+
+    buf_null = Rast_allocate_f_buf();
+    Rast_set_f_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
+	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_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;
+
+	Rast_set_f_null_value(&precCell, 1);
+
+	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 + ad->x] == 0)) {
+		Rast_set_f_null_value(&corrCell, 1);
+	    }
+
+	    if (Rast_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_f_null_value(&supCell, 1);
+	    }
+
+	    if (!Rast_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 (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 + 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;
+			}
+			/* 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] = pid_curr[j + ad->x];
-			    }
+			    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 {
+			pst[new_pid].count++;
+		    }
 		}
-
-		other_above = 0;
 		connected = 1;
 	    }
 
 	    if (!connected) {
-		count++;
+		/* start new patch */
+		npatch++;
 		pid++;
-		pid_curr[j + ad->x] = pid;
-	    }
+		pid_corr[j + ad->x] = pid;
 
-	    if (j < ad->cl - 1) {
-		if (buf[j + ad->x] == buf[j + 1 + ad->x]) {
-		    
-		    connected = 1;
-		    pid_curr[j + 1 + ad->x] = pid_curr[j + ad->x];
+		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;
 		}
-		else {
-		    other_above = 1;
-		    connected = 0;
-		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
     }
 
-    area = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
-	(((NS_DIST1 + NS_DIST2) / 2) / hd.rows) *
-	(ad->rl *ad->cl - null_count);
+    if (npatch > 0) {
+	double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
+	double area_units;
 
-    if (area != 0)
-	*result = (count / area) * 1000000;
-    else
-	Rast_set_d_null_value(result, 1);
+	/* 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 (ad->mask == 1) {
+	area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
+	    (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (ad->rl * ad->cl);
+
+	*result = (npatch / area_units) * 1000000;
+    }
+    else {
+	*result = 0;
+    }
+
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-
-    G_free(cnull);
-    G_free(pid_curr);
+    G_free(buf_null);
+    G_free(pid_corr);
     G_free(pid_sup);
+    G_free(pst);
 
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html
===================================================================
--- grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchdensity/r.li.patchdensity.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,11 +1,17 @@
 <h2>DESCRIPTION</h2>
 
-<em>r.li.patchdensity</em> calculates the "patch density index" as:
+<em>r.li.patchdensity</em> calculates the "patch density index", 
+the number of patches per square kilometer, as:
 <div class="code"><pre>
-f(sample_area) = (Patch_Number/Area) * 1000000
+PD = (Npatch / A) * 1000000
 </pre></div>
 
-that is the number of patches per 1,000,000 area units.
+with:
+<ul>
+  <li><b>A</b>:sampling area size</li>
+  <li><b>Npatch</b>: number of patches</li>
+</ul>
+
 <p>
 This index is calculated using a 4 neighbour algorithm, diagonal cells 
 are ignored when tracing a patch.
@@ -17,16 +23,8 @@
 output will be a raster map, otherwise an ASCII file will be generated in
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
-<!-- TODO: verify next: -->
-A map of NULL values is considered to have zero patches. <br>
-If the size of the sample area is 0, <em>r.li.patchdensity</em> returns 
-NULL. This is only possible if the raster is masked.<br>
-If you want to change these NULL values to some number, run subsequently 
-on the resulting map:
-<div class="code"><pre>
-r.null null=-1 input=my_out
-</pre></div>
-after index calculation.
+A sample area of only NULL values is considered to have zero patches, 
+that is, the result is always ≥ 0.
 
 <h2>EXAMPLES</h2>
 To calculate patch density index on map <em>my_map</em>, using
@@ -64,10 +62,8 @@
 Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
 
 <h2>AUTHORS</h2>
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
 
-Claudio Porta and Lucio Davide Spano, students of Computer Science 
-University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI) (www.faunalia.it)<br>
-
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.li/r.li.patchnum/main.c
===================================================================
--- grass/trunk/raster/r.li/r.li.patchnum/main.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchnum/main.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -6,9 +6,11 @@
  *                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-2007 by the GRASS Development Team
+ * 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
@@ -22,8 +24,20 @@
 #include <grass/raster.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;
+};
+
+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;
@@ -48,145 +62,649 @@
 
     output = G_define_standard_option(G_OPT_R_OUTPUT);
 
-
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
     return calculateIndex(conf->answer, patch_number, NULL, raster->answer,
 			  output->answer);
-
 }
 
 int patch_number(int fd, char **par, struct area_entry *ad, double *result)
 {
-    CELL *buf, *sup, *cnull;
-    CELL pid, old_pid, *pid_curr, *pid_sup, *ctmp;
-    int count, i, j, k, connected, other_above;
+    int ris = RLI_OK;
+    double indice = 0;
+
+    switch (ad->data_type) {
+    case CELL_TYPE:
+	{
+	    calculate(fd, ad, &indice);
+	    break;
+	}
+    case DCELL_TYPE:
+	{
+	    calculateD(fd, ad, &indice);
+	    break;
+	}
+    case FCELL_TYPE:
+	{
+	    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;
-    int mask_fd, *mask_buf, null_count;
 
     Rast_get_cellhd(ad->raster, "", &hd);
 
-    cnull = Rast_allocate_c_buf();
-    Rast_set_c_null_value(cnull, Rast_window_cols());
-    sup = cnull;
+    buf_null = Rast_allocate_c_buf();
+    Rast_set_c_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
 
     /* initialize patch ids */
-    pid_curr = Rast_allocate_c_buf();
-    Rast_set_c_null_value(pid_curr, Rast_window_cols());
-    pid_sup = Rast_allocate_c_buf();
-    Rast_set_c_null_value(pid_sup, Rast_window_cols());
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
 
+    for (j = 0; j < Rast_window_cols(); j++) {
+	pid_corr[j] = 0;
+	pid_sup[j] = 0;
+    }
+
     /* open mask if needed */
     mask_fd = -1;
-    mask_buf = NULL;
-    null_count = 0;
+    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;
+
+	masked = TRUE;
     }
 
     /* calculate number of patches */
-    count = 0;
-    connected = 0;
-    other_above = 0;
+    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) {
+
+	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 (j = 0; j < ad->cl; j++) {
-		if (mask_buf[j + ad->x] == 0) {
-		    Rast_set_c_null_value(&buf[j + ad->x], 1);
-		    null_count++;
+	}
+	
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
+
+	Rast_set_c_null_value(&precCell, 1);
+
+	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 + ad->x] == 0)) {
+		Rast_set_c_null_value(&corrCell, 1);
+	    }
+
+	    if (Rast_is_c_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_c_null_value(&supCell, 1);
+	    }
+
+	    if (!Rast_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 (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 + 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;
+			}
+			/* 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 {
+			pst[new_pid].count++;
+		    }
 		}
+		connected = 1;
 	    }
+
+	    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));
+
+		    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;
+}
+
+
+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;
+
+    Rast_get_cellhd(ad->raster, "", &hd);
+
+    buf_null = Rast_allocate_d_buf();
+    Rast_set_d_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
+	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;
+	}
 	
-	ctmp = pid_sup;
-	pid_sup = pid_curr;
-	pid_curr = ctmp;
-	Rast_set_c_null_value(pid_curr, Rast_window_cols());
+	ltmp = pid_sup;
+	pid_sup = pid_corr;
+	pid_corr = ltmp;
 
+	Rast_set_d_null_value(&precCell, 1);
+
 	connected = 0;
-	other_above = 1;
 	for (j = 0; j < ad->cl; j++) {
+	    pid_corr[j + ad->x] = 0;
 	    
-	    if (Rast_is_null_value(&(buf[j + ad->x]), CELL_TYPE)) {
+	    corrCell = buf[j + ad->x];
+	    if (masked && (mask_buf[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&corrCell, 1);
+	    }
+
+	    if (Rast_is_d_null_value(&corrCell)) {
 		connected = 0;
-		other_above = 1;
+		precCell = corrCell;
 		continue;
 	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_d_null_value(&supCell, 1);
+	    }
 
-	    if (sup[j + ad->x] == buf[j + ad->x]) {
-		
-		if (!connected) {
-		    pid_curr[j + ad->x] = pid_sup[j + ad->x];
-		}
-		
-		if (pid_curr[j + ad->x] != pid_sup[j + ad->x]) {
+	    if (!Rast_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 (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* connect or merge */
+		    /* after r.clump */
 		    if (connected) {
-			count--;
+			npatch--;
+
+			if (npatch == 0) {
+			    G_fatal_error("npatch == 0 at row %d, col %d", i, j);
+			}
 		    }
-		    if (other_above) {
-			pid_curr[j + ad->x] = pid_sup[j + ad->x];
-			for (k = j + ad->x - 1; k >= ad->x; k--) {
-			    if (buf[k] != buf[j + ad->x])
-				break;
-			    pid_curr[k] = pid_sup[j + ad->x];
+
+		    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;
 			}
+			/* 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 {
-			old_pid = pid_sup[j + ad->x];
-			pid_sup[j + ad->x] = pid_curr[j + ad->x];
+			pst[new_pid].count++;
+		    }
+		}
+		connected = 1;
+	    }
+
+	    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));
+
+		    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;
+}
+
+
+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;
+
+    Rast_get_cellhd(ad->raster, "", &hd);
+
+    buf_null = Rast_allocate_f_buf();
+    Rast_set_f_null_value(buf_null, Rast_window_cols());
+    buf_sup = buf_null;
+
+    /* initialize patch ids */
+    pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
+    pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
+
+    for (j = 0; j < Rast_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;
+	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_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;
+
+	Rast_set_f_null_value(&precCell, 1);
+
+	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 + ad->x] == 0)) {
+		Rast_set_f_null_value(&corrCell, 1);
+	    }
+
+	    if (Rast_is_f_null_value(&corrCell)) {
+		connected = 0;
+		precCell = corrCell;
+		continue;
+	    }
+	    
+	    area++;
+	    
+	    supCell = buf_sup[j + ad->x];
+	    if (masked && (mask_sup[j + ad->x] == 0)) {
+		Rast_set_f_null_value(&supCell, 1);
+	    }
+
+	    if (!Rast_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 (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
+
+		if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
+		    /* 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 + 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;
+			}
+			/* 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] = pid_curr[j + ad->x];
-			    }
+			    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 {
+			pst[new_pid].count++;
+		    }
 		}
-
-		other_above = 0;
 		connected = 1;
 	    }
 
 	    if (!connected) {
-		count++;
+		/* start new patch */
+		npatch++;
 		pid++;
-		pid_curr[j + ad->x] = pid;
-	    }
+		pid_corr[j + ad->x] = pid;
 
-	    if (j < ad->cl - 1) {
-		if (buf[j + ad->x] == buf[j + 1 + ad->x]) {
-		    
-		    connected = 1;
-		    pid_curr[j + 1 + ad->x] = pid_curr[j + ad->x];
+		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;
 		}
-		else {
-		    other_above = 1;
-		    connected = 0;
-		}
+
+		pst[pid].count = 1;
+		pst[pid].type.t = CELL_TYPE;
+		pst[pid].type.val.c = corrCell;
 	    }
+	    precCell = corrCell;
 	}
     }
 
-    *result = count;
+    *result = npatch;
 
-    if (ad->mask == 1) {
+    if (masked) {
+	close(mask_fd);
 	G_free(mask_buf);
+	G_free(mask_sup);
     }
-    G_free(cnull);
-    G_free(pid_curr);
+    G_free(buf_null);
+    G_free(pid_corr);
     G_free(pid_sup);
+    G_free(pst);
 
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html
===================================================================
--- grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.patchnum/r.li.patchnum.html	2014-02-17 10:05:22 UTC (rev 59072)
@@ -2,8 +2,11 @@
 
 <em>r.li.patchnum</em> calculates the "patch number index" as:<br>
 <I> f(sample_area)= Patch_Number </I><br>
-This index is calculated using a 4 neighbour algorithm<br>
 
+<p>
+This index is calculated using a 4 neighbour algorithm, diagonal cells 
+are ignored when tracing a patch.
+
 <h2>NOTES</h2>
 
 Do not use absolute path names for the <b>output</b> map/file.
@@ -11,13 +14,8 @@
 output will be a raster map, otherwise an ASCII file will be generated in
 the <tt>$HOME/.grass7/r.li/output/</tt> folder.
 <p>
-<!-- TODO verify: -->
-If the input raster map contains only NULL values then it is considered to have zero patch. <br>
-If you want to keep NULL values, run subsequently on the resulting map:
-<div class="code"><pre>
-r.null setnull=0 input=my_map
-</pre></div>
-after index calculation.
+If the sample area contains only NULL values then it is considered to 
+have zero patches. <br>
 
 <h2>EXAMPLES</h2>
 To calculate patch number index on map <em>my_map</em>, using
@@ -45,9 +43,8 @@
 Gen. Tech. Rep. PNW-351. (<a href="http://treesearch.fs.fed.us/pubs/3064">PDF</a>)
 
 <h2>AUTHORS</h2>
-Claudio Porta and Lucio Davide Spano, students of Computer Science 
-University of Pisa (Italy).<br>
-Commission from Faunalia Pontedera (PI) (www.faunalia.it)<br>
+Michael Shapiro - CERL (patch identification)<br>
+Markus Metz (statistics)
 
 <p>
 <i>Last changed: $Date$</i>

Modified: grass/trunk/raster/r.li/r.li.pielou/pielou.c
===================================================================
--- grass/trunk/raster/r.li/r.li.pielou/pielou.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.pielou/pielou.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -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)
@@ -14,41 +15,27 @@
  *       
  ***************************************************************************/
 
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+
 #include <stdlib.h>
 #include <fcntl.h>
 #include <math.h>
 
-#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 */
+
 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)
-{
-    double *p1 = (double *)pa;
-    double *p2 = (double *)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]);
@@ -75,18 +62,13 @@
 
     return calculateIndex(conf->answer, pielou, NULL, raster->answer,
 			  output->answer);
-
 }
 
 int pielou(int fd, char **par, struct area_entry *ad, double *result)
 {
-
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    Rast_get_cellhd(ad->raster, "", &hd);
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
@@ -117,7 +99,6 @@
     *result = indice;
 
     return RLI_OK;
-
 }
 
 
@@ -125,48 +106,31 @@
 {
     CELL *buf;
     CELL corrCell;
+    CELL precCell;
 
     int i, j;
     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 = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
-    /* add to compute the number of class */
-    double *array_copy;
-    int totNumClass = 1;
-    double logTotNumClass;
-
-    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;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
-	mask_buf = G_malloc(Rast_window_cols() * sizeof(int));
+	mask_buf = G_malloc(ad->cl * sizeof(int));
 	if (mask_buf == NULL) {
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
@@ -174,10 +138,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -185,31 +146,42 @@
 	    }
 	}
 
+	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+	Rast_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) {
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.c = corrCell;
-		    albero = avl_make(cc, 1);
-
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.c = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -227,72 +199,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
-	    }
-	}			/* end for */
-    }				/* end for */
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
 
     /*last closing */
-    if (a != 0 && albero != NULL) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	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;
+		}
+	    case AVL_ADD:
+		{
+		    m++;
+		    break;
+		}
+	    case AVL_PRES:
+		{
+		    break;
+		}
+	    default:
+		{
+		    G_fatal_error("avl_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
+    }
 
-	array = G_malloc(m * sizeof(AVL_tableRow *));
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
+	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");
+	    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;
 	}
-
-	array_copy = G_malloc(m * sizeof(double));
-	for (i = 0; i < m; i++) {
-	    cc_passage = array[i]->k;
-	    array_copy[i] = cc_passage.val.c;
-	}
-
-	qsort(array_copy, m, sizeof(double), cmp);
-
-	for (i = 1; i < m; i++) {
-	    if (array_copy[i - 1] != array_copy[i]) {
-		totNumClass++;
-	    }
-	}
-
 	G_free(array);
-	G_free(array_copy);
 
-	logTotNumClass = (double)log(totNumClass);
-	indice = ((-1) * somma) / logTotNumClass;
-
-	G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
-		somma, logTotNumClass, indice);
+	*result = -shannon / log(m);
     }
     else
-	/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }
@@ -302,43 +293,26 @@
 {
     DCELL *buf;
     DCELL corrCell;
+    DCELL precCell;
 
     int i, j;
     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 = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
-    /* add to compute the number of class */
-    double *array_copy;
-    int totNumClass = 1;
-    double logTotNumClass;
-
-    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 = DCELL_TYPE;
+    uc.t = DCELL_TYPE;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -351,10 +325,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -362,30 +333,42 @@
 	    }
 	}
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+	Rast_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) {
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.dc = corrCell;
-		    albero = avl_make(cc, 1);
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.dc = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -403,72 +386,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
+
+    /*last closing */
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	if (albero == NULL) {
+	    uc.val.dc = precCell;
+	    albero = avl_make(uc, totCorr);
+	    if (albero == NULL) {
+		G_fatal_error("avl_make error");
+		return RLI_ERRORE;
 	    }
-	}			/*close for */
-    }				/*close for */
+	    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_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
+    }
 
-    /*last closing */
-    if (a != 0 && albero != NULL) {
-	array = G_malloc(m * sizeof(AVL_tableRow *));
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
+	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");
+	    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;
 	}
-
-	array_copy = G_malloc(m * sizeof(double));
-	for (i = 0; i < m; i++) {
-	    cc_passage = array[i]->k;
-	    array_copy[i] = cc_passage.val.c;
-	}
-
-	qsort(array_copy, m, sizeof(double), cmp);
-
-	for (i = 1; i < m; i++) {
-	    if (array_copy[i - 1] != array_copy[i]) {
-		totNumClass++;
-	    }
-	}
-
 	G_free(array);
-	G_free(array_copy);
 
-	logTotNumClass = (double)log(totNumClass);
-	indice = ((-1) * somma) / logTotNumClass;
-
-	G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
-		somma, logTotNumClass, indice);
+	*result = -shannon / log(m);
     }
     else
-	/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }
@@ -478,43 +480,26 @@
 {
     FCELL *buf;
     FCELL corrCell;
+    FCELL precCell;
 
     int i, j;
     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 = 1;
 
-    double indice = 0;
-    double somma = 0;
-    double percentuale = 0;
-    double area = 0;
-    double t;
-    double logaritmo;
+    long area = 0;
 
-    /* add to compute the number of class */
-    double *array_copy;
-    int totNumClass = 1;
-    double logTotNumClass;
-
-    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 = FCELL_TYPE;
+    uc.t = FCELL_TYPE;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -527,10 +512,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -538,29 +520,42 @@
 	    }
 	}
 
-	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);
+	Rast_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) {
+
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.fc = corrCell;
-		    albero = avl_make(cc, 1);
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.fc = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -578,71 +573,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
+
+    /*last closing */
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	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++;
 	}
+	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_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
     }
 
-    /*last closing */
-    if (a != 0 && albero != NULL) {
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
 	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");
+	    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;
 	}
-
-	array_copy = G_malloc(m * sizeof(double));
-	for (i = 0; i < m; i++) {
-	    cc_passage = array[i]->k;
-	    array_copy[i] = cc_passage.val.c;
-	}
-
-	qsort(array_copy, m, sizeof(double), cmp);
-
-	for (i = 1; i < m; i++) {
-	    if (array_copy[i - 1] != array_copy[i]) {
-		totNumClass++;
-	    }
-	}
-
 	G_free(array);
-	G_free(array_copy);
 
-	logTotNumClass = (double)log(totNumClass);
-	indice = ((-1) * somma) / logTotNumClass;
-
-	G_debug(1, "somma: %g, number of logTotNumClass: %g, valore finale: %g",
-		somma, logTotNumClass, indice);
+	*result = -shannon / log(m);
     }
     else
-	/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.renyi/renyi.c
===================================================================
--- grass/trunk/raster/r.li/r.li.renyi/renyi.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.renyi/renyi.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -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,15 +22,14 @@
 #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 calculate(struct area_entry *ad, int fd, char **par, double *result);
 double calculateD(struct area_entry *ad, int fd, char **par, double *result);
-
 double calculateF(struct area_entry *ad, int fd, char **par, double *result);
 
 int main(int argc, char *argv[])
@@ -82,17 +82,15 @@
     }
     return calculateIndex(conf->answer, renyi, par, raster->answer,
 			  output->answer);
-
 }
 
 int renyi(int fd, char **par, struct area_entry *ad, double *result)
 {
-
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    Rast_get_cellhd(ad->raster, "", &hd);
+    if (!par)
+	G_fatal_error("par is NULL");
 
     switch (ad->data_type) {
     case CELL_TYPE:
@@ -124,37 +122,28 @@
     *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, 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;
     generic_cell uc;
 
@@ -172,10 +161,6 @@
 	masked = TRUE;
     }
 
-
-    Rast_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) {
@@ -185,71 +170,71 @@
 	}
 
 	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+	Rast_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)) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
+		area++;
+	    }
 
-		if (corrCell != precCell) {
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_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) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.c = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -285,69 +270,68 @@
 	    }
 	}
     }
-    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;
 
-    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;
+	/* calculate renyi index */
+	sum = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    pi = t / area;
+	    sum += pow(pi, alpha);
+	}
+	G_free(array);
+	
+	*result = (1 / (1 - alpha)) * log(sum);
     }
-    G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
+    else
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
-
-    G_free(array);
-    if (masked)
+    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, 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;
@@ -360,14 +344,12 @@
 	    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;
     }
 
-    Rast_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) {
@@ -377,72 +359,71 @@
 	}
 
 	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+	Rast_set_d_null_value(&precCell, 1);
 
-	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 + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
-		a = 1;
+		area++;
+	    }
 
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_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) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.dc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -479,76 +460,68 @@
 	}
     }
 
-    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 alpha;
+	double pi;
+	double t;
+	double sum;
 
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+	alpha = atof(par[0]);
 
-    char *sval;
+	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;
+	}
 
-    sval = par[0];
-    double alpha_double;
-
-    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);
+	/* calculate renyi index */
+	sum = 0;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    pi = t / area;
+	    sum += pow(pi, alpha);
+	}
+	G_free(array);
+	
+	*result = (1 / (1 - alpha)) * log(sum);
     }
+    else
+	Rast_set_d_null_value(result, 1);
 
-    indice = (1 / (1 - alpha_double)) * log(somma);
-
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
     }
 
-    G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
-
-    *result = indice;
-
-    G_free(array);
-    if (masked)
-	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, 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;
 
@@ -566,9 +539,6 @@
 	masked = TRUE;
     }
 
-    Rast_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) {
@@ -578,73 +548,71 @@
 	}
 
 	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+	Rast_set_f_null_value(&precCell, 1);
 
-
-	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 + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+		area++;
+	    }
+
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_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) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.fc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -681,47 +649,44 @@
 	}
     }
 
-    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 alpha;
+	double pi;
+	double t;
+	double sum;
 
-    if (tot != m) {
-	G_warning("avl_to_array unaspected value. the result could be wrong");
-	return RLI_ERRORE;
-    }
+	alpha = atof(par[0]);
 
-    char *sval;
+	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;
+	}
 
-    sval = par[0];
-    double alpha_double;
-
-    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;
+	for (i = 0; i < m; i++) {
+	    t = array[i]->tot;
+	    pi = t / area;
+	    sum += pow(pi, alpha);
+	}
+	G_free(array);
+	
+	*result = (1 / (1 - alpha)) * log(sum);
     }
+    else
+	Rast_set_d_null_value(result, 1);
 
-    indice = (1 / (1 - alpha_double)) * log(somma);
-
-    if (isnan(indice) || isinf(indice)) {
-	indice = -1;
+    avl_destroy(albero);
+    if (masked) {
+	close(mask_fd);
+	G_free(mask_buf);
     }
 
-    G_debug(1, "Valore somma: %g Valore indice: %g", somma, indice);
-
-    *result = indice;
-
-
-    G_free(array);
-    if (masked)
-	G_free(mask_buf);
-
     return RLI_OK;
-
 }

Modified: grass/trunk/raster/r.li/r.li.richness/richness.c
===================================================================
--- grass/trunk/raster/r.li/r.li.richness/richness.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.richness/richness.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,6 +1,6 @@
 
 /*
- * \brief calculates dominance's diversity index
+ * \brief calculates richness diversity index
  *
  *  \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
  *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
@@ -109,7 +109,7 @@
     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 */
@@ -137,9 +137,6 @@
 	masked = TRUE;
     }
 
-    Rast_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) {
@@ -149,6 +146,7 @@
 	}
 
 	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+	Rast_set_c_null_value(&precCell, 1);
 	for (i = 0; i < ad->cl; i++) {	/* for each cell in the row */
 	    corrCell = buf[i + ad->x];
 
@@ -158,9 +156,6 @@
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
 		a = 1;
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
 		if (corrCell != precCell) {
 		    if (albero == NULL) {
 			uc.val.c = precCell;
@@ -202,14 +197,13 @@
 
 		    ;
 		}
-		precCell = corrCell;
 	    }
-
+	    precCell = corrCell;
 	}
     }
 
     /*last closing */
-    if (a != 0) {
+    if (!(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.c = precCell;
 	    albero = avl_make(uc, (long)1);
@@ -268,7 +262,7 @@
     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 */
@@ -295,8 +289,6 @@
 	masked = TRUE;
     }
 
-    Rast_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) {
@@ -306,6 +298,7 @@
 	}
 
 	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+	Rast_set_d_null_value(&precCell, 1);
 
 	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
 	    corrCell = buf[i + ad->x];
@@ -317,9 +310,6 @@
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
 		a = 1;
 
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
 		if (corrCell != precCell) {
 		    if (albero == NULL) {
 			uc.val.dc = precCell;
@@ -361,15 +351,13 @@
 
 		    ;
 		}
-		precCell = corrCell;
 	    }
-
-
+	    precCell = corrCell;
 	}
     }
 
     /*last closing */
-    if (a != 0) {
+    if (!(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.dc = precCell;
 	    albero = avl_make(uc, (long)1);
@@ -430,7 +418,7 @@
     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 */
@@ -457,9 +445,6 @@
 	masked = TRUE;
     }
 
-    Rast_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) {
@@ -469,8 +454,8 @@
 	}
 
 	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+	Rast_set_f_null_value(&precCell, 1);
 
-
 	for (i = 0; i < ad->cl; i++) {	/* for each fcell in the row */
 
 	    corrCell = buf[i + ad->x];
@@ -481,9 +466,7 @@
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
 		a = 1;
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
+
 		if (corrCell != precCell) {
 		    if (albero == NULL) {
 			uc.val.fc = precCell;
@@ -525,15 +508,13 @@
 
 		    ;
 		}
-		precCell = corrCell;
 	    }
-
-
+	    precCell = corrCell;
 	}
     }
 
     /*last closing */
-    if (a != 0) {
+    if (!(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.fc = precCell;
 	    albero = avl_make(uc, (long)1);

Modified: grass/trunk/raster/r.li/r.li.shannon/shannon.c
===================================================================
--- grass/trunk/raster/r.li/r.li.shannon/shannon.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.shannon/shannon.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,13 +1,19 @@
-/*
- * \brief calculates shannon's diversity index
+/****************************************************************************
  *
- *   \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.shannon
+ * 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 Shannon's diversity 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/raster.h>
@@ -17,11 +23,12 @@
 #include <fcntl.h>
 #include <math.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 for dominance, renyi, pielou, 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);
@@ -55,19 +62,14 @@
 
     return calculateIndex(conf->answer, shannon, NULL, raster->answer,
 			  output->answer);
-
 }
 
 
 int shannon(int fd, char **par, struct area_entry * ad, double *result)
 {
-
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    Rast_get_cellhd(ad->raster, "", &hd);
-
     switch (ad->data_type) {
     case CELL_TYPE:
 	{
@@ -98,7 +100,6 @@
     *result = indice;
 
     return RLI_OK;
-
 }
 
 
@@ -106,42 +107,31 @@
 {
     CELL *buf;
     CELL corrCell;
+    CELL precCell;
 
     int i, j;
     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 = 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;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
 	    return RLI_ERRORE;
-	mask_buf = G_malloc(Rast_window_cols() * sizeof(int));
+	mask_buf = G_malloc(ad->cl * sizeof(int));
 	if (mask_buf == NULL) {
 	    G_fatal_error("malloc mask_buf failed");
 	    return RLI_ERRORE;
@@ -149,10 +139,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -160,31 +147,42 @@
 	    }
 	}
 
+	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+	Rast_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) {
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.c = corrCell;
-		    albero = avl_make(cc, 1);
-
+		    uc.val.c = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.c = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.c = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -202,53 +200,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
-	    }
-	}			/* end for */
-    }				/* end for */
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
 
     /*last closing */
-    if (a != 0 && albero != NULL) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	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;
+		}
+	    case AVL_ADD:
+		{
+		    m++;
+		    break;
+		}
+	    case AVL_PRES:
+		{
+		    break;
+		}
+	    default:
+		{
+		    G_fatal_error("avl_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
+    }
 
-	array = G_malloc(m * sizeof(AVL_tableRow *));
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
+	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");
+	    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);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }
@@ -258,37 +294,26 @@
 {
     DCELL *buf;
     DCELL corrCell;
+    DCELL precCell;
 
     int i, j;
     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 = 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 = DCELL_TYPE;
+    uc.t = DCELL_TYPE;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -301,10 +326,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -312,30 +334,42 @@
 	    }
 	}
 
-	for (i = 0; i < ad->cl; i++) {	/* for each dcell in the row */
-	    area++;
+	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+	Rast_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) {
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.dc = corrCell;
-		    albero = avl_make(cc, 1);
+		    uc.val.dc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.dc = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.dc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -353,53 +387,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
+
+    /*last closing */
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	if (albero == NULL) {
+	    uc.val.dc = precCell;
+	    albero = avl_make(uc, totCorr);
+	    if (albero == NULL) {
+		G_fatal_error("avl_make error");
+		return RLI_ERRORE;
 	    }
-	}			/*close for */
-    }				/*close for */
+	    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_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
+    }
 
-    /*last closing */
-    if (a != 0 && albero != NULL) {
-	array = G_malloc(m * sizeof(AVL_tableRow *));
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
+	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");
+	    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);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }
@@ -409,37 +481,26 @@
 {
     FCELL *buf;
     FCELL corrCell;
+    FCELL precCell;
 
     int i, j;
     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 = 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 = FCELL_TYPE;
+    uc.t = FCELL_TYPE;
 
-    if (ad->y + ad->rl > Rast_window_rows())
-	G_fatal_error("Region dimensions are wrong: n rows %d > %d",
-	              ad->y + ad->rl, Rast_window_rows());
-    if (ad->x + ad->cl > Rast_window_cols())
-	G_fatal_error("Region dimensions are wrong; n cols %d > %d",
-	              ad->x + ad->cl, Rast_window_cols());
-
     /* open mask if needed */
     if (ad->mask == 1) {
 	if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
@@ -452,10 +513,7 @@
 	masked = TRUE;
     }
 
-    /*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");
@@ -463,29 +521,42 @@
 	    }
 	}
 
-	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);
+	Rast_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) {
+
+	    if ((masked) && (mask_buf[i + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
-	    if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
-		a = 1;
+	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
+		area++;
+	    }
 
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		     corrCell != precCell) {
+		
+		/* add precCell to search tree */
 		if (albero == NULL) {
-		    cc.val.fc = corrCell;
-		    albero = avl_make(cc, 1);
+		    uc.val.fc = precCell;
+		    albero = avl_make(uc, totCorr);
 		    if (albero == NULL) {
 			G_fatal_error("avl_make error");
 			return RLI_ERRORE;
 		    }
+
 		    m++;
 		}
 		else {
-		    cc.val.fc = corrCell;
-		    ris = avl_add(&albero, cc, 1);
+		    uc.val.fc = precCell;
+		    ris = avl_add(&albero, uc, totCorr);
 		    switch (ris) {
 		    case AVL_ERR:
 			{
@@ -503,52 +574,91 @@
 			}
 		    default:
 			{
-			    G_fatal_error("avl_add unknown error");
+			    G_fatal_error("avl_make unknown error");
 			    return RLI_ERRORE;
 			}
 		    }
 		}
+		totCorr = 1;
+	    }		/* endif not equal cells */
+	    precCell = corrCell;
+	}
+    }
+
+    /*last closing */
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
+	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++;
 	}
+	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_add unknown error");
+		    return RLI_ERRORE;
+		}
+	    }
+	}
     }
 
-    /*last closing */
-    if (a != 0 && albero != NULL) {
+    if (area > 0) {
+	double t;
+	double shannon;
+	double perc, logarithm;;
+
 	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");
+	    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);
+	Rast_set_d_null_value(result, 1);
 
-    *result = indice;
-
+    avl_destroy(albero);
     if (masked) {
 	close(mask_fd);
 	G_free(mask_buf);
     }
-    avl_destroy(albero);
 
     return RLI_OK;
 }

Modified: grass/trunk/raster/r.li/r.li.shape/main.c
===================================================================
--- grass/trunk/raster/r.li/r.li.shape/main.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.shape/main.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -53,20 +53,17 @@
 
     return calculateIndex(conf->answer, shape_index, NULL, raster->answer,
 			  output->answer);
-
 }
 
 int shape_index(int fd, char **par, struct area_entry *ad, double *result)
 {
-
-
     double area;
     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 *mask_buf = NULL;
 
     Rast_set_c_null_value(&complete_value, 1);
     Rast_get_cellhd(ad->raster, "", &hd);
@@ -108,5 +105,6 @@
 	(ad->rl * ad->cl - null_count);
 
     *result = area;
+
     return 1;
 }

Modified: grass/trunk/raster/r.li/r.li.simpson/simpson.c
===================================================================
--- grass/trunk/raster/r.li/r.li.simpson/simpson.c	2014-02-16 22:29:52 UTC (rev 59071)
+++ grass/trunk/raster/r.li/r.li.simpson/simpson.c	2014-02-17 10:05:22 UTC (rev 59072)
@@ -1,32 +1,38 @@
-
-/*
- * \brief calculates Simpson's diversity index
+/****************************************************************************
  *
- *  \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
- *                      Commission from Faunalia Pontedera (PI) www.faunalia.it
+ * MODULE:       r.li.simpson
+ * 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 Simpson's diversity 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/raster.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/raster.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);
+/* template is 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);
+
 int main(int argc, char *argv[])
 {
     struct Option *raster, *conf, *output;
@@ -56,31 +62,27 @@
 
     return calculateIndex(conf->answer, simpson, NULL, raster->answer,
 			  output->answer);
-
 }
 
 int simpson(int fd, char **par, struct area_entry *ad, double *result)
 {
     int ris = RLI_OK;
     double indice = 0;
-    struct Cell_head hd;
 
-    Rast_get_cellhd(ad->raster, "", &hd);
-
     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:
@@ -88,7 +90,6 @@
 	    G_fatal_error("data type unknown");
 	    return RLI_ERRORE;
 	}
-
     }
 
     if (ris != RLI_OK)
@@ -97,41 +98,34 @@
     *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;
     long tot = 0;
     long zero = 0;
-    long totCorr = 0;
+    long totCorr = 1;
 
-    double indice = 0;
     double somma = 0;
     double p = 0;
-    double area = 0;
+    long area = 0;
     double t;
 
     avl_tree albero = NULL;
-
     AVL_table *array;
-
     generic_cell uc;
 
-
     uc.t = CELL_TYPE;
 
     /* open mask if needed */
@@ -146,9 +140,6 @@
 	masked = TRUE;
     }
 
-    Rast_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) {
@@ -158,70 +149,71 @@
 	}
 
 	buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
+	Rast_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)) {
 		Rast_set_c_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+		area++;
+	    }
+
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_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) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.c = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -257,68 +249,65 @@
 	    }
 	}
     }
-    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) {
+	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) {
-	indice = 1 - somma;
+	/* calculate index summary */
+	for (i = 0; i < m; i++) {
+	    t = (double)(array[i]->tot);
+	    p = t / area;
+	    somma = somma + (p * p);
+	}
+	G_free(array);
+
+	*result = 1 - somma;
     }
-    else			/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = (double)(-1);
+    else
+	Rast_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 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;
+    long area = 0;
     double t;
 
     avl_tree albero = NULL;
-
     AVL_table *array;
-
     generic_cell uc;
 
     uc.t = DCELL_TYPE;
@@ -329,14 +318,12 @@
 	    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;
     }
 
-    Rast_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,72 +333,71 @@
 	}
 
 	buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
+	Rast_set_d_null_value(&precCell, 1);
 
-	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 + ad->x] == 0)) {
 		Rast_set_d_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
-		a = 1;
+		area++;
+	    }
 
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_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) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.dc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -447,67 +433,65 @@
 	    }
 	}
     }
-    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) {
+	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 index summary */
+	for (i = 0; i < m; i++) {
+	    t = (double)(array[i]->tot);
+	    p = t / area;
+	    somma = somma + (p * p);
+	}
+	G_free(array);
+
+	*result = 1 - somma;
     }
     else
-	indice = (double)(-1);
+	Rast_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;
+    long area = 0;
     double t;
 
     avl_tree albero = NULL;
-
     AVL_table *array;
-
     generic_cell uc;
 
     uc.t = FCELL_TYPE;
@@ -524,9 +508,6 @@
 	masked = TRUE;
     }
 
-    Rast_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) {
@@ -536,73 +517,71 @@
 	}
 
 	buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
+	Rast_set_f_null_value(&precCell, 1);
 
-
-	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 + ad->x] == 0)) {
 		Rast_set_f_null_value(&corrCell, 1);
-		area--;
 	    }
 
 	    if (!(Rast_is_null_value(&corrCell, uc.t))) {
-		a = 1;
-		if (Rast_is_null_value(&precCell, uc.t)) {
-		    precCell = corrCell;
-		}
-		if (corrCell != precCell) {
+		area++;
+	    }
+
+	    if (!(Rast_is_null_value(&precCell, uc.t)) &&
+		corrCell == precCell) {
+
+		totCorr++;
+	    }
+	    else if (!(Rast_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) {
+    if (area > 0 && !(Rast_is_null_value(&precCell, uc.t))) {
 	if (albero == NULL) {
 	    uc.val.fc = precCell;
 	    albero = avl_make(uc, totCorr);
@@ -639,36 +618,36 @@
 	}
     }
 
-    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) {
+	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 index summary */
-    for (i = 0; i < m; i++) {
-	t = (double)(array[i]->tot);
-	p = t / area;
-	somma = somma + (p * p);
-    }
+	/* calculate index summary */
+	for (i = 0; i < m; i++) {
+	    t = (double)(array[i]->tot);
+	    p = t / area;
+	    somma = somma + (p * p);
+	}
+	G_free(array);
 
-    if (a != 0) {		/*if a is 0, that is all cell are null, i put index=-1 */
-	indice = 1 - somma;
+	*result = 1 - somma;
     }
     else
-	indice = (double)(-1);
+	Rast_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;
 }



More information about the grass-commit mailing list