GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-a351e5eb69
xnmedian.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 
3 #include <grass/gis.h>
4 #include <grass/raster.h>
5 #include <grass/raster.h>
6 #include <grass/calc.h>
7 
8 /**********************************************************************
9 median(x1,x2,..,xn)
10  return median of arguments
11 **********************************************************************/
12 
13 static int icmp(const void *aa, const void *bb)
14 {
15  const CELL *a = aa;
16  const CELL *b = bb;
17 
18  return *a - *b;
19 }
20 
21 static int fcmp(const void *aa, const void *bb)
22 {
23  const FCELL *a = aa;
24  const FCELL *b = bb;
25 
26  if (*a < *b)
27  return -1;
28  if (*a > *b)
29  return 1;
30  return 0;
31 }
32 
33 static int dcmp(const void *aa, const void *bb)
34 {
35  const DCELL *a = aa;
36  const DCELL *b = bb;
37 
38  if (*a < *b)
39  return -1;
40  if (*a > *b)
41  return 1;
42  return 0;
43 }
44 
45 int f_nmedian(int argc, const int *argt, void **args)
46 {
47  static void *array;
48  static int alloc;
49  int size = argc * Rast_cell_size(argt[0]);
50  int i, j;
51 
52  if (argc < 1)
53  return E_ARG_LO;
54 
55  for (i = 1; i <= argc; i++)
56  if (argt[i] != argt[0])
57  return E_ARG_TYPE;
58 
59  if (size > alloc) {
60  alloc = size;
61  array = G_realloc(array, size);
62  }
63 
64  switch (argt[0]) {
65  case CELL_TYPE: {
66  CELL *res = args[0];
67  CELL **argv = (CELL **)&args[1];
68  CELL *a = array;
69  CELL a1;
70  CELL *resc;
71 
72  for (i = 0; i < columns; i++) {
73  int n = 0;
74 
75  for (j = 0; j < argc; j++) {
76  if (IS_NULL_C(&argv[j][i]))
77  continue;
78  a[n++] = argv[j][i];
79  }
80 
81  resc = &res[i];
82 
83  if (!n)
84  SET_NULL_C(resc);
85  else {
86  qsort(a, n, sizeof(CELL), icmp);
87  *resc = a[n / 2];
88  if ((n & 1) == 0) {
89  a1 = a[(n - 1) / 2];
90  if (*resc != a1)
91  *resc = (*resc + a1) / 2;
92  }
93  }
94  }
95 
96  return 0;
97  }
98  case FCELL_TYPE: {
99  FCELL *res = args[0];
100  FCELL **argv = (FCELL **)&args[1];
101  FCELL *a = array;
102  FCELL a1;
103  FCELL *resc;
104 
105  for (i = 0; i < columns; i++) {
106  int n = 0;
107 
108  for (j = 0; j < argc; j++) {
109  if (IS_NULL_F(&argv[j][i]))
110  continue;
111  a[n++] = argv[j][i];
112  }
113 
114  resc = &res[i];
115 
116  if (!n)
117  SET_NULL_F(resc);
118  else {
119  qsort(a, n, sizeof(FCELL), fcmp);
120  *resc = a[n / 2];
121  if ((n & 1) == 0) {
122  a1 = a[(n - 1) / 2];
123  if (*resc != a1)
124  *resc = (*resc + a1) / 2;
125  }
126  }
127  }
128 
129  return 0;
130  }
131  case DCELL_TYPE: {
132  DCELL *res = args[0];
133  DCELL **argv = (DCELL **)&args[1];
134  DCELL *a = array;
135  DCELL a1;
136  DCELL *resc;
137 
138  for (i = 0; i < columns; i++) {
139  int n = 0;
140 
141  for (j = 0; j < argc; j++) {
142  if (IS_NULL_D(&argv[j][i]))
143  continue;
144  a[n++] = argv[j][i];
145  }
146 
147  resc = &res[i];
148 
149  if (!n)
150  SET_NULL_D(resc);
151  else {
152  qsort(a, n, sizeof(DCELL), dcmp);
153  *resc = a[n / 2];
154  if ((n & 1) == 0) {
155  a1 = a[(n - 1) / 2];
156  if (*resc != a1)
157  *resc = (*resc + a1) / 2;
158  }
159  }
160  }
161 
162  return 0;
163  }
164  default:
165  return E_INV_TYPE;
166  }
167 }
@ E_INV_TYPE
Definition: calc.h:15
@ E_ARG_TYPE
Definition: calc.h:13
@ E_ARG_LO
Definition: calc.h:11
#define IS_NULL_C(x)
Definition: calc.h:26
#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_F(x)
Definition: calc.h:27
#define IS_NULL_D(x)
Definition: calc.h:28
#define SET_NULL_F(x)
Definition: calc.h:31
#define G_realloc(p, n)
Definition: defs/gis.h:96
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition: alloc_cell.c:38
float FCELL
Definition: gis.h:627
double DCELL
Definition: gis.h:626
int CELL
Definition: gis.h:625
double b
Definition: r_raster.c:39
#define FCELL_TYPE
Definition: raster.h:12
#define DCELL_TYPE
Definition: raster.h:13
#define CELL_TYPE
Definition: raster.h:11
int f_nmedian(int argc, const int *argt, void **args)
Definition: xnmedian.c:45