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