[GRASS-SVN] r56313 - grass/trunk/raster/r.mapcalc

svn_grass at osgeo.org svn_grass at osgeo.org
Sun May 19 06:30:37 PDT 2013


Author: mmetz
Date: 2013-05-19 06:30:36 -0700 (Sun, 19 May 2013)
New Revision: 56313

Modified:
   grass/trunk/raster/r.mapcalc/function.c
   grass/trunk/raster/r.mapcalc/r.mapcalc.html
   grass/trunk/raster/r.mapcalc/r3.mapcalc.html
   grass/trunk/raster/r.mapcalc/xround.c
Log:
r.mapcalc: enhance round()

Modified: grass/trunk/raster/r.mapcalc/function.c
===================================================================
--- grass/trunk/raster/r.mapcalc/function.c	2013-05-19 11:38:15 UTC (rev 56312)
+++ grass/trunk/raster/r.mapcalc/function.c	2013-05-19 13:30:36 UTC (rev 56313)
@@ -89,7 +89,7 @@
     {"ewres", c_double0, f_ewres},
     {"nsres", c_double0, f_nsres},
     {"tbres", c_double0, f_tbres},
-    {NULL}
+    {NULL, NULL, NULL}
 };
 
 void print_function_names(void)

Modified: grass/trunk/raster/r.mapcalc/r.mapcalc.html
===================================================================
--- grass/trunk/raster/r.mapcalc/r.mapcalc.html	2013-05-19 11:38:15 UTC (rev 56312)
+++ grass/trunk/raster/r.mapcalc/r.mapcalc.html	2013-05-19 13:30:36 UTC (rev 56313)
@@ -318,7 +318,8 @@
 not(x)                  1 if x is zero, 0 otherwise
 pow(x,y)                x to the power y                                *
 rand(a,b)               random value x : a <= x < b
-round(x)                round x to nearest integer                      I
+round(x)                round x to nearest integer                      *
+round(x, y)             round x to y decimal places                     *
 sin(x)                  sine of x (x is in degrees)                     F
 sqrt(x)                 square root of x                                F
 tan(x)                  tangent of x (x is in degrees)                  F
@@ -335,6 +336,9 @@
  null()                 NULL value
 </pre></div>
 Note, that the row() and col() indexing starts with 1.
+<p>
+round(x, y) supports a negative number of decimal places: for example, 
+round(119, -1) results in 120, and round(119, -2) results in 100.
 
 
 <h3>FLOATING POINT VALUES IN THE EXPRESSION</h3>

Modified: grass/trunk/raster/r.mapcalc/r3.mapcalc.html
===================================================================
--- grass/trunk/raster/r.mapcalc/r3.mapcalc.html	2013-05-19 11:38:15 UTC (rev 56312)
+++ grass/trunk/raster/r.mapcalc/r3.mapcalc.html	2013-05-19 13:30:36 UTC (rev 56313)
@@ -222,7 +222,8 @@
 not(x)                  1 if x is zero, 0 otherwise
 pow(x,y)                x to the power y                                *
 rand(a,b)               random value x : a <= x < b
-round(x)                round x to nearest integer                      I
+round(x)                round x to nearest integer                      *
+round(x, y)             round x to y decimal places                     *
 sin(x)                  sine of x (x is in degrees)                     F
 sqrt(x)                 square root of x                                F
 tan(x)                  tangent of x (x is in degrees)                  F
@@ -242,6 +243,9 @@
  null()                 NULL value
 </pre></div>
 Note, that the row(), col() and depth() indexing starts with 1. 
+<p>
+round(x, y) supports a negative number of decimal places: for example, 
+round(119, -1) results in 120, and round(119, -2) results in 100.
 
 
 <h2>FLOATING POINT VALUES IN THE EXPRESSION</h2>

