GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-8cbe8fef7c
xnmode.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_nmode(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 n = 0;
83 
84  for (j = 0; j < argc; j++) {
85  if (IS_NULL_C(&argv[j][i]))
86  continue;
87  value[n++] = (double)argv[j][i];
88  }
89 
90  if (!n)
91  SET_NULL_C(&res[i]);
92  else
93  res[i] = (CELL)mode(value, n);
94  }
95  return 0;
96  }
97  case FCELL_TYPE: {
98  FCELL *res = args[0];
99  FCELL **argv = (FCELL **)&args[1];
100 
101  for (i = 0; i < columns; i++) {
102  int n = 0;
103 
104  for (j = 0; j < argc; j++) {
105  if (IS_NULL_F(&argv[j][i]))
106  continue;
107  value[n++] = (double)argv[j][i];
108  }
109 
110  if (!n)
111  SET_NULL_F(&res[i]);
112  else
113  res[i] = (FCELL)mode(value, n);
114  }
115  return 0;
116  }
117  case DCELL_TYPE: {
118  DCELL *res = args[0];
119  DCELL **argv = (DCELL **)&args[1];
120 
121  for (i = 0; i < columns; i++) {
122  int n = 0;
123 
124  for (j = 0; j < argc; j++) {
125  if (IS_NULL_D(&argv[j][i]))
126  continue;
127  value[n++] = (double)argv[j][i];
128  }
129 
130  if (!n)
131  SET_NULL_D(&res[i]);
132  else
133  res[i] = (DCELL)mode(value, n);
134  }
135  return 0;
136  }
137  default:
138  return E_INV_TYPE;
139  }
140 }
@ 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_nmode(int argc, const int *argt, void **args)
Definition: xnmode.c:57