gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
Octave.C
Go to the documentation of this file.
1 /* Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16 */
17 
18 #include <octave/config.h>
19 #include <octave/octave.h>
20 #include <octave/oct-obj.h>
21 #include <octave/oct-map.h>
22 #include <octave/symtab.h>
23 //#include <octave/ov-scalar.h>
24 #include "Octave.H"
25 #include <iostream>
26 
27 #include <Eigen/Dense>
28 
29 #ifdef HAVE_OPENCV
30 #include <opencv2/opencv.hpp>
31 #endif
32 
33 // taken from octave/toplev.h
34 typedef void (*octave_exit_func) (int);
35 extern OCTINTERP_API octave_exit_func octave_exit;
36 extern OCTINTERP_API void clean_up_and_exit (int, bool);
37 
38 extern OCTINTERP_API octave_value_list
39 feval (const string& name, const octave_value_list& args = octave_value_list (), int nargout = 0);
40 
41 //extern void do_octave_atexit (void);
42 //extern void clean_up_and_exit (int retval);
43 
44 extern void set_global_value (const string& nm, const octave_value& val);
45 extern octave_value get_global_value (const string& nm, bool silent = false);
46 
47 // extern OCTINTERP_API bool octave_initialized;
48 extern OCTINTERP_API bool octave_interpreter_ready;
49 
50 #define BASENAME_CNT 512
51 
52 static void local_exit(int){}
53 void (*octave_exit) (int) = local_exit;
54 
56  init();
57 }
58 
59 bool Octave::isReady(void) {
61 }
62 
63 void Octave::init(void) {
64  input=NULL;
65  //output=NULL;
66  input=new octave_value_list;
67 // output=new octave_value_list;
68  if (!input){ //} || !output){
69  cerr<<"Octave::Octave couldn't malloc the input and output lists.";
70  assert(-1);
71  }
72 }
73 
74 Octave::Octave(const vector<string> &args) {
75  init();
76  startOctave(args);
77 }
78 
79 void Octave::startOctave(const vector<string> &args) {
80  int argc=args.size();
81  vector<const char *> argsIn(argc);
82  for (int i=0; i<argc; i++)
83  argsIn[i]=&args[i][0];
84  int embedded=1;
85  octave_main((int)argsIn.size(), (char**)&argsIn[0], embedded);
86 }
87 
89  if (input)
90  delete input;
91  input=NULL;
93 }
94 
96  clean_up_and_exit (0, true);
97 }
98 
100  //do_octave_atexit();
101 }
102 
103 template<class TYPE>
104 vector<vector<vector<TYPE> > > &Octave::runM(const char* commandName, const vector<vector<vector<TYPE> > > &in, vector<vector<vector<TYPE> > > &out){
105  //octave_value_list input(in.size()); ///< Input variables to pass to Octave
106  if ((*input).length()<in.size())
107  (*input).resize(in.size());
108 
109  // check that the number of columns are consistent.
110  for (int i=0; i<in.size(); i++) { // cycle through each input
111  int colCnt;
112  for (int j=0; j<in[i].size(); j++){
113  if (j==0)
114  colCnt=in[i][j].size();
115  else
116  if (in[i][j].size()!=colCnt){
117  //out.resize(1); out[0].resize(1); out[0][0].resize(1); // in future, this could be another method for returning on error.
118  //out[0][0][0]=(TYPE)OCTAVE_INCONSISTENT_COL_CNT_ERROR;
119  exit(OctaveDebug().evaluateError(OCTAVE_INCONSISTENT_COL_CNT_ERROR, string(". When trying to execute the command ")+commandName)); // no good way to pass back an error when columns are mismatched in size, so exit for now.
120  }
121  }
122  }
123 
124  for (int i=0; i<in.size(); i++) { // cycle through each input
125  int r=in[i].size();
126  for (int j=0; j<r; j++){ // cycle through each row
127  int c=in[i][j].size();
128  if ((*input)(i).rows()!=r || (*input)(i).columns()!=c) // resize the matrix if necessary
129  if (r==c && r==1) // scalar
130  (*input)(i)=octave_value(in[i][j][0]);
131  else
132  (*input)(i)=Matrix(r, c);
133  if (r>=1 && c>=1){ // if the value is a matrix
134  octave_base_value *obv=(*input)(i).internal_rep();
135  for (int k=0; k<c; k++)
136  obv->fast_elem_insert(j+k*r, (double)in[i][j][k]);
137  }
138  }
139  }
140 
141  // execute
142  octave_value_list output;
143  output = feval(string(commandName), (*input));
144 
145  // unload outputs
146  if (out.size() != output.length())
147  out.resize(output.length());
148  for (int i=0; i<out.size(); i++) {
149  octave_base_value *obv=output(i).internal_rep();
150  int r=output(i).rows(), c=output(i).columns();
151  if (r!=out[i].size()) // resize the matrix if necessary
152  out[i].resize(r);
153  for (int j=0; j<r; j++){
154  if (c!=out[i][j].size())
155  out[i][j].resize(c);
156  for (int k=0; k<c; k++)
157  out[i][j][k]=(TYPE)obv->fast_elem_extract(j+k*r).double_value();
158  }
159  }
160 
161  return out;
162 }
163 template vector<vector<vector<double> > > &Octave::runM(const char* commandName, const vector<vector<vector<double> > > &in, vector<vector<vector<double> > > &out);
164 template vector<vector<vector<float> > > &Octave::runM(const char* commandName, const vector<vector<vector<float> > > &in, vector<vector<vector<float> > > &out);
165 template vector<vector<vector<long> > > &Octave::runM(const char* commandName, const vector<vector<vector<long> > > &in, vector<vector<vector<long> > > &out);
166 template vector<vector<vector<int> > > &Octave::runM(const char* commandName, const vector<vector<vector<int> > > &in, vector<vector<vector<int> > > &out);
167 
168 template<class TYPE>
169 vector<Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic> > &Octave::runM(const char* commandName, const vector<Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic> > &in, vector<Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic> > &out){
170  //octave_value_list input(in.size()); ///< Input variables to pass to Octave
171  if ((*input).length()<in.size())
172  (*input).resize(in.size());
173 
174  // this code can most likely be sped up using Eigen::Matrix.block operations for memory copies.
175  for (int i=0; i<in.size(); i++) { // cycle through each input
176  int r=in[i].rows(), c=in[i].cols();
177  if ((*input)(i).rows()!=r || (*input)(i).columns()!=c) // resize the matrix if necessary
178  if (r==c && r==1) // scalar
179  (*input)(i)=octave_value(in[i](0,0));
180  else
181  (*input)(i)=Matrix(r, c);
182  if (r>=1 && c>=1){ // if the value is a matrix
183  octave_base_value *obv=(*input)(i).internal_rep();
184  for (int j=0; j<r; j++)
185  for (int k=0; k<c; k++)
186  obv->fast_elem_insert(j+k*r, (double)in[i](j,k));
187  }
188  }
189 
190  octave_value_list output;
191  output = feval(string(commandName), (*input));
192 
193  if (out.size() != output.length())
194  out.resize(output.length());
195  for (int i=0; i<out.size(); i++) {
196  octave_base_value *obv=output(i).internal_rep();
197  int r=output(i).rows(), c=output(i).columns();
198  if (r!=out[i].rows() || c!=out[i].cols()) // resize the matrix if necessary
199  out[i].resize(r, c);
200  for (int j=0; j<r; j++)
201  for (int k=0; k<c; k++)
202  out[i](j,k)=obv->fast_elem_extract(j+k*r).double_value();
203  }
204 
205  return out;
206 }
207 template vector<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> > &Octave::runM(const char* commandName, const vector<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> > &in, vector<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> > &out);
208 template vector<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > &Octave::runM(const char* commandName, const vector<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > &in, vector<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > &out);
209 
210 octave_value_list Octave::runMWithInput(const char* commandName){
211  octave_value_list output;
212  output = feval(string(commandName), (*input));
213  return output;
214 }
215 
216 void Octave::runM(const char* commandName){
217  //output = feval(string(commandName), input, retCount);
218  feval(string(commandName), octave_value_list (), 0);
219 }
220 
221 #ifdef HAVE_OPENCV
222 vector<cv::Mat> &Octave::runM(const char* commandName, const vector<cv::Mat> &in, vector<cv::Mat> &out){
223  //octave_value_list input(in.size()); ///< Input variables to pass to Octave
224  if ((*input).length()<in.size())
225  (*input).resize(in.size());
226 
227  // this code can most likely be sped up using Eigen::Matrix.block operations for memory copies.
228  for (int i=0; i<in.size(); i++) { // cycle through each input
229  if (in[i].type() != CV_64F){
230  cerr<<"Octave::runM : input matrix in["<<i<<"] openCV Matrix types must be CV_64F : error."<<endl;
231  exit(OctaveDebug().evaluateError(OCTAVE_OPENCV_TYPE_ERROR));
232  }
233  int r=in[i].rows, c=in[i].cols;
234  if ((*input)(i).rows()!=r || (*input)(i).columns()!=c) // resize the matrix if necessary
235  (*input)(i)=Matrix(r, c);
236  //Array<double> *m=dynamic_cast<Array<double>*>((*input)(i).internal_rep());
237  octave_base_value *obv=(*input)(i).internal_rep();
238  for (int j=0; j<r; j++){
239  const double* Mj = in[i].ptr<double>(j);
240  for (int k=0; k<c; k++)
241  obv->fast_elem_insert(j+k*r, (double)Mj[k]);
242  //obv->fast_elem_insert(j+k*r, in[i].at<double>(j,k));
243  }
244  }
245 
246  octave_value_list output;
247  //output = feval(string(commandName), input, retCount);
248  output = feval(string(commandName), (*input));
249 
250  if (out.size() != output.length())
251  out.resize(output.length());
252  for (int i=0; i<out.size(); i++) {
253  octave_base_value *obv=output(i).internal_rep();
254  int r=output(i).rows(), c=output(i).columns();
255  if (r!=out[i].rows || c!=out[i].cols) // resize the matrix if necessary
256  out[i].create(r, c, CV_64F);
257  if (out[i].type() != CV_64F){
258  cerr<<"Octave::runM : output matrix out["<<i<<"] openCV Matrix types must be CV_64F : error."<<endl;
259  exit(OctaveDebug().evaluateError(OCTAVE_OPENCV_TYPE_ERROR));
260  }
261  for (int j=0; j<r; j++){
262  double* Mj = out[i].ptr<double>(j);
263  for (int k=0; k<c; k++)
264  Mj[k]=obv->fast_elem_extract(j+k*r).double_value();
265  //out[i].at<double>(j,k)=obv->fast_elem_extract(j+k*r).double_value();
266  }
267  }
268 
269  return out;
270 }
271 #endif
272 
273 int Octave::setGlobalVariable(const string &name, Matrix &m) {
274  vector<string> varNames; // hold all the global var levels and name: level1.level2.name
275  istringstream tokens(name);
276  char baseName[BASENAME_CNT];
277  if (tokens.getline(baseName, BASENAME_CNT, '.')) { // if there is a base name.
278  char subName[BASENAME_CNT];
279  while (tokens.getline(subName, BASENAME_CNT, '.'))
280  varNames.push_back(string(subName));
281 
282  if (varNames.size()) {
283  octave_value ov=get_global_value(string(baseName), true);
284  set_global_value (string(baseName), setGlobalSubVariable(varNames, m, 0, ov));
285  } else
286  set_global_value (string(baseName), m);
287  return 0;
288  } else
289  return OCTAVE_NOBASE_ERROR;
290 }
291 
292 Octave_map Octave::setGlobalSubVariable(const vector<string> &varNames, const Matrix &m, int index, octave_value &base) {
293  cout<<"setGlobalVariable varName = "<<varNames[index]<<" index = "<<index<<" octave_value "<<endl;
294  Octave_map om;
295  Matrix size=base.size();
296  int whichIdx;
297  cout<<"here"<<endl;
298  if (size(0,0)!=0) { // exists, so do a search ...
299  cout<<"here1"<<endl;
300  if (index+1<varNames.size()){
301  cout<<"here1a"<<endl;
302  whichIdx=base.map_keys().lookup(varNames[index+1]); // map_keys returns a string_vector
303  } else { // at the last entry and this must be the location to put
304  cout<<"here1b"<<endl;
305  //cout<<"last var name, must be location in current global struct ... appending"<<endl;
306 // if (base.is_cell())
307 // om=octave_map(base.cell_value().elem(0));
308 // else
309  om=base.map_value();
310 // om=base.cell_value();
311  octave_value nv=m;
312  if (nv.is_cell())
313  cout<<"created a cell"<<endl;
314  om.assign(varNames[index], nv);
315 // om=base(0);
316 // om.setfield(varNames[index], Cell(m));
317  return om;
318  }
319  } else // not present
320  whichIdx=0;
321 
322  cout<<"here2"<<endl;
323  if (whichIdx) { // if present, then keep parsing and assign
324  cout<<"here3"<<endl;
325  cout<<varNames[index+1]<<" found in the map at location "<<whichIdx<<", appending"<<endl;
326  om=base.map_value();
327  //octave_value ov=om.seek(varNames[index])->second.elem(0);
328  //octave_value ov=om.key(om.seek(varNames[index]));
329  //octave_value ov=om.contents(om.seek(varNames[index])).elem(0);
330  octave_value ov=om.getfield(varNames[index]);
331  om.assign(varNames[index], octave_value(setGlobalSubVariable(varNames, m, index+1, ov)));
332  return om;
333  } else { // not present, so start creating a new branch
334  cout<<"here4"<<endl;
335  cout<<varNames[index]<<" not found in the map, creating new"<<endl;
336  if (varNames.size()>index+1) { // more to walk through
337  cout<<varNames[index]<<" not last, walking more"<<endl;
338  Octave_map ret; //(varNames[index].c_str(), dim_vector(1,1));
339  //Cell ret;
340  createGlobalSubVariable(varNames, m, index+1, ret);
341  om.assign(varNames[index].c_str(), octave_value(ret));
342  //om.setfield(varNames[index].c_str(), ret);
343  return om;
344  }
345  cout<<"here5"<<endl;
346  // no more to walk through, assign here
347  cout<<varNames[index]<<" last, appending"<<endl;
348  om.assign(varNames[index].c_str(), octave_value(m));
349  return om;
350  }
351 }
352 Octave_map Octave::createGlobalSubVariable(const vector<string> &varNames, const Matrix &m, int index, Octave_map &base) {
353 
354  //cout<<"setGlobalVariable varName = "<<varNames[index]<<" index = "<<index<<" Octave_map "<<endl;
355  if (index<varNames.size()-1) {
356  //cout<<"not last, creating new to append to"<<endl;
357  Octave_map ret;
358  base.assign(varNames[index].c_str(), createGlobalSubVariable(varNames, m, index+1, ret));
359  return base;
360  }
361  //cout<<"last, appending to"<<endl;
362  base.assign(varNames[index].c_str(), octave_value(m));
363  return base;
364 }
365 
366 Matrix *Octave::newMatrix(int r, int c){
367  return new Matrix(r,c);
368 }
369 void Octave::setMatrixElem(Matrix *m, int i, int j, double val){
370  m->elem(i,j)=val;
371 }
372 
373 void Octave::deleteMatrix(Matrix *m){
374  delete m;
375 }
376 
377 void Octave::clearAll(void){
378  symbol_table::clear_all();
379 }
Octave_map setGlobalSubVariable(const vector< std::string > &varNames, const Matrix &m, int index, octave_value &base)
Definition: Octave.C:292
static void local_exit(int)
Definition: Octave.C:52
void clearAll(void)
Definition: Octave.C:377
void stopOctaveAndExit()
Definition: Octave.C:95
vector< vector< vector< TYPE > > > & runM(const char *commandName, const vector< vector< vector< TYPE > > > &in, vector< vector< vector< TYPE > > > &out)
Definition: Octave.C:104
size(signal)
OCTINTERP_API octave_value_list feval(const string &name, const octave_value_list &args=octave_value_list(), int nargout=0)
OCTINTERP_API bool octave_interpreter_ready
octave_value_list runMWithInput(const char *commandName)
Definition: Octave.C:210
void deleteMatrix(Matrix *m)
Definition: Octave.C:373
#define OCTAVE_OPENCV_TYPE_ERROR
Definition: Octave.H:31
void(* octave_exit_func)(int)
Definition: Octave.C:34
void setMatrixElem(Matrix *m, int i, int j, double val)
Definition: Octave.C:369
void set_global_value(const string &nm, const octave_value &val)
#define BASENAME_CNT
the name max length
Definition: Octave.C:50
void init(void)
Initialisation method common to all constructors.
Definition: Octave.C:63
int setGlobalVariable(const std::string &name, const Eigen::DenseBase< Derived > &var)
Definition: Octave.H:211
#define OCTAVE_INCONSISTENT_COL_CNT_ERROR
Definition: Octave.H:32
OCTINTERP_API void clean_up_and_exit(int, bool)
#define Octave_map
Definition: Octave.H:62
octave_value_list * input
The inputs to pass to the octave .m file.
Definition: Octave.H:122
#define OCTAVE_NOBASE_ERROR
Definition: Octave.H:30
bool isReady(void)
Definition: Octave.C:59
OCTINTERP_API octave_exit_func octave_exit
Definition: Octave.C:53
Octave_map createGlobalSubVariable(const vector< std::string > &varNames, const Matrix &m, int index, Octave_map &base)
Definition: Octave.C:352
void stopOctave()
Definition: Octave.C:99
Octave(void)
Definition: Octave.C:55
Matrix * newMatrix(int r, int c)
Definition: Octave.C:366
void startOctave(const vector< std::string > &args)
Definition: Octave.C:79
virtual ~Octave()
Destructor.
Definition: Octave.C:88
octave_value get_global_value(const string &nm, bool silent=false)
gtkIOStream: /tmp/gtkiostream/src/Octave.C Source File
GTK+ IOStream  Beta