Modified: grass/trunk/raster/r.mapcalc/xround.c
===================================================================
--- grass/trunk/raster/r.mapcalc/xround.c	2013-05-19 11:38:15 UTC (rev 56312)
+++ grass/trunk/raster/r.mapcalc/xround.c	2013-05-19 13:30:36 UTC (rev 56313)
@@ -1,5 +1,6 @@
 
 #include <limits.h>
+#include <math.h>
 
 #include <grass/gis.h>
 #include <grass/raster.h>
@@ -8,91 +9,181 @@
 #include "func_proto.h"
 
 /**********************************************************************
-round(x)
+round(x) rounds x to nearest integer
+round(x, y) rounds x to y decimal places
 
-  rounds x to nearest integer.
-
   if input is CELL (which is an integer already)
+  and the number of decimal places is 0
   the input argument (argv[0]) is simply copied to the output cell.
 
   if the input is double, the input is rounded by adding .5 to positive
   numbers, and subtracting .5 from negatives.
 **********************************************************************/
 
-/* i_round(x) rounds x to nearest CELL value, handles negative correctly */
+/* d_round(x) rounds x to nearest integer value, handles negative correctly */
 
-static int i_round(double x)
+static double d_round(double x)
 {
-    int n;
+    if (!IS_NULL_D(&x)) {
+	x = floor(x + 0.5);
+    }
 
-    if (IS_NULL_D(&x))
-	SET_NULL_C(&n);
-    else if (x > INT_MAX || x < -INT_MAX) {
-	SET_NULL_C(&n);
-	if (!IS_NULL_D(&x))
-	    overflow_occurred = 1;
+    return x;
+}
+
+/**********************************************************************/
+
+/* d_roundd(x, y) rounds x to y decimal places, handles negative correctly */
+
+static double d_roundd(double x, int y)
+{
+    if (!IS_NULL_D(&x)) {
+	double pow10, intx, sgn = 1.;
+
+	if (x < 0.) {
+	    sgn = -1.;
+	    x = -x;
+	}
+	if (y == 0)
+	    return (double)(sgn * d_round(x));
+	else if (y > 0) {
+	    pow10 = pow(10., y);
+	    intx = floor(x);
+	    return (double)(sgn * (intx + d_round((double)((x - intx) * pow10)) / pow10));
+	}
+	else {
+	    pow10 = pow(10., -y);
+	    return (double)(sgn * d_round((double)(x / pow10)) * pow10);
+	}
     }
-    else if (x >= 0.0)
-	n = x + .5;
-    else {
-	n = -x + .5;
-	n = -n;
-    }
 
-    return n;
+    return x;
 }
 
 /**********************************************************************/
-
 int f_round(int argc, const int *argt, void **args)
 {
-    int *res = args[0];
     int i;
 
     if (argc < 1)
 	return E_ARG_LO;
-    if (argc > 1)
+    if (argc > 2)
 	return E_ARG_HI;
 
-    if (argt[0] != CELL_TYPE)
-	return E_RES_TYPE;
+    if (argc == 1) {
+	switch (argt[1]) {
+	case CELL_TYPE:
+	    {
+		CELL *arg1 = args[1];
+		CELL *res = args[0];
 
-    switch (argt[1]) {
-    case CELL_TYPE:
-	{
-	    CELL *arg1 = args[1];
+		for (i = 0; i < columns; i++)
+		    if (IS_NULL_C(&arg1[i]))
+			SET_NULL_C(&res[i]);
+		    else
+			res[i] = arg1[i];
+		return 0;
+	    }
+	case FCELL_TYPE:
+	    {
+		FCELL *arg1 = args[1];
+		FCELL *res = args[0];
 
-	    for (i = 0; i < columns; i++)
-		if (IS_NULL_C(&arg1[i]))
-		    SET_NULL_C(&res[i]);
-		else
-		    res[i] = arg1[i];
-	    return 0;
-	}
-    case FCELL_TYPE:
-	{
-	    FCELL *arg1 = args[1];
+		for (i = 0; i < columns; i++)
+		    if (IS_NULL_F(&arg1[i]))
+			SET_NULL_F(&res[i]);
+		    else
+			res[i] = d_round(arg1[i]);
+		return 0;
+	    }
+	case DCELL_TYPE:
+	    {
+		DCELL *arg1 = args[1];
+		DCELL *res = args[0];
 
-	    for (i = 0; i < columns; i++)
-		if (IS_NULL_F(&arg1[i]))
-		    SET_NULL_C(&res[i]);
-		else
-		    res[i] = i_round(arg1[i]);
-	    return 0;
+		for (i = 0; i < columns; i++)
+		    if (IS_NULL_D(&arg1[i]))
+			SET_NULL_D(&res[i]);
+		    else
+			res[i] = d_round(arg1[i]);
+		return 0;
+	    }
+	default:
+	    return E_INV_TYPE;
 	}
-    case DCELL_TYPE:
-	{
-	    DCELL *arg1 = args[1];
+    }
+    else {    /* argc == 2 */
+	int digits;
+	DCELL *arg2;
 
-	    for (i = 0; i < columns; i++)
-		if (IS_NULL_D(&arg1[i]))
-		    SET_NULL_C(&res[i]);
-		else
-		    res[i] = i_round(arg1[i]);
-	    return 0;
+	switch (argt[1]) {
+	case CELL_TYPE:
+	    {
+		CELL *arg1 = args[1];
+		CELL *res = args[0];
+
+		arg2 = args[2];
+
+		for (i = 0; i < columns; i++)
+		    if (IS_NULL_C(&arg1[i]))
+			SET_NULL_C(&res[i]);
+		    else {
+			if (arg2[i] >= 0)
+			    digits = d_round(arg2[i]) + 0.5;
+			else
+			    digits = d_round(arg2[i]) - 0.5;
+			if (digits >= 0)
+			    res[i] = arg1[i];
+			else {
+			    if (arg1[i] >= 0)
+				res[i] = d_roundd(arg1[i], digits) + 0.5;
+			    else
+				res[i] = d_roundd(arg1[i], digits) - 0.5;
+			}
+		    }
+		return 0;
+	    }
+	case FCELL_TYPE:
+	    {
+		FCELL *arg1 = args[1];
+		FCELL *res = args[0];
+
+		arg2 = args[2];
+
+		for (i = 0; i < columns; i++)
+		    if (IS_NULL_F(&arg1[i]))
+			SET_NULL_F(&res[i]);
+		    else {
+			if (arg2[i] >= 0)
+			    digits = d_round(arg2[i]) + 0.5;
+			else
+			    digits = d_round(arg2[i]) - 0.5;
+			res[i] = d_roundd(arg1[i], digits);
+		    }
+		return 0;
+	    }
+	case DCELL_TYPE:
+	    {
+		DCELL *arg1 = args[1];
+		DCELL *res = args[0];
+
+		arg2 = args[2];
+
+		for (i = 0; i < columns; i++)
+		    if (IS_NULL_D(&arg1[i]))
+			SET_NULL_D(&res[i]);
+		    else {
+			if (arg2[i] >= 0)
+			    digits = d_round(arg2[i]) + 0.5;
+			else
+			    digits = d_round(arg2[i]) - 0.5;
+			res[i] = d_roundd(arg1[i], digits);
+		    }
+		return 0;
+	    }
+	default:
+	    return E_INV_TYPE;
 	}
-    default:
-	return E_INV_TYPE;
     }
 }
 
@@ -100,11 +191,13 @@
 {
     if (argc < 1)
 	return E_ARG_LO;
-    if (argc > 1)
+    if (argc > 2)
 	return E_ARG_HI;
 
-    argt[0] = CELL_TYPE;
-    /*      argt[1] = argt[1];      */
+    argt[0] = argt[1];
+    
+    if (argc == 2)
+	argt[2] = DCELL_TYPE;
 
     return 0;
 }



More information about the grass-commit mailing list