[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