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;
}
char *oph_get_subarray2(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	int res = 0, number = 0, i;
	oph_get_subarray2_param *param;
	oph_string *measure;
	unsigned long total, max;
	unsigned long *sizes = 0;

	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_get_subarray2_param));
		if (!initid->ptr) {
			pmesg(1, __FILE__, __LINE__, "Error allocating oph_get_subarray2_param\n");
			param->error = 1;
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		param = (oph_get_subarray2_param *) initid->ptr;
		param->measure = NULL;
		param->subset = NULL;
		param->flags = NULL;
		param->result = NULL;
		param->error = 0;
	} else
		param = (oph_get_subarray2_param *) initid->ptr;

	if (!param->error && !param->measure) {
		// Input
		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;

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

		// Set measure->type
		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;
		}
		// Set measure->elemsize
		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;
		}
		// Set measure->numelem
		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;
		}

		if (args->arg_count > 4) {
			max = *((long long *) args->args[args->arg_count - 1]);
			number = args->arg_count - 4;
			sizes = (unsigned long *) malloc(number * sizeof(unsigned long));
			for (i = 0; i < number; ++i)
				sizes[i] = *((long long *) args->args[i + 4]);
		} else
			max = measure->numelem;

		// Set subsetting structures
		if (oph_subset_init(&(param->subset))) {
			pmesg(1, __FILE__, __LINE__, "Error in oph_subset initialization\n");
			param->error = 1;
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		if (oph_subset_parse(args->args[3], args->lengths[3], param->subset, max)) {
			pmesg(1, __FILE__, __LINE__, "Error in parsing subset_string\n");
			param->error = 1;
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		// New implementation with flags
		param->flags = malloc(measure->numelem * sizeof(char));
		if (!param->flags) {
			pmesg(1, __FILE__, __LINE__, "Error allocating flag array\n");
			param->error = 1;
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		if (oph_subset_set_flags(param->subset, param->flags, measure->numelem, &total, sizes, number)) {
			pmesg(1, __FILE__, __LINE__, "Error in setting flag array\n");
			param->error = 1;
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		if (sizes)
			free(sizes);

		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;
		}
		param->result_type = output_array.type;
		param->result_elemsize = output_array.elemsize;

		// Output
		param->length = total * param->result_elemsize;	// 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;

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

	res = core_oph_get_subarray2(param);
	if (res) {
		pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	*length = param->length;
	*is_null = 0;
	*error = 0;
	return (result = param->result);
}