GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-b35369f6b7
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
xmode.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <stdbool.h>
3 
4 #include <grass/gis.h>
5 #include <grass/raster.h>
6 #include <grass/calc.h>
7 
8 /**********************************************************************
9 mode(x1,x2,..,xn)
10  return mode of arguments
11 **********************************************************************/
12 
13 #define SIZE_THRESHOLD 32
14 
15 static int dcmp(const void *aa, const void *bb)
16 {
17  const double *a = aa;
18  const double *b = bb;
19 
20  if (*a < *b)
21  return -1;
22  if (*a > *b)
23  return 1;
24  return 0;
25 }
26 
27 static double mode(double *value, int argc)
28 {
29  /* Nota:
30  * It might be safer for to return nan or inf in case the input is empty,
31  * but it is a misuse of the function, so the return value is sort of
32  * undefined in that case.
33  */
34  double mode_v = 0.0;
35  int mode_n = 0;
36  int i;
37 
38  qsort(value, argc, sizeof(double), dcmp);
39 
40  for (i = 0; i < argc;) {
41  int n = 1;
42  double v = value[i];
43 
44  for (i++; i < argc; i++) {
45  if (value[i] != v)
46  break;
47  n++;
48  }
49 
50  if (n < mode_n)
51  continue;
52 
53  mode_v = v;
54  mode_n = n;
55  }
56 
57  return mode_v;
58 }
59 
60 int f_mode(int argc, const int *argt, void **args)
61 {
62  double stack_value[SIZE_THRESHOLD];
63  double *value = stack_value;
64  bool use_heap = false;
65  int size = argc * sizeof(double);
66  int i, j;
67 
68  if (argc < 1)
69  return E_ARG_LO;
70 
71  for (i = 1; i <= argc; i++)
72  if (argt[i] != argt[0])
73  return E_ARG_TYPE;
74 
75  if (argc > SIZE_THRESHOLD) {
76  value = G_malloc(size);
77  use_heap = true;
78  }
79 
80  switch (argt[argc]) {
81  case CELL_TYPE: {
82  CELL *res = args[0];
83  CELL **argv = (CELL **)&args[1];
84 
85  for (i = 0; i < columns; i++) {
86  int nv = 0;
87 
88  for (j = 0; j < argc && !nv; j++) {
89  if (IS_NULL_C(&argv[j][i]))
90  nv = 1;
91  else
92  value[j] = (double)argv[j][i];
93  }
94 
95  if (nv)
96  SET_NULL_C(&res[i]);
97  else
98  res[i] = (CELL)mode(value, argc);
99  }
100  if (use_heap) {
101  G_free(value);
102  }
103  return 0;
104  }
105  case FCELL_TYPE: {
106  FCELL *res = args[0];
107  FCELL **argv = (FCELL **)&args[1];
108 
109  for (i = 0; i < columns; i++) {
110  int nv = 0;
111 
112  for (j = 0; j < argc && !nv; j++) {
113  if (IS_NULL_F(&argv[j][i]))
114  nv = 1;
115  else
116  value[j] = (double)argv[j][i];
117  }
118 
119  if (nv)
120  SET_NULL_F(&res[i]);
121  else
122  res[i] = (FCELL)mode(value, argc);
123  }
124  if (use_heap) {
125  G_free(value);
126  }
127  return 0;
128  }
129  case DCELL_TYPE: {
130  DCELL *res = args[0];
131  DCELL **argv = (DCELL **)&args[1];
132 
133  for (i = 0; i < columns; i++) {
134  int nv = 0;
135 
136  for (j = 0; j < argc && !nv; j++) {
137  if (IS_NULL_D(&argv[j][i]))
138  nv = 1;
139  else
140  value[j] = (double)argv[j][i];
141  }
142 
143  if (nv)
144  SET_NULL_D(&res[i]);
145  else
146  res[i] = (DCELL)mode(value, argc);
147  }
148  if (use_heap) {
149  G_free(value);
150  }
151  return 0;
152  }
153  default:
154  if (use_heap) {
155  G_free(value);
156  }
157  return E_INV_TYPE;
158  }
159 }
@ 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
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
#define G_malloc(n)
Definition: defs/gis.h:94
float FCELL
Definition: gis.h:636
double DCELL
Definition: gis.h:635
int CELL
Definition: gis.h:634
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_mode(int argc, const int *argt, void **args)
Definition: xmode.c:60
#define SIZE_THRESHOLD
Definition: xmode.c:13