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