int core_oph_interlace_multi(oph_generic_param_multi * param)
{
	int i, j, k, h;
	oph_multistring *measure = param->measure, *result = param->result;
	char *ic, *oc = result->content, output_format = measure->num_measure == result->num_measure;
	for (j = 0; j < measure->numelem; ++j)	// Loop on elements
	{
		k = h = 0;
		do		// Loop on input measures
		{
			measure = param->measure + k;
			ic = measure->content;
			for (i = 0; i < measure->num_measure; ++i)	// Loop on data types
			{
				if (core_oph_type_cast(ic + j * measure->blocksize, oc, measure->type[i], result->type[output_format ? h % result->num_measure : h], NULL)) {
					pmesg(1, __FILE__, __LINE__, "Error in compute array\n");
					return 1;
				}
				ic += measure->elemsize[i];
				oc += result->elemsize[output_format ? h % result->num_measure : h];
				h++;
			}
			k++;
		}
		while (!measure->islast);
	}
	return 0;
}
int core_oph_concat2_multi(oph_generic_param_multi * param)
{
	int i, j, k = 0;
	oph_multistring *measure, *result = param->result;
	char *ic, *oc = result->content;
	do			// Loop on input measures
	{
		measure = param->measure + k;
		ic = measure->content;
		for (i = 0; i < measure->num_measure; ++i)	// Loop on data types
		{
			for (j = 0; j < measure->numelem; ++j)	// Loop on elements
			{
				if (core_oph_type_cast(ic + j * measure->blocksize, oc + j * result->blocksize, measure->type[i], result->type[i], NULL)) {
					pmesg(1, __FILE__, __LINE__, "Error in compute array\n");
					return 1;
				}
			}
			ic += measure->elemsize[i];
			oc += result->elemsize[i];
		}
		oc += (measure->numelem - 1) * result->blocksize;

		if (k)
			break;
		k = (int) measure->param;
	}
	while (k);

	return 0;
}
int core_oph_gsl_spline_multi(oph_multistring* byte_array, oph_multistring* result, oph_gsl_spline_param* spline)
{
	int j,k;
	double tmp, *pointer;
	char *in_string = byte_array->content, *out_string = result->content;
	char *in_pointer, *out_pointer;
	for (j=0;j<byte_array->num_measure;++j)
	{
		in_pointer = in_string;
		switch(byte_array->type[j])
		{
		        case OPH_DOUBLE:{
				pointer = (double*)in_string;
		                break;
		        }
			case OPH_FLOAT:{
				pointer = spline->tmp;
				for (k=0;k<byte_array->numelem;++k) { spline->tmp[k] = *(float*)in_pointer; in_pointer += byte_array->blocksize; }
		                break;
		        }
			case OPH_INT:{
				pointer = spline->tmp;
				for (k=0;k<byte_array->numelem;++k) { spline->tmp[k] = *(int*)in_pointer; in_pointer += byte_array->blocksize; }
		                break;
		        }
			case OPH_SHORT:{
				pointer = spline->tmp;
				for (k=0;k<byte_array->numelem;++k) { spline->tmp[k] = *(short*)in_pointer; in_pointer += byte_array->blocksize; }
		                break;
		        }
			case OPH_BYTE:{
				pointer = spline->tmp;
				for (k=0;k<byte_array->numelem;++k) { spline->tmp[k] = *(char*)in_pointer; in_pointer += byte_array->blocksize; }
		                break;
		        }
			case OPH_LONG:{
				pointer = spline->tmp;
				for (k=0;k<byte_array->numelem;++k) { spline->tmp[k] = *(long long*)in_pointer; in_pointer += byte_array->blocksize; }
		                break;
		        }
			default:
		                pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
		                return  -1;
		}
		if (gsl_spline_init(spline->spline, spline->old_x, pointer, byte_array->numelem)) return -1;
		out_pointer = out_string;
		for (k=0;k<result->numelem;++k)
		{
			if ((spline->new_x[k] < spline->old_x[0]) || (spline->new_x[k] > spline->old_x[byte_array->numelem-1])) tmp = NAN;
			else tmp = gsl_spline_eval(spline->spline, spline->new_x[k], spline->acc);
			if (core_oph_type_cast(&tmp, out_pointer, OPH_DOUBLE, result->type[j])) return -1;
			out_pointer += result->blocksize;
		}
		in_string += byte_array->elemsize[j];
		out_string += result->elemsize[j];
	}
	return 0;
}
int core_oph_get_subarray2(oph_get_subarray2_param * param)
{
	oph_string *measure = (oph_string *) param->measure;
	unsigned long j, k = 0;

	for (j = 0; j < measure->numelem; ++j) {
		if (param->flags[j]) {
			if (core_oph_type_cast(measure->content + j * measure->elemsize, param->result + k * param->result_elemsize, measure->type, param->result_type, NULL)) {
				pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
				return OPH_SUBSET_SYSTEM_ERR;
			}
			k++;
		}
	}

	return OPH_SUBSET_OK;
}
int core_oph_roll_up(oph_roll_up_param* param)
{
	if (param->rows < param->size)
	{
		oph_string* measure = (oph_string*)param->measure;
		unsigned long row_size = measure->numelem * param->result_elemsize;
		if (param->result_type != measure->type)
		{
			unsigned long i;
			char *input_ptr = measure->content, *output_ptr = param->result + param->rows*row_size;
			for (i=0; i<measure->numelem; ++i, input_ptr += measure->elemsize, output_ptr += param->result_elemsize)
			{
				if(core_oph_type_cast(input_ptr, output_ptr, measure->type, param->result_type))
				{
					pmesg(1,  __FILE__, __LINE__, "Unable to find result\n");
					return 1;
				}
			}
		}
		else memcpy(param->result + param->rows*row_size, measure->content, row_size);
		param->rows++;
	}
	return 0;
}
char *oph_gsl_complex_to_polar(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	if (*error) {
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}
	if (*is_null || !args->lengths[2]) {
		*length = 0;
		*is_null = 1;
		*error = 0;
		return NULL;
	}

	if (!initid->ptr) {
		initid->ptr = (char *) calloc(1, sizeof(oph_string));
		if (!initid->ptr) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		oph_stringPtr output = (oph_stringPtr) initid->ptr;

		initid->extension = (char *) calloc(1, sizeof(oph_string));
		if (!initid->extension) {
			pmesg(1, __FILE__, __LINE__, "Error allocating measure\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		oph_stringPtr measure = (oph_stringPtr) initid->extension;

		core_set_type(measure, args->args[0], &(args->lengths[0]));
		if (measure->type != OPH_COMPLEX_INT && measure->type != OPH_COMPLEX_LONG && measure->type != OPH_COMPLEX_FLOAT && measure->type == OPH_COMPLEX_DOUBLE) {
			pmesg(1, __FILE__, __LINE__, "Invalid input type: complex required\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		measure->length = &(args->lengths[2]);

		if (core_set_elemsize(measure)) {
			pmesg(1, __FILE__, __LINE__, "Error on setting element size\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (core_set_numelem(measure)) {
			pmesg(1, __FILE__, __LINE__, "Error on counting result elements\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		core_set_type(output, args->args[1], &(args->lengths[1]));
		if (output->type != OPH_COMPLEX_INT && output->type != OPH_COMPLEX_LONG && output->type != OPH_COMPLEX_FLOAT && output->type != OPH_COMPLEX_DOUBLE) {
			pmesg(1, __FILE__, __LINE__, "Invalid output type: complex required\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (core_set_elemsize(output)) {
			pmesg(1, __FILE__, __LINE__, "Error on setting element size\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		output->length = (unsigned long *) calloc(1, sizeof(unsigned long));
		if (!output->length) {
			pmesg(1, __FILE__, __LINE__, "Error allocating length\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		*(output->length) = measure->numelem * output->elemsize;
		output->numelem = measure->numelem;

		output->content = (char *) calloc(1, *(output->length));
		if (!output->content) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
	}

	oph_stringPtr output = (oph_stringPtr) initid->ptr;
	oph_stringPtr measure = (oph_stringPtr) initid->extension;
	measure->content = args->args[2];

	int i, j = 0;
	gsl_complex z;
	double val1, val2;
	switch (measure->type) {
		case OPH_COMPLEX_INT:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((int *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((int *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		case OPH_COMPLEX_LONG:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((long long *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((long long *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		case OPH_COMPLEX_FLOAT:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = (double) ((float *) (args->args[2]))[i];	//real part
						z.dat[1] = (double) ((float *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		case OPH_COMPLEX_DOUBLE:
			switch (output->type) {
				case OPH_COMPLEX_INT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(int)), OPH_DOUBLE, OPH_INT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_LONG:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(long long)), OPH_DOUBLE, OPH_LONG, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_FLOAT:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(float)), OPH_DOUBLE, OPH_FLOAT, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				case OPH_COMPLEX_DOUBLE:
					for (i = 0; i < output->numelem * 2; i += 2) {
						z.dat[0] = ((double *) (args->args[2]))[i];	//real part
						z.dat[1] = ((double *) (args->args[2]))[i + 1];	//imag part
						val1 = gsl_complex_abs(z);
						val2 = gsl_complex_arg(z);
						if (core_oph_type_cast(&val1, output->content + (j * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						if (core_oph_type_cast(&val2, output->content + ((j + 1) * sizeof(double)), OPH_DOUBLE, OPH_DOUBLE, NULL)) {
							pmesg(1, __FILE__, __LINE__, "Error casting output\n");
							*length = 0;
							*is_null = 0;
							*error = 1;
							return NULL;
						}
						j += 2;
					}
					break;
				default:
					pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
					*length = 0;
					*is_null = 0;
					*error = 1;
					return NULL;
			}
			break;
		default:
			pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
	}

	*length = *(output->length);
	*error = 0;
	*is_null = 0;

	return output->content;
}
int core_oph_predicate2(oph_stringPtr byte_array, char *result)
{
	unsigned long i, occurrence, occurrence_number = 0;
	unsigned short r;
	double res, temporary;
	oph_predicate2_param *_result = (oph_predicate2_param *) result;
	if (_result->occurrence < 0)
		occurrence = 1;
	else
		occurrence = (unsigned long) _result->occurrence;
	switch (byte_array->type) {
		case OPH_DOUBLE:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((double *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((double *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_FLOAT:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((float *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((float *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_INT:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((int *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((int *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_SHORT:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((short *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((short *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_BYTE:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((char *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((char *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		case OPH_LONG:
			{
				for (i = _result->occurrence < 0 ? byte_array->numelem - 1 : 0; (0 <= i) && (i < byte_array->numelem); _result->occurrence < 0 ? --i : ++i) {
					res = evaluator_evaluate_x(_result->f[1], *((long long *) (byte_array->content + i * byte_array->elemsize)));
					switch (_result->op) {
						case OPH_GREATER_THAN_ZERO:
							{
								r = res > 0.0;
								break;
							}
						case OPH_LESS_THAN_ZERO:
							{
								r = res < 0.0;
								break;
							}
						case OPH_EQUAL_TO_ZERO:
							{
								r = res == 0.0;
								break;
							}
						case OPH_GREATER_OR_EQUAL_TO_ZERO:
							{
								r = res >= 0.0;
								break;
							}
						case OPH_LESS_OR_EQUAL_TO_ZERO:
							{
								r = res <= 0.0;
								break;
							}
						case OPH_NOT_EQUAL_TO_ZERO:
							{
								r = res != 0.0;
								break;
							}
						case OPH_NULL:
							{
								r = isnan(res);
								break;
							}
						default:
							pmesg(1, __FILE__, __LINE__, "Comparison value non recognized\n");
							return -1;
					}
					if (occurrence && r) {
						occurrence_number++;
						if (occurrence != occurrence_number)
							r = 0;
					}
					temporary = evaluator_evaluate_x(_result->f[r ? 2 : 3], *((long long *) (byte_array->content + i * byte_array->elemsize)));
					if (core_oph_type_cast(&temporary, (((char *) _result->f[0]) + i * _result->result_elemsize), OPH_DOUBLE, _result->result_type, byte_array->missingvalue)) {
						pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
						return 1;
					}
				}
				break;
			}
		default:
			pmesg(1, __FILE__, __LINE__, "Type non recognized\n");
			return -1;
	}
	return 0;
}
char* oph_reduce2(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
        oph_request inp_req;

        long long hierarchy_set = 0;
        long long result_length = 0;
	long long block_size = 1, numelement_to_reduce, max_size = 0;
        int i = 0, j;
	unsigned long lll, olll, k;

	int (*core_oph_oper) (oph_stringPtr byte_array, char *res);

	if (args->arg_count > 5)
	{
		block_size = *((long long*)(args->args[5]));
		if(block_size<=0)
		{
		        pmesg(1,  __FILE__, __LINE__, "Wrong arguments to oph_reduce2 function\n");
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
	}

        core_set_type(&(inp_req.measure), args->args[0], &(args->lengths[0]));
	if(!inp_req.measure.type){
                pmesg(1,  __FILE__, __LINE__, "Unable to recognize measures type\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }

        if(args->arg_count < 4){
                core_set_oper(&inp_req, NULL, 0);
        }
        else{
                core_set_oper(&inp_req, args->args[3], &(args->lengths[3]));
        }

	if(!inp_req.oper){
                pmesg(1,  __FILE__, __LINE__, "Operator not recognized\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }

        core_set_hier(&inp_req, NULL, 0);
	if(!inp_req.hier){
                pmesg(1,  __FILE__, __LINE__, "Hierarchy not recognized\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }

        inp_req.measure.content = args->args[2];
        inp_req.measure.length = &(args->lengths[2]);

	if(core_set_elemsize(&(inp_req.measure))){
                pmesg(1,  __FILE__, __LINE__, "Unable to recognize measures type\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }

        if(core_set_numelem(&(inp_req.measure))){
        	pmesg(1,  __FILE__, __LINE__, "Error on counting elements\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }

	if (args->arg_count < 6)
		numelement_to_reduce = (long long)inp_req.measure.numelem;
	else
	{
		if(((long long)inp_req.measure.numelem) % block_size)
		{
			pmesg(1,  __FILE__, __LINE__, "Error: 'block_size' %lld not applicable on %ld elements\n", block_size, inp_req.measure.numelem);
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
		numelement_to_reduce = (long long)inp_req.measure.numelem / block_size;
	}

	if (args->arg_count > 6) max_size = *((long long*)(args->args[6]));
	if (!max_size) max_size = numelement_to_reduce;

        if((args->arg_count < 5) || !args->args[4])
                hierarchy_set = (long long) (inp_req.measure.numelem);
        else
	{
		hierarchy_set = *((long long*)(args->args[4]));
		if (!hierarchy_set || (hierarchy_set>max_size)) hierarchy_set = max_size;
		else if ((hierarchy_set<0) || (max_size%hierarchy_set)) 
		{
			pmesg(1,  __FILE__, __LINE__, "Wrong parameter value 'count' %lld\n",hierarchy_set);
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
        }

        /* Check if I can apply the hierarchy */
        if(numelement_to_reduce%hierarchy_set)
	{
        	pmesg(1,  __FILE__, __LINE__, "Error: hierarchy_set %lld not applicable on %ld elements\n", hierarchy_set, inp_req.measure.numelem);
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }

        result_length = inp_req.measure.numelem/hierarchy_set;

	oph_type result_type = inp_req.measure.type;
	size_t result_size = inp_req.measure.elemsize;
        switch(inp_req.oper)
	{
                case OPH_COUNT:
			core_oph_oper = core_oph_count;
			break;
                case OPH_MAX:
			core_oph_oper = core_oph_max;
			break;
                case OPH_MIN:
			core_oph_oper = core_oph_min;
			break;
                case OPH_SUM:
			core_oph_oper = core_oph_sum;
			break;
		case OPH_AVG:
			core_oph_oper = core_oph_avg;
			break;
		case OPH_STD:
			core_oph_oper = core_oph_std;
			break;
		case OPH_VAR:
			core_oph_oper = core_oph_var;
			break;
		case OPH_CMOMENT:
			core_oph_oper = core_oph_cmoment;
			break;
		case OPH_ACMOMENT:
			core_oph_oper = core_oph_acmoment;
			break;
		case OPH_RMOMENT:
			core_oph_oper = core_oph_rmoment;
			break;
		case OPH_ARMOMENT:
			core_oph_oper = core_oph_armoment;
			break;
		case OPH_QUANTILE:
			core_oph_oper = core_oph_quantile;
			break;
		default:
                        pmesg(1,  __FILE__, __LINE__, "Unable to recognize operator\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
                        return NULL;
        }
	switch(inp_req.oper)
	{
		case OPH_COUNT:
			result_type = OPH_LONG;
			result_size = core_sizeof(OPH_LONG);
			break;
		case OPH_AVG:
		case OPH_STD:
		case OPH_VAR:
		case OPH_CMOMENT:
		case OPH_ACMOMENT:
		case OPH_RMOMENT:
		case OPH_ARMOMENT:
		case OPH_QUANTILE:
			if(inp_req.measure.type == OPH_BYTE || inp_req.measure.type == OPH_SHORT || inp_req.measure.type == OPH_INT)
			{
				result_type = OPH_FLOAT;
				result_size = core_sizeof(OPH_FLOAT);
			}
			else if(inp_req.measure.type == OPH_LONG)
			{
				result_type = OPH_DOUBLE;
				result_size = core_sizeof(OPH_DOUBLE);
			}
			break;
		default:;
	}

	oph_string output_array;
        core_set_type(&output_array, args->args[1], &(args->lengths[1]));
	if(!output_array.type){
                pmesg(1,  __FILE__, __LINE__, "Unable to recognize measures type\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }
	if(core_set_elemsize(&output_array)){
                pmesg(1,  __FILE__, __LINE__, "Unable to recognize measures type\n");
                *length=0;
                *is_null=0;
                *error=1;
                return NULL;
        }
	olll = result_length*output_array.elemsize;

        /* Allocate the right space for the result set */
	oph_reduce2_param* tmp;
        if(!initid->ptr)
	{
                tmp = (oph_reduce2_param*)malloc(sizeof(oph_reduce2_param));
		initid->ptr = (char*)tmp;
		if(!initid->ptr)
		{
			pmesg(1,  __FILE__, __LINE__, "Error allocating measures string\n");
	                *length=0;
		        *is_null=0;
        		*error=1;
                	return NULL;
		}
		tmp->result = (char *)malloc(olll);
		if(!tmp->result)
		{
			pmesg(1,  __FILE__, __LINE__, "Error allocating measures string\n");
	                *length=0;
		        *is_null=0;
        		*error=1;
                	return NULL;
		}
		if (block_size>1)
		{
			tmp->temp = (char *)malloc(hierarchy_set*inp_req.measure.elemsize);
			if(!tmp->temp)
			{
				pmesg(1,  __FILE__, __LINE__, "Error allocating measures string\n");
			        *length=0;
				*is_null=0;
				*error=1;
		        	return NULL;
			}
		}
		else tmp->temp = NULL;
		if (inp_req.oper == OPH_QUANTILE)
		{
			tmp->temp2 = (char *)malloc(*inp_req.measure.length);
			if(!tmp->temp2)
			{
				pmesg(1,  __FILE__, __LINE__, "Error allocating measures string\n");
				*length=0;
				*is_null=0;
				*error=1;
				return NULL;
			}
		}
		else tmp->temp2 = NULL;
        }
	else tmp = (oph_reduce2_param*)initid->ptr;

	oph_string curr_array;
        curr_array.type = inp_req.measure.type;
        curr_array.elemsize = inp_req.measure.elemsize;
        curr_array.numelem = hierarchy_set;
        curr_array.length = &lll;
        *curr_array.length = (unsigned long)(hierarchy_set*curr_array.elemsize);
	if(args->arg_count > 7)
	{
		curr_array.param = *((double*)(args->args[7]));
		if (curr_array.param<0)
		{
			pmesg(1,  __FILE__, __LINE__, "Wrong parameter value 'order' %f\n",curr_array.param);
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
	}
	else curr_array.param = 2.0;
	curr_array.extend = (void*)tmp->temp2;

	char temporary[result_size];
        for(i=0; i < result_length; i++)
	{
		if (block_size==1) curr_array.content = inp_req.measure.content+(i*(*curr_array.length));
		else
		{
			for (j=0, k=0; k<inp_req.measure.numelem; ++k) // Loop on the input array
				if (k%block_size + (k/(block_size*hierarchy_set))*block_size == i)
				{
					memcpy(tmp->temp+j*inp_req.measure.elemsize,inp_req.measure.content+k*inp_req.measure.elemsize,inp_req.measure.elemsize);
					++j;
					if (j>=hierarchy_set) break; // Found all the elements to be reduced
				}
			if (k>=inp_req.measure.numelem)
			{
				pmesg(1,  __FILE__, __LINE__, "Unable to find an element to be aggregated\n");
				*length=0;
				*is_null=0;
				*error=1;
				return NULL;
			}
			curr_array.content = tmp->temp;
		}
                if(core_oph_oper(&curr_array, temporary))
		{
                        pmesg(1,  __FILE__, __LINE__, "Unable to find result\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
			return NULL;
                }
		if(core_oph_type_cast(temporary, tmp->result+i*output_array.elemsize, result_type, output_array.type))
		{
                        pmesg(1,  __FILE__, __LINE__, "Unable to find result\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
			return NULL;
                }
                pmesg(3,  __FILE__, __LINE__, "RES: %f\n", *(double*)(tmp->result));
        }
        *length = (unsigned long) (olll);

	*is_null=0;
	*error=0;

        return tmp->result;
}
int core_oph_gsl_fit_linear_multi(oph_multistring * byte_array, oph_multistring * result, oph_gsl_fit_linear_param * fit)
{
	int j, k;
	double tmp, *pointer;
	double cov00, cov01, cov11, sumsq;
	char *in_string = byte_array->content, *out_string = result->content;
	char *in_pointer, *out_pointer;
	for (j = 0; j < byte_array->num_measure; ++j) {
		in_pointer = in_string;
		switch (byte_array->type[j]) {
			case OPH_DOUBLE:{
					pointer = (double *) in_string;
					break;
				}
			case OPH_FLOAT:{
					pointer = fit->tmp;
					for (k = 0; k < byte_array->numelem; ++k) {
						fit->tmp[k] = *(float *) in_pointer;
						in_pointer += byte_array->blocksize;
					}
					break;
				}
			case OPH_INT:{
					pointer = fit->tmp;
					for (k = 0; k < byte_array->numelem; ++k) {
						fit->tmp[k] = *(int *) in_pointer;
						in_pointer += byte_array->blocksize;
					}
					break;
				}
			case OPH_SHORT:{
					pointer = fit->tmp;
					for (k = 0; k < byte_array->numelem; ++k) {
						fit->tmp[k] = *(short *) in_pointer;
						in_pointer += byte_array->blocksize;
					}
					break;
				}
			case OPH_BYTE:{
					pointer = fit->tmp;
					for (k = 0; k < byte_array->numelem; ++k) {
						fit->tmp[k] = *(char *) in_pointer;
						in_pointer += byte_array->blocksize;
					}
					break;
				}
			case OPH_LONG:{
					pointer = fit->tmp;
					for (k = 0; k < byte_array->numelem; ++k) {
						fit->tmp[k] = *(long long *) in_pointer;
						in_pointer += byte_array->blocksize;
					}
					break;
				}
			default:
				pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
				return -1;
		}
		if (gsl_fit_linear(fit->old_x, 1, pointer, 1, fit->n, &fit->c[0], &fit->c[1], &cov00, &cov01, &cov11, &sumsq))
			return -1;
		out_pointer = out_string;
		for (k = 0; k < result->numelem; ++k) {
			tmp = fit->c[0] + fit->new_x[k] * fit->c[1];
			if (core_oph_type_cast(&tmp, out_pointer, OPH_DOUBLE, result->type[j], byte_array->missingvalue))
				return -1;
			out_pointer += result->blocksize;
		}
		in_string += byte_array->elemsize[j];
		out_string += result->elemsize[j];
	}
	return 0;
}
char* oph_extract(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
        int res = 0;
	oph_extract_param* param;
	oph_string *measure, *index_list;

	if (*error)
	{
	        *length=0;
	        *is_null=0;
	        *error=1;
	        return NULL;
	}
	if (*is_null || !args->lengths[2] || !args->lengths[3])
	{
	        *length=0;
	        *is_null=1;
	        *error=0;
	        return NULL;
	}

	if(!initid->ptr)
	{
		initid->ptr=(char*)malloc(sizeof(oph_extract_param));
		if(!initid->ptr)
		{
			pmesg(1, __FILE__, __LINE__, "Error allocating oph_extract_param\n");
			param->error = 1;
			*length=0;
        	        *is_null=0;
                	*error=1;
	                return NULL;
        	}
		param = (oph_extract_param*)initid->ptr;
		param->measure = NULL;
		param->index_list = NULL;
		param->result = NULL;
		param->error = 0;
	}
	else param = (oph_extract_param*)initid->ptr;

	if (!param->error && !param->measure && !param->index_list)
	{
		// Measure
		param->measure = malloc(sizeof(oph_string));
		if(!param->measure)
		{
			pmesg(1, __FILE__, __LINE__, "Error allocating oph_string\n");
			param->error = 1;
			*length=0;
        	        *is_null=0;
                	*error=1;
	                return NULL;
        	}
		measure = (oph_string*)param->measure;
		measure->length = &(args->lengths[2]);
		res = core_set_type(measure, args->args[0], &(args->lengths[0]));
		if (res)
		{
			pmesg(1,  __FILE__, __LINE__, "Error on setting the data type\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
		if (core_set_elemsize(measure))
		{
			pmesg(1,  __FILE__, __LINE__, "Error on setting data element size\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
		if(core_set_numelem(measure))
		{
			pmesg(1,  __FILE__, __LINE__, "Error on counting elements\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}

		// Index list
		param->index_list = malloc(sizeof(oph_string));
		if(!param->index_list)
		{
			pmesg(1, __FILE__, __LINE__, "Error allocating oph_string\n");
			param->error = 1;
			*length=0;
        	        *is_null=0;
                	*error=1;
	                return NULL;
        	}
		index_list = (oph_string*)param->index_list;
		index_list->length = &(args->lengths[3]);
		char long_type[10];
		sprintf(long_type,"oph_long");
		unsigned long len = strlen(long_type); 
		res = core_set_type(index_list, long_type, &len); // Index are always oph_long, i.e. long long
		if (res)
		{
			pmesg(1,  __FILE__, __LINE__, "Error on setting the data type\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
		if (core_set_elemsize(index_list))
		{
			pmesg(1,  __FILE__, __LINE__, "Error on setting data element size\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
		if(core_set_numelem(index_list))
		{
			pmesg(1,  __FILE__, __LINE__, "Error on counting elements\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}

		oph_string output_array;
		core_set_type(&output_array, args->args[1], &(args->lengths[1]));
		if(!output_array.type){
		        pmesg(1,  __FILE__, __LINE__, "Unable to recognize measures type\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
		if(core_set_elemsize(&output_array)){
		        pmesg(1,  __FILE__, __LINE__, "Unable to recognize measures type\n");
			param->error = 1;
		        *length=0;
		        *is_null=0;
		        *error=1;
		        return NULL;
		}
		param->result_type = output_array.type;
		param->result_elemsize = output_array.elemsize;

		// Output
		param->length = output_array.elemsize * index_list->numelem; // bytes
		if (!param->length)
		{
			*length=0;
        	        *is_null=1;
                	*error=0;
	                return NULL;
        	}
		param->result = (char*)malloc(param->length);
		if(!param->result)
		{
			pmesg(1, __FILE__, __LINE__, "Error allocating result\n");
			param->error = 1;
			*length=0;
        	        *is_null=0;
                	*error=1;
	                return NULL;
        	}
	}
	else
	{
		measure = (oph_string*)param->measure;
		index_list = (oph_string*)param->index_list;
	}

	// Set measure->content
        measure->content = args->args[2]; // Input
	if (!measure->content)
	{
                *length=0;
                *is_null=1;
                *error=0;
                return NULL;
        }
	// Set index_list->content
	index_list->content = args->args[3]; // Input
	if (!index_list->content)
	{
	        *length=0;
	        *is_null=1;
	        *error=0;
	        return NULL;
	}

	long long i, index;
	char temporary[measure->elemsize];
	for (i=0; i<index_list->numelem; ++i)
	{
		index = *((long long*)(index_list->content+i*index_list->elemsize))-1; // Non 'C'-like indexing
		memcpy(temporary, measure->content+index*measure->elemsize, measure->elemsize);
		if(core_oph_type_cast(temporary, param->result+i*param->result_elemsize, measure->type, param->result_type))
		{
                        pmesg(1,  __FILE__, __LINE__, "Unable to find result\n");
                        *length=0;
                        *is_null=0;
                        *error=1;
			return NULL;
                }
	}

	*length=param->length;
	*is_null=0;
        *error=0;
	return (result=param->result);
}
char *oph_gsl_complex_get_abs(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	if (*error) {
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}
	if (*is_null || !args->lengths[2]) {
		*length = 0;
		*is_null = 1;
		*error = 0;
		return NULL;
	}

	oph_generic_param_multi *param;
	if (!initid->ptr) {
		param = (oph_generic_param_multi *) malloc(sizeof(oph_generic_param_multi));
		if (!param) {
			pmesg(1, __FILE__, __LINE__, "Error in allocating parameters\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		param->measure = NULL;
		param->result = NULL;
		param->error = 0;
		param->extend = NULL;

		initid->ptr = (char *) param;
	} else
		param = (oph_generic_param_multi *) initid->ptr;

	if (param->error) {
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	oph_multistring *measure;
	if (!param->error && !param->measure) {
		if (core_set_oph_multistring(&measure, args->args[0], &(args->lengths[0]))) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		if (!measure->islast) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Wrong number of input measure\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		measure->length = args->lengths[2];
		if (measure->length % measure->blocksize) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Wrong input type or data corrupted\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		measure->numelem = measure->length / measure->blocksize;

		param->measure = measure;
	} else
		measure = param->measure;

	measure->content = args->args[2];

	oph_multistring *output;
	if (!param->error && !param->result) {
		if (core_set_oph_multistring(&output, args->args[1], &(args->lengths[1]))) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		if (output->num_measure != measure->num_measure) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Wrong number of output data type\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		output->numelem = measure->numelem;
		output->length = output->numelem * output->blocksize;

		output->content = (char *) malloc(output->length);
		if (!output->content) {
			param->error = 1;
			pmesg(1, __FILE__, __LINE__, "Error allocating measures string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		param->result = output;
	} else
		output = param->result;

	int i, k;
	gsl_complex z;
	double tmp = 0;
	size_t run_sum1 = 0;
	size_t run_sum2 = 0;
	for (i = 0; i < measure->num_measure; i++) {
		switch (measure->type[i]) {
			case OPH_COMPLEX_INT:
				for (k = 0; k < i; k++) {
					run_sum1 += measure->elemsize[k];
					run_sum2 += output->elemsize[k];
				}
				for (k = 0; k < measure->numelem; k++) {
					z.dat[0] = (double) *((int *) (measure->content + (k * measure->blocksize) + run_sum1));	//real part
					z.dat[1] = (double) *((int *) (measure->content + (k * measure->blocksize) + run_sum1 + sizeof(int)));	//imag part
					tmp = gsl_complex_abs(z);
					if (core_oph_type_cast(&tmp, output->content + (k * output->blocksize) + run_sum2, OPH_DOUBLE, output->type[i], NULL)) {
						param->error = 1;
						pmesg(1, __FILE__, __LINE__, "Error casting output\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
					}
				}
				run_sum1 = 0;
				run_sum2 = 0;
				break;
			case OPH_COMPLEX_LONG:
				for (k = 0; k < i; k++) {
					run_sum1 += measure->elemsize[k];
					run_sum2 += output->elemsize[k];
				}
				for (k = 0; k < measure->numelem; k++) {
					z.dat[0] = (double) *((long long *) (measure->content + (k * measure->blocksize) + run_sum1));	//real part
					z.dat[1] = (double) *((long long *) (measure->content + (k * measure->blocksize) + run_sum1 + sizeof(long long)));	//imag part
					tmp = gsl_complex_abs(z);
					if (core_oph_type_cast(&tmp, output->content + (k * output->blocksize) + run_sum2, OPH_DOUBLE, output->type[i], NULL)) {
						param->error = 1;
						pmesg(1, __FILE__, __LINE__, "Error casting output\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
					}
				}
				run_sum1 = 0;
				run_sum2 = 0;
				break;
			case OPH_COMPLEX_FLOAT:
				for (k = 0; k < i; k++) {
					run_sum1 += measure->elemsize[k];
					run_sum2 += output->elemsize[k];
				}
				for (k = 0; k < measure->numelem; k++) {
					z.dat[0] = (double) *((float *) (measure->content + (k * measure->blocksize) + run_sum1));	//real part
					z.dat[1] = (double) *((float *) (measure->content + (k * measure->blocksize) + run_sum1 + sizeof(float)));	//imag part
					tmp = gsl_complex_abs(z);
					if (core_oph_type_cast(&tmp, output->content + (k * output->blocksize) + run_sum2, OPH_DOUBLE, output->type[i], NULL)) {
						param->error = 1;
						pmesg(1, __FILE__, __LINE__, "Error casting output\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
					}
				}
				run_sum1 = 0;
				run_sum2 = 0;
				break;
			case OPH_COMPLEX_DOUBLE:
				for (k = 0; k < i; k++) {
					run_sum1 += measure->elemsize[k];
					run_sum2 += output->elemsize[k];
				}
				for (k = 0; k < measure->numelem; k++) {
					z.dat[0] = *((double *) (measure->content + (k * measure->blocksize) + run_sum1));	//real part
					z.dat[1] = *((double *) (measure->content + (k * measure->blocksize) + run_sum1 + sizeof(double)));	//imag part
					tmp = gsl_complex_abs(z);
					if (core_oph_type_cast(&tmp, output->content + (k * output->blocksize) + run_sum2, OPH_DOUBLE, output->type[i], NULL)) {
						param->error = 1;
						pmesg(1, __FILE__, __LINE__, "Error casting output\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
					}
				}
				run_sum1 = 0;
				run_sum2 = 0;
				break;
			default:
				param->error = 1;
				pmesg(1, __FILE__, __LINE__, "Input Type not allowed\n");
				*length = 0;
				*is_null = 0;
				*error = 1;
				return NULL;
		}
	}

	*length = output->length;
	*error = 0;
	*is_null = 0;

	return (result = output->content);
}
char *oph_aggregate_operator(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	int i;

	if (*error != 0) {
		pmesg(1, __FILE__, __LINE__, "Error on adding elements\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}
	oph_agg_oper_data *dat = (oph_agg_oper_data *) initid->ptr;
	oph_stringPtr res = (oph_stringPtr) & (dat->result.measure);
	if (!res->content) {
		*error = 0;
		*is_null = 0;
		return NULL;
	}

	double missingvalue = 0, *pointer = NULL;
	if ((args->arg_count > 4) && args->args[4]) {
		missingvalue = *((double *) (args->args[4]));
		pointer = &missingvalue;
	}

	switch (dat->result.oper) {
		case OPH_COUNT:
		case OPH_MAX:
		case OPH_MIN:
		case OPH_SUM:
			break;
		case OPH_AVG:
			{
				switch (res->type) {
					case OPH_DOUBLE:{
							double *position = (double *) res->content;
							for (i = 0; i < res->numelem; i++) {
								if (!dat->count[i])
									*position = pointer ? missingvalue : NAN;
								else
									*position /= dat->count[i];
								position++;
							}
							break;
						}
					case OPH_FLOAT:{
							float *position = (float *) res->content;
							for (i = 0; i < res->numelem; i++) {
								if (!dat->count[i])
									*position = pointer ? (float) missingvalue : NAN;
								else
									*position /= dat->count[i];
								position++;
							}
							break;
						}
					case OPH_INT:{
							float accumulator[res->numelem];
							int *position = (int *) res->content;
							for (i = 0; i < res->numelem; i++) {
								if (!dat->count[pointer ? i : 0])
									accumulator[i] = (float) missingvalue;
								else
									accumulator[i] = (float) (*position) / dat->count[pointer ? i : 0];	// Only count[0] is updated to improve performance
								position++;
							}
							free(res->content);
							unsigned long length = res->numelem * core_sizeof(OPH_FLOAT);
							res->content = malloc(length);
							memcpy(res->content, accumulator, length);
							break;
						}
					case OPH_LONG:{
							double accumulator[res->numelem];
							long long *position = (long long *) res->content;
							for (i = 0; i < res->numelem; i++) {
								if (!dat->count[pointer ? i : 0])
									accumulator[i] = missingvalue;
								else
									accumulator[i] = (double) (*position) / dat->count[pointer ? i : 0];	// Only count[0] is updated to improve performance
								position++;
							}
							free(res->content);
							unsigned long length = res->numelem * core_sizeof(OPH_DOUBLE);
							res->content = malloc(length);
							memcpy(res->content, accumulator, length);
							break;
						}
					case OPH_SHORT:{
							float accumulator[res->numelem];
							short *position = (short *) res->content;
							for (i = 0; i < res->numelem; i++) {
								if (!dat->count[pointer ? i : 0])
									accumulator[i] = (float) missingvalue;
								else
									accumulator[i] = (float) (*position) / dat->count[pointer ? i : 0];	// Only count[0] is updated to improve performance
								position++;
							}
							free(res->content);
							unsigned long length = res->numelem * core_sizeof(OPH_FLOAT);
							res->content = malloc(length);
							memcpy(res->content, accumulator, length);
							break;
						}
					case OPH_BYTE:{
							float accumulator[res->numelem];
							char *position = (char *) res->content;
							for (i = 0; i < res->numelem; i++) {
								if (!dat->count[pointer ? i : 0])
									accumulator[i] = (float) missingvalue;
								else
									accumulator[i] = (float) (*position) / dat->count[pointer ? i : 0];	// Only count[0] is updated to improve performance
								position++;
							}
							free(res->content);
							unsigned long length = res->numelem * core_sizeof(OPH_FLOAT);
							res->content = malloc(length);
							memcpy(res->content, accumulator, length);
							break;
						}
					default:
						pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
				}
				break;
			}
		default:
			pmesg(1, __FILE__, __LINE__, "Operation not recognized\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
	}

	for (i = 0; i < res->numelem; ++i) {
		if (core_oph_type_cast(res->content + i * res->elemsize, dat->result_data + i * dat->result_size, res->type, dat->result_type, pointer)) {
			pmesg(1, __FILE__, __LINE__, "Unable to find result\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
	}

	*length = dat->result_length;
	*error = 0;
	*is_null = 0;

	return (result = dat->result_data);
}
int core_oph_sum_scalar2_multi(oph_multistring* byte_array, double *scalars, oph_multistring* result, int id)
{
        int i,j,js,je;
	double tmp;

	if (id<=0) { js=0; je=byte_array->num_measure; }
	else if (id>byte_array->num_measure)
	{
		pmesg(1, __FILE__, __LINE__, "Index out of boundaries\n");
		return -1;
	}
	else { js=id-1; je=id; }

	for (j=js;j<je;++j)
	{
		switch(byte_array->type[j])
		{
		        case OPH_DOUBLE:{
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp = (*(double*)((byte_array->content)+(i*byte_array->elemsize[j])) + scalars[0]);
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
				break;
			}
		        case OPH_FLOAT:{
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp = (double) (*(float*)((byte_array->content)+(i*byte_array->elemsize[j])) + scalars[0]);
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
				break;
			}
		        case OPH_INT:{
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp = (double) (*(int*)((byte_array->content)+(i*byte_array->elemsize[j])) + scalars[0]);
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
				break;
			}
		        case OPH_SHORT:{
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp = (double) (*(short*)((byte_array->content)+(i*byte_array->elemsize[j])) + scalars[0]);
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
				break;
			}
		        case OPH_BYTE:{
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp = (double) (*(char*)((byte_array->content)+(i*byte_array->elemsize[j])) + scalars[0]);
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
				break;
			}
		        case OPH_LONG:{
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp = (double) (*(long long*)((byte_array->content)+(i*byte_array->elemsize[j])) + scalars[0]);
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
				break;
			}
			case OPH_COMPLEX_INT:
			{
#ifdef GSL_SUPPORTED
				gsl_complex a,b,c;
				for (i = 0; i < (byte_array->numelem)*2; i+=2){
					a.dat[0] = (double) ((int *)(byte_array->content))[i];    //real part
					a.dat[1] = (double) ((int *)(byte_array->content))[i+1];  //imag part
					b.dat[0] = scalars[0]; //real part
					b.dat[1] = scalars[1]; //imag part
					c = gsl_complex_add(a,b);
					if(core_oph_type_cast(c.dat, (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
					if(core_oph_type_cast(c.dat+1, (result->content)+((i+1)*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
#else
				pmesg(1, __FILE__, __LINE__, "Operation not allowed\n");
#endif
				break;
			}
			case OPH_COMPLEX_LONG:
			{
#ifdef GSL_SUPPORTED
				gsl_complex a,b,c;
				for (i = 0; i < (byte_array->numelem)*2; i+=2){
					a.dat[0] = (double) ((long long *)(byte_array->content))[i];    //real part
					a.dat[1] = (double) ((long long *)(byte_array->content))[i+1];  //imag part
					b.dat[0] = scalars[0]; //real part
					b.dat[1] = scalars[1]; //imag part
					c = gsl_complex_add(a,b);
					if(core_oph_type_cast(c.dat, (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
					if(core_oph_type_cast(c.dat+1, (result->content)+((i+1)*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
#else
				pmesg(1, __FILE__, __LINE__, "Operation not allowed\n");
#endif
				break;
			}
			case OPH_COMPLEX_FLOAT:
			{
#ifdef GSL_SUPPORTED
				gsl_complex a,b,c;
				for (i = 0; i < (byte_array->numelem)*2; i+=2){
					a.dat[0] = (double) ((float *)(byte_array->content))[i];    //real part
					a.dat[1] = (double) ((float *)(byte_array->content))[i+1];  //imag part
					b.dat[0] = scalars[0]; //real part
					b.dat[1] = scalars[1]; //imag part
					c = gsl_complex_add(a,b);
					if(core_oph_type_cast(c.dat, (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
					if(core_oph_type_cast(c.dat+1, (result->content)+((i+1)*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
#else
				pmesg(1, __FILE__, __LINE__, "Operation not allowed\n");
#endif
				break;
			}
			case OPH_COMPLEX_DOUBLE:
			{
#ifdef GSL_SUPPORTED
				gsl_complex a,b,c;
				for (i = 0; i < (byte_array->numelem)*2; i+=2){
					a.dat[0] = ((double *)(byte_array->content))[i];    //real part
					a.dat[1] = ((double *)(byte_array->content))[i+1];  //imag part
					b.dat[0] = scalars[0]; //real part
					b.dat[1] = scalars[1]; //imag part
					c = gsl_complex_add(a,b);
					if(core_oph_type_cast(c.dat, (result->content)+(i*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
					if(core_oph_type_cast(c.dat+1, (result->content)+((i+1)*result->elemsize[j]), OPH_DOUBLE, result->type[j])) return -1;
				}
#else
				pmesg(1, __FILE__, __LINE__, "Operation not allowed\n");
#endif
				break;
			}
		        default:
		                pmesg(1, __FILE__, __LINE__, "Type non recognized\n");
		                return -1;
		}
	}
        return 0;
}
int core_oph_sum_scalar_multi(oph_multistring * byte_array, double scalar, oph_multistring * result, int id)
{
	int i, j, js, je;
	double tmp;

	if (id <= 0) {
		js = 0;
		je = byte_array->num_measure;
	} else if (id > byte_array->num_measure) {
		pmesg(1, __FILE__, __LINE__, "Index out of boundaries\n");
		return -1;
	} else {
		js = id - 1;
		je = id;
	}

	for (j = js; j < je; ++j) {
		switch (byte_array->type[j]) {
			case OPH_DOUBLE:{
					for (i = 0; i < byte_array->numelem; i++) {
						tmp = (*(double *) ((byte_array->content) + (i * byte_array->elemsize[j])) + scalar);
						if (core_oph_type_cast((void *) (&tmp), (result->content) + (i * result->elemsize[j]), OPH_DOUBLE, result->type[j], byte_array->missingvalue))
							return -1;
					}
					break;
				}
			case OPH_FLOAT:{
					for (i = 0; i < byte_array->numelem; i++) {
						tmp = (double) (*(float *) ((byte_array->content) + (i * byte_array->elemsize[j])) + scalar);
						if (core_oph_type_cast((void *) (&tmp), (result->content) + (i * result->elemsize[j]), OPH_DOUBLE, result->type[j], byte_array->missingvalue))
							return -1;
					}
					break;
				}
			case OPH_INT:{
					for (i = 0; i < byte_array->numelem; i++) {
						tmp = (double) (*(int *) ((byte_array->content) + (i * byte_array->elemsize[j])) + scalar);
						if (core_oph_type_cast((void *) (&tmp), (result->content) + (i * result->elemsize[j]), OPH_DOUBLE, result->type[j], byte_array->missingvalue))
							return -1;
					}
					break;
				}
			case OPH_SHORT:{
					for (i = 0; i < byte_array->numelem; i++) {
						tmp = (double) (*(short *) ((byte_array->content) + (i * byte_array->elemsize[j])) + scalar);
						if (core_oph_type_cast((void *) (&tmp), (result->content) + (i * result->elemsize[j]), OPH_DOUBLE, result->type[j], byte_array->missingvalue))
							return -1;
					}
					break;
				}
			case OPH_BYTE:{
					for (i = 0; i < byte_array->numelem; i++) {
						tmp = (double) (*(char *) ((byte_array->content) + (i * byte_array->elemsize[j])) + scalar);
						if (core_oph_type_cast((void *) (&tmp), (result->content) + (i * result->elemsize[j]), OPH_DOUBLE, result->type[j], byte_array->missingvalue))
							return -1;
					}
					break;
				}
			case OPH_LONG:{
					for (i = 0; i < byte_array->numelem; i++) {
						tmp = (double) (*(long long *) ((byte_array->content) + (i * byte_array->elemsize[j])) + scalar);
						if (core_oph_type_cast((void *) (&tmp), (result->content) + (i * result->elemsize[j]), OPH_DOUBLE, result->type[j], byte_array->missingvalue))
							return -1;
					}
					break;
				}
			default:
				pmesg(1, __FILE__, __LINE__, "Type non recognized\n");
				return -1;
		}
	}
	return 0;
}
char *oph_aggregate_stats_partial(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	if (*error != 0) {
		pmesg(1, __FILE__, __LINE__, "Error on adding elements\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	oph_agg_stats_partial_data *dat = (oph_agg_stats_partial_data *) initid->ptr;

	if (dat->count == 0) {
		*length = 0;
		*error = 0;
		*is_null = 1;
		return NULL;
	}
	if (!dat->result.content) {
		*length = 0;
		*error = 0;
		*is_null = 1;
		return NULL;
	}

	int j, k, q = 0;
	int size = dat->result.numelem / (dat->measure.numelem);

	// Add count to result array
	for (k = 0; k < dat->result.numelem; k += size) {
		if (core_oph_type_cast(&dat->count, dat->result.content + k * dat->result.elemsize, OPH_INT, dat->result.type, NULL)) {
			pmesg(1, __FILE__, __LINE__, "Error in casting\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
	}

	// Add other partial results to result
	for (j = 0; j < size - 1; j++) {
		for (k = 0; k < dat->result.numelem; k += size) {
			if (core_oph_type_cast
			    (dat->partials[j].content + q * dat->measure.elemsize, dat->result.content + (j + 1 + k) * dat->result.elemsize, dat->measure.type, dat->result.type, NULL)) {
				pmesg(1, __FILE__, __LINE__, "Error in casting\n");
				*length = 0;
				*is_null = 0;
				*error = 1;
				return NULL;
			}
			q++;
		}
		q = 0;
	}

	*is_null = 0;
	*error = 0;

	*length = *(dat->result.length);
	return (result = dat->result.content);
}
int core_oph_deaccumulate_multi(oph_multistring* byte_array, oph_multistring* result, int id)
{
        int i,j,js,je;

	if (id<=0) { js=0; je=byte_array->num_measure; }
	else if (id>byte_array->num_measure)
	{
		pmesg(1, __FILE__, __LINE__, "Index out of boundaries\n");
		return -1;
	}
	else { js=id-1; je=id; }

	for (j=js;j<je;++j)
	{
		switch(byte_array->type[j])
		{
		        case OPH_DOUBLE:{
				double tmp=0,tmp2;
		                for (i = 0; i < byte_array->numelem; i++){
					tmp2 = *(double*)((byte_array->content)+(i*byte_array->elemsize[j]));
		                        tmp = tmp2 - tmp;
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), byte_array->type[j], result->type[j])) return -1;
					tmp = tmp2;
				}
				break;
			}
		        case OPH_FLOAT:{
				float tmp=0,tmp2;
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp2 = *(float*)((byte_array->content)+(i*byte_array->elemsize[j]));
					tmp = tmp2 - tmp;
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), byte_array->type[j], result->type[j])) return -1;
					tmp = tmp2;
				}
				break;
			}
		        case OPH_INT:{
				int tmp=0,tmp2;
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp2 = *(int*)((byte_array->content)+(i*byte_array->elemsize[j]));
					tmp = tmp2 - tmp;
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), byte_array->type[j], result->type[j])) return -1;
					tmp = tmp2;
				}
				break;
			}
		        case OPH_SHORT:{
				short tmp=0,tmp2;
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp2 = *(short*)((byte_array->content)+(i*byte_array->elemsize[j]));
					tmp = tmp2 - tmp;
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), byte_array->type[j], result->type[j])) return -1;
					tmp = tmp2;
				}
				break;
			}
		        case OPH_BYTE:{
				char tmp=0,tmp2;
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp2 = *(char*)((byte_array->content)+(i*byte_array->elemsize[j]));
					tmp = tmp2 - tmp;
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), byte_array->type[j], result->type[j])) return -1;
					tmp = tmp2;
				}
				break;
			}
		        case OPH_LONG:{
				long long tmp=0,tmp2;
		                for (i = 0; i < byte_array->numelem; i++){
		                        tmp2 = *(long long*)((byte_array->content)+(i*byte_array->elemsize[j]));
					tmp = tmp2 - tmp;
					if(core_oph_type_cast((void*)(&tmp), (result->content)+(i*result->elemsize[j]), byte_array->type[j], result->type[j])) return -1;
					tmp = tmp2;
				}
				break;
			}
		        default:
		                pmesg(1, __FILE__, __LINE__, "Type non recognized\n");
		                return -1;
		}
	}
        return 0;
}