GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-8cbe8fef7c
xmode.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/calc.h>
6 
7 /**********************************************************************
8 mode(x1,x2,..,xn)
9  return mode of arguments
10 **********************************************************************/
11 
12 static int dcmp(const void *aa, const void *bb)
13 {
14  const double *a = aa;
15  const double *b = bb;
16 
17  if (*a < *b)
18  return -1;
19  if (*a > *b)
20  return 1;
21  return 0;
22 }
23 
24 static double mode(double *value, int argc)
25 {
26  /* Nota:
27  * It might be safer for to return nan or inf in case the input is empty,
28  * but it is a misuse of the function, so the return value is sort of
29  * undefined in that case.
30  */
31  double mode_v = 0.0;
32  int mode_n = 0;
33  int i;
34 
35  qsort(value, argc, sizeof(double), dcmp);
36 
37  for (i = 0; i < argc;) {
38  int n = 1;
39  double v = value[i];
40 
41  for (i++; i < argc; i++) {
42  if (value[i] != v)
43  break;
44  n++;
45  }
46 
47  if (n < mode_n)
48  continue;
49 
50  mode_v = v;
51  mode_n = n;
52  }
53 
54  return mode_v;
55 }
56 
57 int f_mode(int argc, const int *argt, void **args)
58 {
59  static double *value;
60  static int value_size;
61  int size = argc * sizeof(double);
62  int i, j;
63 
64  if (argc < 1)
65  return E_ARG_LO;
66 
67  for (i = 1; i <= argc; i++)
68  if (argt[i] != argt[0])
69  return E_ARG_TYPE;
70 
71  if (size > value_size) {
72  value_size = size;
73  value = G_realloc(value, value_size);
74  }
75 
76  switch (argt[argc]) {
77  case CELL_TYPE: {
78  CELL *res = args[0];
79  CELL **argv = (CELL **)&args[1];
80 
81  for (i = 0; i < columns; i++) {
82  int nv = 0;
83 
84  for (j = 0; j < argc && !nv; j++) {
85  if (IS_NULL_C(&argv[j][i]))
86  nv = 1;
87  else
88  value[j] = (double)argv[j][i];
89  }
90 
91  if (nv)
92  SET_NULL_C(&res[i]);
93  else
94  res[i] = (CELL)mode(value, argc);
95  }
96  return 0;
97  }
98  case FCELL_TYPE: {
99  FCELL *res = args[0];
100  FCELL **argv = (FCELL **)&args[1];
101 
102  for (i = 0; i < columns; i++) {
103  int nv = 0;
104 
105  for (j = 0; j < argc && !nv; j++) {
106  if (IS_NULL_F(&argv[j][i]))
107  nv = 1;
108  else
109  value[j] = (double)argv[j][i];
110  }
111 
112  if (nv)
113  SET_NULL_F(&res[i]);
114  else
115  res[i] = (FCELL)mode(value, argc);
116  }
117  return 0;
118  }
119  case DCELL_TYPE: {
120  DCELL *res = args[0];
121  DCELL **argv = (DCELL **)&args[1];
122 
123  for (i = 0; i < columns; i++) {
124  int nv = 0;
125 
126  for (j = 0; j < argc && !nv; j++) {
127  if (IS_NULL_D(&argv[j][i]))
128  nv = 1;
129  else
130  value[j] = (double)argv[j][i];
131  }
132 
133  if (nv)
134  SET_NULL_D(&res[i]);
135  else
136  res[i] = (DCELL)mode(value, argc);
137  }
138  return 0;
139  }
140  default:
141  return E_INV_TYPE;
142  }
143 }
@ 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
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_mode(int argc, const int *argt, void **args)
Definition: xmode.c:57