GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-6c790bf5c0
xround.c
Go to the documentation of this file.
1 #include <limits.h>
2 #include <math.h>
3 
4 #include <grass/gis.h>
5 #include <grass/raster.h>
6 #include <grass/calc.h>
7 
8 /**********************************************************************
9 round(x, step, start)
10 
11  rounds x to nearest value in the sequence
12  y[i] = i * step + start
13 
14 **********************************************************************/
15 
16 /* i_round(x) rounds x to nearest value, handles negative correctly */
17 
18 static double i_round(double x, double step, double start)
19 {
20  x -= start;
21  x /= step;
22  x = floor(x + 0.5);
23  x *= step;
24  x += start;
25  return x;
26 }
27 
28 /**********************************************************************/
29 
30 int f_round(int argc, const int *argt, void **args)
31 {
32  const DCELL *arg1 = args[1];
33  int i;
34 
35  if (argc < 1)
36  return E_ARG_LO;
37  if (argc > 3)
38  return E_ARG_HI;
39 
40  if (argc == 1 && argt[0] != CELL_TYPE)
41  return E_RES_TYPE;
42  if (argt[1] != DCELL_TYPE)
43  return E_ARG_TYPE;
44  if (argc > 1 && argt[2] != DCELL_TYPE)
45  return E_ARG_TYPE;
46  if (argc > 2 && argt[3] != DCELL_TYPE)
47  return E_ARG_TYPE;
48 
49  if (argc == 1) {
50  CELL *res = args[0];
51 
52  for (i = 0; i < columns; i++) {
53  if (IS_NULL_D(&arg1[i]))
54  SET_NULL_C(&res[i]);
55  else {
56  DCELL x = i_round(arg1[i], 1.0, 0.0);
57  if (x > 2147483647.0 || x < -2147483647.0)
58  SET_NULL_C(&res[i]);
59  else
60  res[i] = (CELL)x;
61  }
62  }
63  return 0;
64  }
65  else if (argc == 2) {
66  const DCELL *arg2 = args[2];
67 
68  switch (argt[0]) {
69  case CELL_TYPE: {
70  CELL *res = args[0];
71 
72  for (i = 0; i < columns; i++) {
73  if (IS_NULL_D(&arg1[i]))
74  SET_NULL_C(&res[i]);
75  else if (IS_NULL_D(&arg2[i]))
76  SET_NULL_C(&res[i]);
77  else {
78  DCELL x = i_round(arg1[i], arg2[i], 0.0);
79  if (x > 2147483647.0 || x < -2147483647.0)
80  SET_NULL_C(&res[i]);
81  else
82  res[i] = (CELL)x;
83  }
84  }
85  return 0;
86  }
87  case FCELL_TYPE: {
88  FCELL *res = args[0];
89 
90  for (i = 0; i < columns; i++)
91  if (IS_NULL_D(&arg1[i]))
92  SET_NULL_F(&res[i]);
93  else if (IS_NULL_D(&arg2[i]))
94  SET_NULL_F(&res[i]);
95  else
96  res[i] = (FCELL)i_round(arg1[i], arg2[i], 0.0);
97  return 0;
98  }
99  case DCELL_TYPE: {
100  DCELL *res = args[0];
101 
102  for (i = 0; i < columns; i++)
103  if (IS_NULL_D(&arg1[i]))
104  SET_NULL_D(&res[i]);
105  else if (IS_NULL_D(&arg2[i]))
106  SET_NULL_D(&res[i]);
107  else
108  res[i] = (DCELL)i_round(arg1[i], arg2[i], 0.0);
109  return 0;
110  }
111  default:
112  return E_INV_TYPE;
113  }
114  }
115  else if (argc == 3) {
116  const DCELL *arg2 = args[2];
117  const DCELL *arg3 = args[3];
118 
119  switch (argt[0]) {
120  case CELL_TYPE: {
121  CELL *res = args[0];
122 
123  for (i = 0; i < columns; i++) {
124  if (IS_NULL_D(&arg1[i]))
125  SET_NULL_C(&res[i]);
126  else if (IS_NULL_D(&arg2[i]))
127  SET_NULL_C(&res[i]);
128  else if (IS_NULL_D(&arg3[i]))
129  SET_NULL_C(&res[i]);
130  else {
131  DCELL x = i_round(arg1[i], arg2[i], arg3[i]);
132  if (x > 2147483647.0 || x < -2147483647.0)
133  SET_NULL_C(&res[i]);
134  else
135  res[i] = (CELL)x;
136  }
137  }
138  return 0;
139  }
140  case FCELL_TYPE: {
141  FCELL *res = args[0];
142 
143  for (i = 0; i < columns; i++)
144  if (IS_NULL_D(&arg1[i]))
145  SET_NULL_F(&res[i]);
146  else if (IS_NULL_D(&arg2[i]))
147  SET_NULL_F(&res[i]);
148  else if (IS_NULL_D(&arg3[i]))
149  SET_NULL_F(&res[i]);
150  else
151  res[i] = (FCELL)i_round(arg1[i], arg2[i], arg3[i]);
152  return 0;
153  }
154  case DCELL_TYPE: {
155  DCELL *res = args[0];
156 
157  for (i = 0; i < columns; i++)
158  if (IS_NULL_D(&arg1[i]))
159  SET_NULL_D(&res[i]);
160  else if (IS_NULL_D(&arg2[i]))
161  SET_NULL_D(&res[i]);
162  else if (IS_NULL_D(&arg3[i]))
163  SET_NULL_D(&res[i]);
164  else
165  res[i] = (DCELL)i_round(arg1[i], arg2[i], arg3[i]);
166  return 0;
167  }
168  default:
169  return E_INV_TYPE;
170  }
171  }
172  else
173  return E_WTF;
174 }
175 
176 int c_round(int argc, int *argt)
177 {
178  if (argc < 1)
179  return E_ARG_LO;
180  if (argc > 3)
181  return E_ARG_HI;
182 
183  argt[0] = CELL_TYPE;
184  if (argc > 1 && argt[0] < argt[2])
185  argt[0] = argt[2];
186  if (argc > 2 && argt[0] < argt[3])
187  argt[0] = argt[3];
188 
189  argt[1] = DCELL_TYPE;
190  if (argc > 1)
191  argt[2] = DCELL_TYPE;
192  if (argc > 2)
193  argt[3] = DCELL_TYPE;
194 
195  return 0;
196 }
@ E_INV_TYPE
Definition: calc.h:15
@ E_RES_TYPE
Definition: calc.h:14
@ E_ARG_TYPE
Definition: calc.h:13
@ E_ARG_HI
Definition: calc.h:12
@ E_WTF
Definition: calc.h:17
@ E_ARG_LO
Definition: calc.h:11
#define SET_NULL_D(x)
Definition: calc.h:32
int columns
Definition: calc.c:11
#define SET_NULL_C(x)
Definition: calc.h:30
#define IS_NULL_D(x)
Definition: calc.h:28
#define SET_NULL_F(x)
Definition: calc.h:31
float FCELL
Definition: gis.h:627
double DCELL
Definition: gis.h:626
int CELL
Definition: gis.h:625
#define FCELL_TYPE
Definition: raster.h:12
#define DCELL_TYPE
Definition: raster.h:13
#define CELL_TYPE
Definition: raster.h:11
#define x
int c_round(int argc, int *argt)
Definition: xround.c:176
int f_round(int argc, const int *argt, void **args)
Definition: xround.c:30