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