1
2 #include <stdlib.h>
3
4 #include <grass/gis.h>
5 #include <grass/raster.h>
6 #include <grass/calc.h>
7
8 /**********************************************************************
9 mode(x1,x2,..,xn)
10 return mode of arguments
11 **********************************************************************/
12
dcmp(const void * aa,const void * bb)13 static 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
mode(double * value,int argc)25 static double mode(double *value, int argc)
26 {
27 double mode_v;
28 int mode_n = 0;
29 int i;
30
31 qsort(value, argc, sizeof(double), dcmp);
32
33 for (i = 0; i < argc;) {
34 int n = 1;
35 double v = value[i];
36
37 for (i++; i < argc; i++) {
38 if (value[i] != v)
39 break;
40 n++;
41 }
42
43 if (n < mode_n)
44 continue;
45
46 mode_v = v;
47 mode_n = n;
48 }
49
50 return mode_v;
51 }
52
f_mode(int argc,const int * argt,void ** args)53 int f_mode(int argc, const int *argt, void **args)
54 {
55 static double *value;
56 static int value_size;
57 int size = argc * sizeof(double);
58 int i, j;
59
60 if (argc < 1)
61 return E_ARG_LO;
62
63 for (i = 1; i <= argc; i++)
64 if (argt[i] != argt[0])
65 return E_ARG_TYPE;
66
67 if (size > value_size) {
68 value_size = size;
69 value = G_realloc(value, value_size);
70 }
71
72 switch (argt[argc]) {
73 case CELL_TYPE:
74 {
75 CELL *res = args[0];
76 CELL **argv = (CELL **) & args[1];
77
78 for (i = 0; i < columns; i++) {
79 int nv = 0;
80
81 for (j = 0; j < argc && !nv; j++) {
82 if (IS_NULL_C(&argv[j][i]))
83 nv = 1;
84 else
85 value[j] = (double)argv[j][i];
86 }
87
88 if (nv)
89 SET_NULL_C(&res[i]);
90 else
91 res[i] = (CELL) mode(value, argc);
92 }
93 return 0;
94 }
95 case FCELL_TYPE:
96 {
97 FCELL *res = args[0];
98 FCELL **argv = (FCELL **) & args[1];
99
100 for (i = 0; i < columns; i++) {
101 int nv = 0;
102
103 for (j = 0; j < argc && !nv; j++) {
104 if (IS_NULL_F(&argv[j][i]))
105 nv = 1;
106 else
107 value[j] = (double)argv[j][i];
108 }
109
110 if (nv)
111 SET_NULL_F(&res[i]);
112 else
113 res[i] = (FCELL) mode(value, argc);
114 }
115 return 0;
116 }
117 case DCELL_TYPE:
118 {
119 DCELL *res = args[0];
120 DCELL **argv = (DCELL **) & args[1];
121
122 for (i = 0; i < columns; i++) {
123 int nv = 0;
124
125 for (j = 0; j < argc && !nv; j++) {
126 if (IS_NULL_D(&argv[j][i]))
127 nv = 1;
128 else
129 value[j] = (double)argv[j][i];
130 }
131
132 if (nv)
133 SET_NULL_D(&res[i]);
134 else
135 res[i] = (DCELL) mode(value, argc);
136 }
137 return 0;
138 }
139 default:
140 return E_INV_TYPE;
141 }
142 }
143