ACDC_KNOSYS-2021/MSC/libsvm-weights-3.20/matlab/libsvmread.c

213 lines
4.2 KiB
C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "mex.h"
#ifdef MX_API_VER
#if MX_API_VER < 0x07030000
typedef int mwIndex;
#endif
#endif
#ifndef max
#define max(x,y) (((x)>(y))?(x):(y))
#endif
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#endif
void exit_with_help()
{
mexPrintf(
"Usage: [label_vector, instance_matrix] = libsvmread('filename');\n"
);
}
static void fake_answer(int nlhs, mxArray *plhs[])
{
int i;
for(i=0;i<nlhs;i++)
plhs[i] = mxCreateDoubleMatrix(0, 0, mxREAL);
}
static char *line;
static int max_line_len;
static char* readline(FILE *input)
{
int len;
if(fgets(line,max_line_len,input) == NULL)
return NULL;
while(strrchr(line,'\n') == NULL)
{
max_line_len *= 2;
line = (char *) realloc(line, max_line_len);
len = (int) strlen(line);
if(fgets(line+len,max_line_len-len,input) == NULL)
break;
}
return line;
}
// read in a problem (in libsvm format)
void read_problem(const char *filename, int nlhs, mxArray *plhs[])
{
int max_index, min_index, inst_max_index;
size_t elements, k, i, l=0;
FILE *fp = fopen(filename,"r");
char *endptr;
mwIndex *ir, *jc;
double *labels, *samples;
if(fp == NULL)
{
mexPrintf("can't open input file %s\n",filename);
fake_answer(nlhs, plhs);
return;
}
max_line_len = 1024;
line = (char *) malloc(max_line_len*sizeof(char));
max_index = 0;
min_index = 1; // our index starts from 1
elements = 0;
while(readline(fp) != NULL)
{
char *idx, *val;
// features
int index = 0;
inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0
strtok(line," \t"); // label
while (1)
{
idx = strtok(NULL,":"); // index:value
val = strtok(NULL," \t");
if(val == NULL)
break;
errno = 0;
index = (int) strtol(idx,&endptr,10);
if(endptr == idx || errno != 0 || *endptr != '\0' || index <= inst_max_index)
{
mexPrintf("Wrong input format at line %d\n",l+1);
fake_answer(nlhs, plhs);
return;
}
else
inst_max_index = index;
min_index = min(min_index, index);
elements++;
}
max_index = max(max_index, inst_max_index);
l++;
}
rewind(fp);
// y
plhs[0] = mxCreateDoubleMatrix(l, 1, mxREAL);
// x^T
if (min_index <= 0)
plhs[1] = mxCreateSparse(max_index-min_index+1, l, elements, mxREAL);
else
plhs[1] = mxCreateSparse(max_index, l, elements, mxREAL);
labels = mxGetPr(plhs[0]);
samples = mxGetPr(plhs[1]);
ir = mxGetIr(plhs[1]);
jc = mxGetJc(plhs[1]);
k=0;
for(i=0;i<l;i++)
{
char *idx, *val, *label;
jc[i] = k;
readline(fp);
label = strtok(line," \t\n");
if(label == NULL)
{
mexPrintf("Empty line at line %d\n",i+1);
fake_answer(nlhs, plhs);
return;
}
labels[i] = strtod(label,&endptr);
if(endptr == label || *endptr != '\0')
{
mexPrintf("Wrong input format at line %d\n",i+1);
fake_answer(nlhs, plhs);
return;
}
// features
while(1)
{
idx = strtok(NULL,":");
val = strtok(NULL," \t");
if(val == NULL)
break;
ir[k] = (mwIndex) (strtol(idx,&endptr,10) - min_index); // precomputed kernel has <index> start from 0
errno = 0;
samples[k] = strtod(val,&endptr);
if (endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
{
mexPrintf("Wrong input format at line %d\n",i+1);
fake_answer(nlhs, plhs);
return;
}
++k;
}
}
jc[l] = k;
fclose(fp);
free(line);
{
mxArray *rhs[1], *lhs[1];
rhs[0] = plhs[1];
if(mexCallMATLAB(1, lhs, 1, rhs, "transpose"))
{
mexPrintf("Error: cannot transpose problem\n");
fake_answer(nlhs, plhs);
return;
}
plhs[1] = lhs[0];
}
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
char filename[256];
if(nrhs != 1 || nlhs != 2)
{
exit_with_help();
fake_answer(nlhs, plhs);
return;
}
mxGetString(prhs[0], filename, mxGetN(prhs[0]) + 1);
if(filename == NULL)
{
mexPrintf("Error: filename is NULL\n");
return;
}
read_problem(filename, nlhs, plhs);
return;
}