1 /*
2   This code was extracted from liblinear-2.2.1 in Feb 2019 and
3   modified for the use with Octave and Matlab
4 
5 Copyright (c) 2007-2019 The LIBLINEAR Project.
6 All rights reserved.
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 
15 2. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 
19 3. Neither name of copyright holders nor the names of its contributors
20 may be used to endorse or promote products derived from this software
21 without specific prior written permission.
22 
23 
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
28 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 
36 */
37 
38 #include <stdlib.h>
39 #include <string.h>
40 #include "linear.h"
41 #include "linear_model_matlab.h"
42 
43 #ifdef MX_API_VER
44 #if MX_API_VER < 0x07030000
45 typedef int mwIndex;
46 #endif
47 #endif
48 
49 #define Malloc(type,n) (type *)malloc((n)*sizeof(type))
50 
51 #define NUM_OF_RETURN_FIELD 6
52 
53 static const char *field_names[] = {
54 	"Parameters",
55 	"nr_class",
56 	"nr_feature",
57 	"bias",
58 	"Label",
59 	"w",
60 };
61 
model_to_matlab_structure(mxArray * plhs[],struct model * model_)62 const char *model_to_matlab_structure(mxArray *plhs[], struct model *model_)
63 {
64 	int i;
65 	int nr_w;
66 	double *ptr;
67 	mxArray *return_model, **rhs;
68 	int out_id = 0;
69 	int n, w_size;
70 
71 	rhs = (mxArray **)mxMalloc(sizeof(mxArray *)*NUM_OF_RETURN_FIELD);
72 
73 	// Parameters
74 	// for now, only solver_type is needed
75 	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
76 	ptr = mxGetPr(rhs[out_id]);
77 	ptr[0] = model_->param.solver_type;
78 	out_id++;
79 
80 	// nr_class
81 	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
82 	ptr = mxGetPr(rhs[out_id]);
83 	ptr[0] = model_->nr_class;
84 	out_id++;
85 
86 	if(model_->nr_class==2 && model_->param.solver_type != MCSVM_CS)
87 		nr_w=1;
88 	else
89 		nr_w=model_->nr_class;
90 
91 	// nr_feature
92 	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
93 	ptr = mxGetPr(rhs[out_id]);
94 	ptr[0] = model_->nr_feature;
95 	out_id++;
96 
97 	// bias
98 	rhs[out_id] = mxCreateDoubleMatrix(1, 1, mxREAL);
99 	ptr = mxGetPr(rhs[out_id]);
100 	ptr[0] = model_->bias;
101 	out_id++;
102 
103 	if(model_->bias>=0)
104 		n=model_->nr_feature+1;
105 	else
106 		n=model_->nr_feature;
107 
108 	w_size = n;
109 	// Label
110 	if(model_->label)
111 	{
112 		rhs[out_id] = mxCreateDoubleMatrix(model_->nr_class, 1, mxREAL);
113 		ptr = mxGetPr(rhs[out_id]);
114 		for(i = 0; i < model_->nr_class; i++)
115 			ptr[i] = model_->label[i];
116 	}
117 	else
118 		rhs[out_id] = mxCreateDoubleMatrix(0, 0, mxREAL);
119 	out_id++;
120 
121 	// w
122 	rhs[out_id] = mxCreateDoubleMatrix(nr_w, w_size, mxREAL);
123 	ptr = mxGetPr(rhs[out_id]);
124 	for(i = 0; i < w_size*nr_w; i++)
125 		ptr[i]=model_->w[i];
126 	out_id++;
127 
128 	/* Create a struct matrix contains NUM_OF_RETURN_FIELD fields */
129 	return_model = mxCreateStructMatrix(1, 1, NUM_OF_RETURN_FIELD, field_names);
130 
131 	/* Fill struct matrix with input arguments */
132 	for(i = 0; i < NUM_OF_RETURN_FIELD; i++)
133 		mxSetField(return_model,0,field_names[i],mxDuplicateArray(rhs[i]));
134 	/* return */
135 	plhs[0] = return_model;
136 	mxFree(rhs);
137 
138 	return NULL;
139 }
140 
matlab_matrix_to_model(struct model * model_,const mxArray * matlab_struct)141 const char *matlab_matrix_to_model(struct model *model_, const mxArray *matlab_struct)
142 {
143 	int i, num_of_fields;
144 	int nr_w;
145 	double *ptr;
146 	int id = 0;
147 	int n, w_size;
148 	mxArray **rhs;
149 
150 	num_of_fields = mxGetNumberOfFields(matlab_struct);
151 	rhs = (mxArray **) mxMalloc(sizeof(mxArray *)*num_of_fields);
152 
153 	for(i=0;i<num_of_fields;i++)
154 		rhs[i] = mxGetFieldByNumber(matlab_struct, 0, i);
155 
156 	model_->nr_class=0;
157 	nr_w=0;
158 	model_->nr_feature=0;
159 	model_->w=NULL;
160 	model_->label=NULL;
161 
162 	// Parameters
163 	ptr = mxGetPr(rhs[id]);
164 	model_->param.solver_type = (int)ptr[0];
165 	id++;
166 
167 	// nr_class
168 	ptr = mxGetPr(rhs[id]);
169 	model_->nr_class = (int)ptr[0];
170 	id++;
171 
172 	if(model_->nr_class==2 && model_->param.solver_type != MCSVM_CS)
173 		nr_w=1;
174 	else
175 		nr_w=model_->nr_class;
176 
177 	// nr_feature
178 	ptr = mxGetPr(rhs[id]);
179 	model_->nr_feature = (int)ptr[0];
180 	id++;
181 
182 	// bias
183 	ptr = mxGetPr(rhs[id]);
184 	model_->bias = ptr[0];
185 	id++;
186 
187 	if(model_->bias>=0)
188 		n=model_->nr_feature+1;
189 	else
190 		n=model_->nr_feature;
191 	w_size = n;
192 
193 	// Label
194 	if(mxIsEmpty(rhs[id]) == 0)
195 	{
196 		model_->label = Malloc(int, model_->nr_class);
197 		ptr = mxGetPr(rhs[id]);
198 		for(i=0;i<model_->nr_class;i++)
199 			model_->label[i] = (int)ptr[i];
200 	}
201 	id++;
202 
203 	ptr = mxGetPr(rhs[id]);
204 	model_->w=Malloc(double, w_size*nr_w);
205 	for(i = 0; i < w_size*nr_w; i++)
206 		model_->w[i]=ptr[i];
207 	id++;
208 	mxFree(rhs);
209 
210 	return NULL;
211 }
212 
213