GRASS 8 Programmer's Manual 8.6.0dev(2026)-5f4f7ad06c
Loading...
Searching...
No Matches
xnmode.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_nmode(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 n = 0;
87
88 for (j = 0; j < argc; j++) {
89 if (IS_NULL_C(&argv[j][i]))
90 continue;
91 value[n++] = (double)argv[j][i];
92 }
93
94 if (!n)
95 SET_NULL_C(&res[i]);
96 else
97 res[i] = (CELL)mode(value, n);
98 }
99 if (use_heap) {
100 G_free(value);
101 }
102 return 0;
103 }
104 case FCELL_TYPE: {
105 FCELL *res = args[0];
106 FCELL **argv = (FCELL **)&args[1];
107
108 for (i = 0; i < columns; i++) {
109 int n = 0;
110
111 for (j = 0; j < argc; j++) {
112 if (IS_NULL_F(&argv[j][i]))
113 continue;
114 value[n++] = (double)argv[j][i];
115 }
116
117 if (!n)
118 SET_NULL_F(&res[i]);
119 else
120 res[i] = (FCELL)mode(value, n);
121 }
122 if (use_heap) {
123 G_free(value);
124 }
125 return 0;
126 }
127 case DCELL_TYPE: {
128 DCELL *res = args[0];
129 DCELL **argv = (DCELL **)&args[1];
130
131 for (i = 0; i < columns; i++) {
132 int n = 0;
133
134 for (j = 0; j < argc; j++) {
135 if (IS_NULL_D(&argv[j][i]))
136 continue;
137 value[n++] = (double)argv[j][i];
138 }
139
140 if (!n)
141 SET_NULL_D(&res[i]);
142 else
143 res[i] = (DCELL)mode(value, n);
144 }
145 if (use_heap) {
146 G_free(value);
147 }
148 return 0;
149 }
150 default:
151 if (use_heap) {
152 G_free(value);
153 }
154 return E_INV_TYPE;
155 }
156}
@ 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_nmode
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 xnmode.c:13