1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <errno.h>
6
7 #include "mex.h"
8
9 #ifdef MX_API_VER
10 #if MX_API_VER < 0x07030000
11 typedef int mwIndex;
12 #endif
13 #endif
14 #ifndef max
15 #define max(x,y) (((x)>(y))?(x):(y))
16 #endif
17 #ifndef min
18 #define min(x,y) (((x)<(y))?(x):(y))
19 #endif
20
exit_with_help()21 void exit_with_help()
22 {
23 mexPrintf(
24 "Usage: [label_vector, instance_matrix] = libsvmread('filename');\n"
25 );
26 }
27
fake_answer(int nlhs,mxArray * plhs[])28 static void fake_answer(int nlhs, mxArray *plhs[])
29 {
30 int i;
31 for(i=0;i<nlhs;i++)
32 plhs[i] = mxCreateDoubleMatrix(0, 0, mxREAL);
33 }
34
35 static char *line;
36 static int max_line_len;
37
readline(FILE * input)38 static char* readline(FILE *input)
39 {
40 int len;
41
42 if(fgets(line,max_line_len,input) == NULL)
43 return NULL;
44
45 while(strrchr(line,'\n') == NULL)
46 {
47 max_line_len *= 2;
48 line = (char *) realloc(line, max_line_len);
49 len = (int) strlen(line);
50 if(fgets(line+len,max_line_len-len,input) == NULL)
51 break;
52 }
53 return line;
54 }
55
56 // read in a problem (in libsvm format)
read_problem(const char * filename,int nlhs,mxArray * plhs[])57 void read_problem(const char *filename, int nlhs, mxArray *plhs[])
58 {
59 int max_index, min_index, inst_max_index;
60 size_t elements, k, i, l=0;
61 FILE *fp = fopen(filename,"r");
62 char *endptr;
63 mwIndex *ir, *jc;
64 double *labels, *samples;
65
66 if(fp == NULL)
67 {
68 mexPrintf("can't open input file %s\n",filename);
69 fake_answer(nlhs, plhs);
70 return;
71 }
72
73 max_line_len = 1024;
74 line = (char *) malloc(max_line_len*sizeof(char));
75
76 max_index = 0;
77 min_index = 1; // our index starts from 1
78 elements = 0;
79 while(readline(fp) != NULL)
80 {
81 char *idx, *val;
82 // features
83 int index = 0;
84
85 inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0
86 strtok(line," \t"); // label
87 while (1)
88 {
89 idx = strtok(NULL,":"); // index:value
90 val = strtok(NULL," \t");
91 if(val == NULL)
92 break;
93
94 errno = 0;
95 index = (int) strtol(idx,&endptr,10);
96 if(endptr == idx || errno != 0 || *endptr != '\0' || index <= inst_max_index)
97 {
98 mexPrintf("Wrong input format at line %d\n",l+1);
99 fake_answer(nlhs, plhs);
100 return;
101 }
102 else
103 inst_max_index = index;
104
105 min_index = min(min_index, index);
106 elements++;
107 }
108 max_index = max(max_index, inst_max_index);
109 l++;
110 }
111 rewind(fp);
112
113 // y
114 plhs[0] = mxCreateDoubleMatrix(l, 1, mxREAL);
115 // x^T
116 if (min_index <= 0)
117 plhs[1] = mxCreateSparse(max_index-min_index+1, l, elements, mxREAL);
118 else
119 plhs[1] = mxCreateSparse(max_index, l, elements, mxREAL);
120
121 labels = mxGetPr(plhs[0]);
122 samples = mxGetPr(plhs[1]);
123 ir = mxGetIr(plhs[1]);
124 jc = mxGetJc(plhs[1]);
125
126 k=0;
127 for(i=0;i<l;i++)
128 {
129 char *idx, *val, *label;
130 jc[i] = k;
131
132 readline(fp);
133
134 label = strtok(line," \t\n");
135 if(label == NULL)
136 {
137 mexPrintf("Empty line at line %d\n",i+1);
138 fake_answer(nlhs, plhs);
139 return;
140 }
141 labels[i] = strtod(label,&endptr);
142 if(endptr == label || *endptr != '\0')
143 {
144 mexPrintf("Wrong input format at line %d\n",i+1);
145 fake_answer(nlhs, plhs);
146 return;
147 }
148
149 // features
150 while(1)
151 {
152 idx = strtok(NULL,":");
153 val = strtok(NULL," \t");
154 if(val == NULL)
155 break;
156
157 ir[k] = (mwIndex) (strtol(idx,&endptr,10) - min_index); // precomputed kernel has <index> start from 0
158
159 errno = 0;
160 samples[k] = strtod(val,&endptr);
161 if (endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
162 {
163 mexPrintf("Wrong input format at line %d\n",i+1);
164 fake_answer(nlhs, plhs);
165 return;
166 }
167 ++k;
168 }
169 }
170 jc[l] = k;
171
172 fclose(fp);
173 free(line);
174
175 {
176 mxArray *rhs[1], *lhs[1];
177 rhs[0] = plhs[1];
178 if(mexCallMATLAB(1, lhs, 1, rhs, "transpose"))
179 {
180 mexPrintf("Error: cannot transpose problem\n");
181 fake_answer(nlhs, plhs);
182 return;
183 }
184 plhs[1] = lhs[0];
185 }
186 }
187
mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])188 void mexFunction( int nlhs, mxArray *plhs[],
189 int nrhs, const mxArray *prhs[] )
190 {
191 char filename[256];
192
193 if(nrhs != 1 || nlhs != 2)
194 {
195 exit_with_help();
196 fake_answer(nlhs, plhs);
197 return;
198 }
199
200 mxGetString(prhs[0], filename, mxGetN(prhs[0]) + 1);
201
202 if(filename == NULL)
203 {
204 mexPrintf("Error: filename is NULL\n");
205 return;
206 }
207
208 read_problem(filename, nlhs, plhs);
209
210 return;
211 }
212
213