int oph_subset_vector_free(oph_subset** subset_struct, int num)
{
	int i;
	if (subset_struct) for (i=0;i<num;++i)
		if (subset_struct[i]) { oph_subset_free(subset_struct[i]); subset_struct[i]=NULL; }
	return OPH_SUBSET_LIB_OK;
}
void oph_get_subarray2_deinit(UDF_INIT * initid)
{
	//Free allocated space
	if (initid->ptr) {
		oph_get_subarray2_param *param = (oph_get_subarray2_param *) initid->ptr;
		if (param->measure) {
			free(param->measure);
			param->measure = NULL;
		}
		if (param->subset) {
			oph_subset_free(param->subset);
			param->subset = NULL;
		}
		if (param->flags) {
			free(param->flags);
			param->flags = NULL;
		}
		if (param->result) {
			free(param->result);
			param->result = NULL;
		}
		free(initid->ptr);
		initid->ptr = NULL;
	}
}
int oph_subset_value_to_index(const char* in_cond, char* data, unsigned long long data_size, char* data_type, double offset, char* out_cond, oph_subset** out_subset)
{
	if (!in_cond || !data || !data_size || !data_type || !out_cond)
	{
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Null pointer\n");
		return OPH_SUBSET_LIB_NULL_POINTER_ERR;
	}

	out_cond[0]=0; // Already allocated
	if (out_subset) *out_subset = NULL;

	double min, max;
	if (!strncasecmp(data_type,OPH_SUBSET_LIB_DOUBLE_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		min = *((double*)data);
		max = *(((double*)data)+data_size-1);
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_FLOAT_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		min = (double)(*((float*)data));
		max = (double)(*(((float*)data)+data_size-1));
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_INT_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		min = (double)(*((int*)data));
		max = (double)(*(((int*)data)+data_size-1));
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_LONG_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		min = (double)(*((long long*)data));
		max = (double)(*(((long long*)data)+data_size-1));
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_SHORT_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		min = (double)(*((short*)data));
		max = (double)(*(((short*)data)+data_size-1));
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_BYTE_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		min = (double)(*((char*)data));
		max = (double)(*(((char*)data)+data_size-1));
	}
	else
	{
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unknown data type\n");
		return OPH_SUBSET_LIB_DATA_ERR;
	}

	oph_subset_double* subset_double;
	if (oph_subset_double_init(&subset_double)) return OPH_SUBSET_LIB_SYSTEM_ERR;
	if (oph_subset_double_parse(in_cond, strlen(in_cond), subset_double, min, max, offset)) return OPH_SUBSET_LIB_DATA_ERR;
	
	oph_subset* subset;
	oph_subset_init(&subset);
	subset->number = subset_double->number;
	subset->type = (oph_subset_type*)calloc(subset->number,sizeof(oph_subset_type));
	subset->start = (unsigned long long*)calloc(subset->number,sizeof(unsigned long long));
	subset->end = (unsigned long long*)calloc(subset->number,sizeof(unsigned long long));
	subset->stride = (unsigned long long*)calloc(subset->number,sizeof(unsigned long long));
	subset->count = (unsigned long long*)calloc(subset->number,sizeof(unsigned long long));
	subset->total = 0;

	int i, j;
	for (i=0;i<(int)subset->number;++i) subset->stride[i] = 1;

	if (!strncasecmp(data_type,OPH_SUBSET_LIB_DOUBLE_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		for (i=0;i<(int)subset->number;++i)
		{
			subset->type[i] = subset_double->type[i];
			switch (subset_double->type[i])
			{
				case OPH_SUBSET_LIB_SINGLE:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((double*)data+j) >= subset_double->start[i]) break;
						if ((j<(int)data_size) && (!j || (*((double*)data+j) - subset_double->start[i] < subset_double->start[i] - *((double*)data+j-1)))) j++; // Non 'C'-like indexing
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((double*)data+j) >= subset_double->start[i]) break;
						if ((j<0) || ((j<(int)data_size-1) && (*((double*)data+j) - subset_double->start[i] > subset_double->start[i] - *((double*)data+j+1)))) j++;
						j++; // Non 'C'-like indexing
					}
					subset->start[i] = subset->end[i] = j; // The actual value is beetween j-1 (-inf if negative) and j (+inf if equal to data_size)
					break;
				case OPH_SUBSET_LIB_INTERVAL:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((double*)data+j) >= subset_double->start[i]) break;
						if (j==(int)data_size)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if (!j && (subset_double->end[i] < *((double*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->start[i] = j+1; // Non 'C'-like indexing
							if (*((double*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->end[i] = subset->start[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j++; j<(int)data_size; ++j)
								if (*((double*)data+j) > subset_double->end[i]) break;
							subset->end[i] = j; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((double*)data+j) >= subset_double->start[i]) break;
						if (j<0)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if ((j==(int)data_size-1) && (subset_double->end[i] < *((double*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->end[i] = j+1; // Non 'C'-like indexing
							if (*((double*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->start[i] = subset->end[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j--; j>=0; --j)
								if (*((double*)data+j) > subset_double->end[i]) break;
							subset->start[i] = j+2; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					break;
				default:
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unexpected subset type\n");
					oph_subset_free(subset);
					oph_subset_double_free(subset_double);
					return OPH_SUBSET_LIB_SYSTEM_ERR;
			}
			subset->count[i] = 1+(subset->end[i]-subset->start[i]);
			subset->total += subset->count[i];
		}
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_FLOAT_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		for (i=0;i<(int)subset->number;++i)
		{
			subset->type[i] = subset_double->type[i];
			switch (subset_double->type[i])
			{
				case OPH_SUBSET_LIB_SINGLE:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((float*)data+j) >= subset_double->start[i]) break;
						if ((j<(int)data_size) && (!j || (*((float*)data+j) - subset_double->start[i] < subset_double->start[i] - *((float*)data+j-1)))) j++; // Non 'C'-like indexing
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((float*)data+j) >= subset_double->start[i]) break;
						if ((j<0) || ((j<(int)data_size-1) && (*((float*)data+j) - subset_double->start[i] > subset_double->start[i] - *((float*)data+j+1)))) j++;
						j++; // Non 'C'-like indexing
					}
					subset->start[i] = subset->end[i] = j;
					break;
				case OPH_SUBSET_LIB_INTERVAL:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((float*)data+j) >= subset_double->start[i]) break;
						if (j==(int)data_size)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if(!j && (subset_double->end[i] < *((float*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->start[i] = j+1; // Non 'C'-like indexing
							if (*((float*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->end[i] = subset->start[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j++; j<(int)data_size; ++j)
								if (*((float*)data+j) > subset_double->end[i]) break;
							subset->end[i] = j; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((float*)data+j) >= subset_double->start[i]) break;
						if (j<0)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if ((j==(int)data_size-1) && (subset_double->end[i] < *((float*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->end[i] = j+1; // Non 'C'-like indexing
							if (*((float*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->start[i] = subset->end[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j--; j>=0; --j)
								if (*((float*)data+j) > subset_double->end[i]) break;
							subset->start[i] = j+2; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					break;
				default:
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unexpected subset type\n");
					oph_subset_free(subset);
					oph_subset_double_free(subset_double);
					return OPH_SUBSET_LIB_SYSTEM_ERR;
			}
			subset->count[i] = 1+(subset->end[i]-subset->start[i]);
			subset->total += subset->count[i];
		}
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_BYTE_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		for (i=0;i<(int)subset->number;++i)
		{
			subset->type[i] = subset_double->type[i];
			switch (subset_double->type[i])
			{
				case OPH_SUBSET_LIB_SINGLE:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((char*)data+j) >= subset_double->start[i]) break;
						if ((j<(int)data_size) && (!j || (*((char*)data+j) - subset_double->start[i] < subset_double->start[i] - *((char*)data+j-1)))) j++; // Non 'C'-like indexing
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((char*)data+j) >= subset_double->start[i]) break;
						if ((j<0) || ((j<(int)data_size-1) && (*((char*)data+j) - subset_double->start[i] > subset_double->start[i] - *((char*)data+j+1)))) j++;
						j++; // Non 'C'-like indexing
					}
					subset->start[i] = subset->end[i] = j;
					break;
				case OPH_SUBSET_LIB_INTERVAL:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((char*)data+j) >= subset_double->start[i]) break;
						if (j==(int)data_size)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if (!j && (subset_double->end[i] < *((char*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->start[i] = j+1; // Non 'C'-like indexing
							if (*((char*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->end[i] = subset->start[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j++; j<(int)data_size; ++j)
								if (*((char*)data+j) > subset_double->end[i]) break;
							subset->end[i] = j; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((char*)data+j) >= subset_double->start[i]) break;
						if (j<0)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if ((j==(int)data_size-1) && (subset_double->end[i] < *((char*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->end[i] = j+1; // Non 'C'-like indexing
							if (*((char*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->start[i] = subset->end[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j--; j>=0; --j)
								if (*((char*)data+j) > subset_double->end[i]) break;
							subset->start[i] = j+2; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					break;
				default:
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unexpected subset type\n");
					oph_subset_free(subset);
					oph_subset_double_free(subset_double);
					return OPH_SUBSET_LIB_SYSTEM_ERR;
			}
			subset->count[i] = 1+(subset->end[i]-subset->start[i]);
			subset->total += subset->count[i];
		}
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_SHORT_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		for (i=0;i<(int)subset->number;++i)
		{
			subset->type[i] = subset_double->type[i];
			switch (subset_double->type[i])
			{
				case OPH_SUBSET_LIB_SINGLE:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((short*)data+j) >= subset_double->start[i]) break;
						if ((j<(int)data_size) && (!j || (*((short*)data+j) - subset_double->start[i] < subset_double->start[i] - *((short*)data+j-1)))) j++; // Non 'C'-like indexing
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((short*)data+j) >= subset_double->start[i]) break;
						if ((j<0) || ((j<(int)data_size-1) && (*((short*)data+j) - subset_double->start[i] > subset_double->start[i] - *((short*)data+j+1)))) j++;
						j++; // Non 'C'-like indexing
					}
					subset->start[i] = subset->end[i] = j;
					break;
				case OPH_SUBSET_LIB_INTERVAL:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((short*)data+j) >= subset_double->start[i]) break;
						if (j==(int)data_size)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if (!j && (subset_double->end[i] < *((short*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->start[i] = j+1; // Non 'C'-like indexing
							if (*((short*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->end[i] = subset->start[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j++; j<(int)data_size; ++j)
								if (*((short*)data+j) > subset_double->end[i]) break;
							subset->end[i] = j; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((short*)data+j) >= subset_double->start[i]) break;
						if (j<0)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if ((j==(int)data_size-1) && (subset_double->end[i] < *((short*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->end[i] = j+1; // Non 'C'-like indexing
							if (*((short*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->start[i] = subset->end[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j--; j>=0; --j)
								if (*((short*)data+j) > subset_double->end[i]) break;
							subset->start[i] = j+2; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					break;
				default:
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unexpected subset type\n");
					oph_subset_free(subset);
					oph_subset_double_free(subset_double);
					return OPH_SUBSET_LIB_SYSTEM_ERR;
			}
			subset->count[i] = 1+(subset->end[i]-subset->start[i]);
			subset->total += subset->count[i];
		}
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_INT_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		for (i=0;i<(int)subset->number;++i)
		{
			subset->type[i] = subset_double->type[i];
			switch (subset_double->type[i])
			{
				case OPH_SUBSET_LIB_SINGLE:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((int*)data+j) >= subset_double->start[i]) break;
						if ((j<(int)data_size) && (!j || (*((int*)data+j) - subset_double->start[i] < subset_double->start[i] - *((int*)data+j-1)))) j++; // Non 'C'-like indexing
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((int*)data+j) >= subset_double->start[i]) break;
						if ((j<0) || ((j<(int)data_size-1) && (*((int*)data+j) - subset_double->start[i] > subset_double->start[i] - *((int*)data+j+1)))) j++;
						j++; // Non 'C'-like indexing
					}
					subset->start[i] = subset->end[i] = j;
					break;
				case OPH_SUBSET_LIB_INTERVAL:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((int*)data+j) >= subset_double->start[i]) break;
						if (j==(int)data_size)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if (!j && (subset_double->end[i] < *((int*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->start[i] = j+1; // Non 'C'-like indexing
							if (*((int*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->end[i] = subset->start[i];
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j++; j<(int)data_size; ++j)
								if (*((int*)data+j) > subset_double->end[i]) break;
							subset->end[i] = j; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((int*)data+j) >= subset_double->start[i]) break;
						if (j<0)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if ((j==(int)data_size-1) && (subset_double->end[i] < *((int*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->end[i] = j+1; // Non 'C'-like indexing
							if (*((int*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->start[i] = subset->end[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j--; j>=0; --j)
								if (*((int*)data+j) > subset_double->end[i]) break;
							subset->start[i] = j+2; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					break;
				default:
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unexpected subset type\n");
					oph_subset_free(subset);
					oph_subset_double_free(subset_double);
					return OPH_SUBSET_LIB_SYSTEM_ERR;
			}
			subset->count[i] = 1+(subset->end[i]-subset->start[i]);
			subset->total += subset->count[i];
		}
	}
	else if (!strncasecmp(data_type,OPH_SUBSET_LIB_LONG_TYPE,OPH_SUBSET_LIB_MAX_TYPE_LENGTH))
	{
		for (i=0;i<(int)subset->number;++i)
		{
			subset->type[i] = subset_double->type[i];
			switch (subset_double->type[i])
			{
				case OPH_SUBSET_LIB_SINGLE:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((long long*)data+j) >= subset_double->start[i]) break;
						if ((j<(int)data_size) && (!j || (*((long long*)data+j) - subset_double->start[i] < subset_double->start[i] - *((long long*)data+j-1)))) j++; // Non 'C'-like indexing
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((long long*)data+j) >= subset_double->start[i]) break;
						if ((j<0) || ((j<(int)data_size-1) && (*((long long*)data+j) - subset_double->start[i] > subset_double->start[i] - *((long long*)data+j+1)))) j++;
						j++; // Non 'C'-like indexing
					}
					subset->start[i] = subset->end[i] = j;
					break;
				case OPH_SUBSET_LIB_INTERVAL:
					if (min<max)
					{
						for (j=0; j<(int)data_size; ++j)
							if (*((long long*)data+j) >= subset_double->start[i]) break;
						if (j==(int)data_size)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if (!j && (subset_double->end[i] < *((int*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->start[i] = j+1; // Non 'C'-like indexing
							if (*((long long*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->end[i] = subset->start[i];
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j++; j<(int)data_size; ++j)
								if (*((long long*)data+j) > subset_double->end[i]) break;
							subset->end[i] = j; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					else
					{
						for (j=data_size-1; j>=0; --j)
							if (*((long long*)data+j) >= subset_double->start[i]) break;
						if (j<0)
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too high\n", subset_double->start[i]);
							continue;
						} 
						else if ((j==(int)data_size-1) && (subset_double->end[i] < *((long long*)data+j)))
						{
							pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset interval is out of dimension range: %f is too low\n", subset_double->end[i]);
							continue;
						} 
						else
						{
							subset->end[i] = j+1; // Non 'C'-like indexing
							if (*((long long*)data+j) > subset_double->end[i]) // Empty set
							{
								pmesg(LOG_WARNING, __FILE__, __LINE__, "Subset cube is empty\n");
								subset->start[i] = subset->end[i]; // Non 'C'-like indexing
								subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
								continue;
							}
							for (j--; j>=0; --j)
								if (*((long long*)data+j) > subset_double->end[i]) break;
							subset->start[i] = j+2; // Non 'C'-like indexing
							if (subset->start[i] == subset->end[i]) subset_double->type[i] = OPH_SUBSET_LIB_SINGLE;
						}
					}
					break;
				default:
					pmesg(LOG_ERROR, __FILE__, __LINE__, "Unexpected subset type\n");
					oph_subset_free(subset);
					oph_subset_double_free(subset_double);
					return OPH_SUBSET_LIB_SYSTEM_ERR;
			}
			subset->count[i] = 1+(subset->end[i]-subset->start[i]);
			subset->total += subset->count[i];
		}
	}
	else
	{
		pmesg(LOG_ERROR, __FILE__, __LINE__, "Unknown data type\n");
		oph_subset_free(subset);
		oph_subset_double_free(subset_double);
		return OPH_SUBSET_LIB_DATA_ERR;
	}

	oph_subset_double_free(subset_double);

	if (!subset->total)
	{
		pmesg(LOG_DEBUG, __FILE__, __LINE__, "Subset cube is empty\n");
		oph_subset_free(subset);
		return OPH_SUBSET_LIB_OK;
	}

	size_t len;
	unsigned int actual_number=0;
	char buffer[OPH_SUBSET_LIB_MAX_STRING_LENGTH], separator=0, found_empty=0;
	for (i=0;i<(int)subset->number;++i)
	{
		if (!subset->count[i])
		{
			found_empty = 1;
			if (separator && (i==(int)subset->number-1) && ((len=strlen(out_cond)))) out_cond[len-1]=0;
			continue;
		}
		switch (subset->type[i])
		{
			case OPH_SUBSET_LIB_SINGLE:
				snprintf(buffer,OPH_SUBSET_LIB_MAX_STRING_LENGTH,"%lld",subset->start[i]);
				break;
			case OPH_SUBSET_LIB_INTERVAL:
				snprintf(buffer,OPH_SUBSET_LIB_MAX_STRING_LENGTH,"%lld%s%lld",subset->start[i],OPH_SUBSET_LIB_PARAM_SEPARATOR,subset->end[i]);
				break;
			default:
				pmesg(LOG_ERROR, __FILE__, __LINE__, "Unexpected subset type\n");
				oph_subset_free(subset);
				return OPH_SUBSET_LIB_SYSTEM_ERR;
		}
		strncat(out_cond,buffer,OPH_SUBSET_LIB_MAX_STRING_LENGTH);
		if (i<(int)subset->number-1)
		{
			strncat(out_cond,OPH_SUBSET_LIB_SUBSET_SEPARATOR,OPH_SUBSET_LIB_MAX_STRING_LENGTH);
			separator=1;
		}
		actual_number++;
	}

	if (!out_subset) oph_subset_free(subset);
	else
	{
		if (found_empty) // Remake subset to be exported
		{
			oph_subset* subset2;
			oph_subset_init(&subset2);
			subset2->number = actual_number;
			subset2->type = (oph_subset_type*)malloc(subset2->number*sizeof(oph_subset_type));
			subset2->start = (unsigned long long*)malloc(subset2->number*sizeof(unsigned long long));
			subset2->end = (unsigned long long*)malloc(subset2->number*sizeof(unsigned long long));
			subset2->stride = (unsigned long long*)malloc(subset2->number*sizeof(unsigned long long));
			subset2->count = (unsigned long long*)malloc(subset2->number*sizeof(unsigned long long));
			subset2->total = subset->total;
			for (i=j=0;i<(int)subset->number;++i) if (subset->count[i])
			{
				subset2->type[j] = subset->type[i];
				subset2->start[j] = subset->start[i];
				subset2->end[j] = subset->end[i];
				subset2->stride[j] = subset->stride[i];
				subset2->count[j] = subset->count[i];
				j++;
			}
			oph_subset_free(subset);
			*out_subset = subset2;
		}
		else *out_subset = subset;
	}

	pmesg(LOG_INFO, __FILE__, __LINE__, "Subset string is '%s' when expressed as indexes\n",out_cond);

	return OPH_SUBSET_LIB_OK;
}