GRASS 8 Programmer's Manual 8.6.0dev(2026)-5f4f7ad06c
Loading...
Searching...
No Matches
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/**********************************************************************
9mode(x1,x2,..,xn)
10 return mode of arguments
11**********************************************************************/
12
13#define SIZE_THRESHOLD 32
14
15static 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
27static 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
60int f_mode(int argc, const int *argt, void **args)
61{
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
func_t f_mode
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
#define G_malloc(n)
Definition defs/gis.h:139
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
#define SIZE_THRESHOLD
Definition xmode.c:13