1 /*
2 returns the kurtosis of the values in a distribution
3
4 input parameters:
5 data (real)
6 number of decimals in result (int, optional)
7
8 output:
9 kurtosis of the distribution (real)
10
11 registering the function:
12 CREATE AGGREGATE FUNCTION kurtosis RETURNS REAL SONAME 'udf_kurtosis.so';
13
14 getting rid of the function:
15 DROP FUNCTION kurtosis;
16
17 */
18
19
20 #ifdef STANDARD
21 #include <stdio.h>
22 #include <string.h>
23 #ifdef __WIN__
24 typedef unsigned __int64 ulonglong;
25 typedef __int64 longlong;
26 #else
27 typedef unsigned long long ulonglong;
28 typedef long long longlong;
29 #endif /*__WIN__*/
30 #else
31 #include <my_global.h>
32 #include <my_sys.h>
33 #endif
34 #include <mysql.h>
35 #include <m_ctype.h>
36 #include <m_string.h>
37 #include <math.h>
38
39 #ifdef HAVE_DLOPEN
40
41
42 #define BUFFERSIZE 1024
43
44
45
46 extern "C" {
47 my_bool kurtosis_init( UDF_INIT* initid, UDF_ARGS* args, char* message );
48 void kurtosis_deinit( UDF_INIT* initid );
49 void kurtosis_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
50 void kurtosis_clear( UDF_INIT* initid, char* is_null, char *error );
51 void kurtosis_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
52 double kurtosis( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
53 }
54
55
56 struct kurtosis_data
57 {
58 unsigned long count;
59 unsigned long abscount;
60 unsigned long pages;
61 double *values;
62 };
63
64
kurtosis_init(UDF_INIT * initid,UDF_ARGS * args,char * message)65 my_bool kurtosis_init( UDF_INIT* initid, UDF_ARGS* args, char* message )
66 {
67 if (args->arg_count < 1 || args->arg_count>2)
68 {
69 strcpy(message,"wrong number of arguments: kurtosis() requires one or two arguments");
70 return 1;
71 }
72
73 if (args->arg_type[0]!=REAL_RESULT)
74 {
75 strcpy(message,"kurtosis() requires a real as parameter 1");
76 return 1;
77 }
78
79 if (args->arg_count>1 && (args->arg_type[1]!=INT_RESULT))
80 {
81 strcpy(message,"kurtosis() requires an int as parameter 2");
82 return 1;
83 }
84
85 initid->decimals=2;
86 if (args->arg_count==2 && (*((ulong*)args->args[1])<=16))
87 {
88 initid->decimals=*((ulong*)args->args[1]);
89 }
90
91 kurtosis_data *buffer = new kurtosis_data;
92 buffer->count = 0;
93 buffer->abscount=0;
94 buffer->pages = 1;
95 buffer->values = NULL;
96
97 initid->maybe_null = 1;
98 initid->max_length = 32;
99 initid->ptr = (char*)buffer;
100
101 return 0;
102 }
103
104
kurtosis_deinit(UDF_INIT * initid)105 void kurtosis_deinit( UDF_INIT* initid )
106 {
107 kurtosis_data *buffer = (kurtosis_data*)initid->ptr;
108
109 if (buffer->values != NULL)
110 {
111 free(buffer->values);
112 buffer->values=NULL;
113 }
114 delete initid->ptr;
115 }
116
117
118
kurtosis_reset(UDF_INIT * initid,UDF_ARGS * args,char * is_null,char * is_error)119 void kurtosis_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )
120 {
121 kurtosis_clear( initid, is_null, is_error );
122 kurtosis_add( initid, args, is_null, is_error );
123 }
124
125
kurtosis_clear(UDF_INIT * initid,char * is_null,char * is_error)126 void kurtosis_clear( UDF_INIT* initid, char* is_null, char* is_error )
127 {
128 kurtosis_data *buffer = (kurtosis_data*)initid->ptr;
129 buffer->count = 0;
130 buffer->abscount=0;
131 buffer->pages = 1;
132 *is_null = 0;
133 *is_error = 0;
134
135 if (buffer->values != NULL)
136 {
137 free(buffer->values);
138 buffer->values=NULL;
139 }
140
141 buffer->values=(double *) malloc(BUFFERSIZE*sizeof(double));
142
143 }
144
145
kurtosis_add(UDF_INIT * initid,UDF_ARGS * args,char * is_null,char * is_error)146 void kurtosis_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )
147 {
148 if (args->args[0]!=NULL)
149 {
150 kurtosis_data *buffer = (kurtosis_data*)initid->ptr;
151 if (buffer->count>=BUFFERSIZE)
152 {
153 buffer->pages++;
154 buffer->count=0;
155 buffer->values=(double *) realloc(buffer->values,BUFFERSIZE*buffer->pages*sizeof(double));
156 }
157 buffer->values[buffer->abscount++] = *((double*)args->args[0]);
158 buffer->count++;
159 }
160 }
161
162
163
kurtosis(UDF_INIT * initid,UDF_ARGS * args,char * is_null,char * is_error)164 double kurtosis( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )
165 {
166 kurtosis_data* buffer = (kurtosis_data*)initid->ptr;
167
168 *is_null=1;
169 if (buffer->abscount<2 || *is_error!=0)
170 {
171 return 0.0;
172 }
173
174 ulong i;
175 double mean=0.0; double term=0.0; double stddev=0.0; double kurtosis=0.0;
176
177 for (i=0;i<buffer->abscount;++i)
178 {
179 mean+=buffer->values[i];
180 }
181
182 mean/=(double) buffer->abscount;
183
184 for (i=0;i<buffer->abscount;++i)
185 {
186 term=buffer->values[i]-mean;
187 stddev+=term*term;
188
189 kurtosis+=term*term*term*term;
190 }
191
192 stddev/=(double) buffer->abscount;
193 stddev=pow(stddev,0.5);
194
195 if (stddev==0.0)
196 {
197 return 0.0;
198 }
199
200 *is_null=0;
201 kurtosis/=((double) buffer->abscount)*stddev*stddev*stddev*stddev;
202
203 return kurtosis-3.0;
204 }
205
206 #endif
207
208