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