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
i_round(double x,double step,double start)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
f_round(int argc,const int * argt,void ** args)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
c_round(int argc,int * argt)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 }
204