GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
mex.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2006-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cstdarg>
31 #include <cstdlib>
32 #include <cstring>
33 #include <cctype>
34 
35 #include <limits>
36 #include <map>
37 #include <set>
38 #include <string>
39 
40 #include "f77-fcn.h"
41 #include "lo-ieee.h"
42 #include "oct-locbuf.h"
43 #include "quit.h"
44 
45 #include "Cell.h"
46 #include "error.h"
47 #include "interpreter-private.h"
48 #include "interpreter.h"
49 // mxArray must be declared as a class before including mexproto.h.
50 #include "mxarray.h"
51 #include "mexproto.h"
52 #include "oct-map.h"
53 #include "ovl.h"
54 #include "ov.h"
55 #include "ov-classdef.h"
56 #include "ov-mex-fcn.h"
57 #include "ov-usr-fcn.h"
58 #include "pager.h"
59 #include "parse.h"
60 #include "unwind-prot.h"
61 #include "utils.h"
62 #include "variables.h"
63 #include "graphics.h"
64 
65 // #define DEBUG 1
66 
67 static void
68 xfree (void *ptr)
69 {
70  ::free (ptr);
71 }
72 
73 static mwSize
74 max_str_len (mwSize m, const char **str)
75 {
76  int max_len = 0;
77 
78  for (mwSize i = 0; i < m; i++)
79  {
80  mwSize tmp = strlen (str[i]);
81 
82  if (tmp > max_len)
83  max_len = tmp;
84  }
85 
86  return max_len;
87 }
88 
89 static int
90 valid_key (const char *key)
91 {
92  int retval = 0;
93 
94  int nel = strlen (key);
95 
96  if (nel > 0)
97  {
98  if (isalpha (key[0]))
99  {
100  for (int i = 1; i < nel; i++)
101  {
102  if (! (isalnum (key[i]) || key[i] == '_'))
103  return retval;
104  }
105 
106  retval = 1;
107  }
108  }
109 
110  return retval;
111 }
112 
113 // ------------------------------------------------------------------
114 
115 static mwIndex
117  mwSize nsubs, const mwIndex *subs)
118 {
119  mwIndex retval = 0;
120 
121  switch (nsubs)
122  {
123  case 0:
124  break;
125 
126  case 1:
127  retval = subs[0];
128  break;
129 
130  default:
131  {
132  // Both nsubs and ndims should be at least 2 here.
133 
134  mwSize n = (nsubs <= ndims ? nsubs : ndims);
135 
136  retval = subs[--n];
137 
138  while (--n >= 0)
139  retval = dims[n] * retval + subs[n];
140  }
141  break;
142  }
143 
144  return retval;
145 }
146 
147 // The object that handles values pass to MEX files from Octave. Some
148 // methods in this class may set mutate_flag to TRUE to tell the
149 // mxArray class to convert to the Matlab-style representation and
150 // then invoke the method on that object instead (for example, getting
151 // a pointer to real or imaginary data from a complex object requires
152 // a mutation but getting a pointer to real data from a real object
153 // does not). Changing the representation causes a copy so we try to
154 // avoid it unless it is really necessary. Once the conversion
155 // happens, we delete this representation, so the conversion can only
156 // happen once per call to a MEX file.
157 
158 static inline void * maybe_mark_foreign (void *ptr);
159 
161 {
162 public:
163 
165  : mxArray_base (), val (ov), mutate_flag (false),
166  id (mxUNKNOWN_CLASS), class_name (nullptr), ndims (-1), dims (nullptr) { }
167 
168  // No assignment! FIXME: should this be implemented? Note that we
169  // do have a copy constructor.
170 
172 
173  mxArray_base * dup (void) const { return new mxArray_octave_value (*this); }
174 
175  mxArray * as_mxArray (void) const
176  {
178 
179  // RETVAL is assumed to be an mxArray_matlab object. Should we
180  // assert that condition here?
181 
182  if (retval)
183  {
184  // Preserve cached values of class name and dimensions in case
185  // they will be used after we mutate.
186 
187  // set_class_name will handle deleting class name that comes
188  // from as_mxArray conversion function.
189 
190  if (class_name)
191  {
192  retval->set_class_name (class_name);
193 
194  class_name = nullptr;
195  }
196 
197  if (dims)
198  {
199  mwSize *xdims = retval->get_dimensions ();
200 
201  mxFree (xdims);
202 
203  retval->set_dimensions (dims, ndims);
204 
205  dims = nullptr;
206  }
207  }
208 
209  return retval;
210  }
211 
213  {
214  mxFree (class_name);
215  mxFree (dims);
216  }
217 
218  bool is_octave_value (void) const { return true; }
219 
220  int iscell (void) const { return val.iscell (); }
221 
222  int is_char (void) const { return val.is_string (); }
223 
224  int is_complex (void) const { return val.iscomplex (); }
225 
226  int is_double (void) const { return val.is_double_type (); }
227 
228  int is_function_handle (void) const { return val.is_function_handle (); }
229 
230  int is_int16 (void) const { return val.is_int16_type (); }
231 
232  int is_int32 (void) const { return val.is_int32_type (); }
233 
234  int is_int64 (void) const { return val.is_int64_type (); }
235 
236  int is_int8 (void) const { return val.is_int8_type (); }
237 
238  int is_logical (void) const { return val.islogical (); }
239 
240  int is_numeric (void) const { return val.isnumeric (); }
241 
242  int is_single (void) const { return val.is_single_type (); }
243 
244  int is_sparse (void) const { return val.issparse (); }
245 
246  int is_struct (void) const { return val.isstruct (); }
247 
248  int is_uint16 (void) const { return val.is_uint16_type (); }
249 
250  int is_uint32 (void) const { return val.is_uint32_type (); }
251 
252  int is_uint64 (void) const { return val.is_uint64_type (); }
253 
254  int is_uint8 (void) const { return val.is_uint8_type (); }
255 
256  int is_range (void) const { return val.is_range (); }
257 
258  int isreal (void) const { return val.isreal (); }
259 
260  int is_logical_scalar_true (void) const
261  {
262  return (is_logical_scalar () && val.is_true ());
263  }
264 
265  mwSize get_m (void) const { return val.rows (); }
266 
267  mwSize get_n (void) const
268  {
269  mwSize n = 1;
270 
271  // Force dims and ndims to be cached.
272  get_dimensions ();
273 
274  for (mwIndex i = ndims - 1; i > 0; i--)
275  n *= dims[i];
276 
277  return n;
278  }
279 
280  mwSize * get_dimensions (void) const
281  {
282  if (! dims)
283  {
284  ndims = val.ndims ();
285 
286  dims = static_cast<mwSize *> (mxArray::malloc (ndims
287  * sizeof (mwSize)));
288 
289  dim_vector dv = val.dims ();
290 
291  for (mwIndex i = 0; i < ndims; i++)
292  dims[i] = dv(i);
293  }
294 
295  return dims;
296  }
297 
299  {
300  // Force dims and ndims to be cached.
301  get_dimensions ();
302 
303  return ndims;
304  }
305 
306  void set_m (mwSize /*m*/) { request_mutation (); }
307 
308  void set_n (mwSize /*n*/) { request_mutation (); }
309 
310  int set_dimensions (mwSize * /*dims_arg*/, mwSize /*ndims_arg*/)
311  {
312  request_mutation ();
313 
314  return 0;
315  }
316 
317  mwSize get_number_of_elements (void) const { return val.numel (); }
318 
319  int isempty (void) const { return val.isempty (); }
320 
321  bool is_scalar (void) const
322  {
323  // Force dims and ndims to be cached.
324  get_dimensions ();
325 
326  return ndims == 2 && dims[0] == 1 && dims[1] == 1;
327  }
328 
329  mxClassID get_class_id (void) const
330  {
331  id = mxUNKNOWN_CLASS;
332 
333  std::string cn = val.class_name ();
334 
335  if (cn == "double")
336  id = mxDOUBLE_CLASS;
337  else if (cn == "single")
338  id = mxSINGLE_CLASS;
339  else if (cn == "char")
340  id = mxCHAR_CLASS;
341  else if (cn == "logical")
342  id = mxLOGICAL_CLASS;
343  else if (cn == "cell")
344  id = mxCELL_CLASS;
345  else if (cn == "struct")
346  id = mxSTRUCT_CLASS;
347  else if (cn == "function_handle")
348  id = mxFUNCTION_CLASS;
349  else if (cn == "int8")
350  id = mxINT8_CLASS;
351  else if (cn == "uint8")
352  id = mxUINT8_CLASS;
353  else if (cn == "int16")
354  id = mxINT16_CLASS;
355  else if (cn == "uint16")
356  id = mxUINT16_CLASS;
357  else if (cn == "int32")
358  id = mxINT32_CLASS;
359  else if (cn == "uint32")
360  id = mxUINT32_CLASS;
361  else if (cn == "int64")
362  id = mxINT64_CLASS;
363  else if (cn == "uint64")
364  id = mxUINT64_CLASS;
365 
366  return id;
367  }
368 
369  const char * get_class_name (void) const
370  {
371  if (! class_name)
372  {
373  std::string s = val.class_name ();
374  class_name = mxArray::strsave (s.c_str ());
375  }
376 
377  return class_name;
378  }
379 
380  // Not allowed.
381  void set_class_name (const char * /*name_arg*/) { request_mutation (); }
382 
383  mxArray * get_property (mwIndex idx, const char *pname) const
384  {
385  mxArray *retval = nullptr;
386 
387  if (val.is_classdef_object ())
388  {
390 
391  if (ov_cdef)
392  {
393  octave_value pval = ov_cdef->get_property (idx, pname);
394 
395  if (pval.is_defined())
396  retval = new mxArray (pval);
397  }
398  }
399 
400  return retval;
401  }
402 
403  void set_property (mwIndex idx, const char *pname, const mxArray *pval)
404  {
405  if (val.is_classdef_object ())
406  {
408 
409  if (ov_cdef)
410  ov_cdef->set_property (idx, pname, pval->as_octave_value ());
411  }
412  else
413  err_invalid_type ();
414  }
415 
416  mxArray * get_cell (mwIndex /*idx*/) const
417  {
418  request_mutation ();
419  return nullptr;
420  }
421 
422  // Not allowed.
423  void set_cell (mwIndex /*idx*/, mxArray * /*val*/) { request_mutation (); }
424 
425  double get_scalar (void) const
426  {
427  if (val.issparse ())
428  {
429  // For sparse arrays, return the first non-zero value.
430  void *data = val.mex_get_data ();
431  if (data == nullptr)
432  return 0.0;
433 
434  if (val.islogical ())
435  return *static_cast<bool *> (data);
436  else if (val.isreal ())
437  return *static_cast<double *> (data);
438  else // Complex type, only return real part
439  return *static_cast<double *> (data);
440  }
441  else
442  return val.scalar_value (true);
443  }
444 
445  void * get_data (void) const
446  {
447  void *retval = val.mex_get_data ();
448 
449  if (retval)
451  else
452  request_mutation ();
453 
454  return retval;
455  }
456 
457  void * get_imag_data (void) const
458  {
459  void *retval = nullptr;
460 
461  if (is_numeric () && isreal ())
462  retval = nullptr;
463  else
464  request_mutation ();
465 
466  return retval;
467  }
468 
469  // Not allowed.
470  void set_data (void * /*pr*/) { request_mutation (); }
471 
472  // Not allowed.
473  void set_imag_data (void * /*pi*/) { request_mutation (); }
474 
475  mwIndex * get_ir (void) const
476  {
477  return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_ir ()));
478  }
479 
480  mwIndex * get_jc (void) const
481  {
482  return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_jc ()));
483  }
484 
485  mwSize get_nzmax (void) const { return val.nzmax (); }
486 
487  // Not allowed.
488  void set_ir (mwIndex * /*ir*/) { request_mutation (); }
489 
490  // Not allowed.
491  void set_jc (mwIndex * /*jc*/) { request_mutation (); }
492 
493  // Not allowed.
494  void set_nzmax (mwSize /*nzmax*/) { request_mutation (); }
495 
496  // Not allowed.
497  int add_field (const char * /*key*/)
498  {
499  request_mutation ();
500  return 0;
501  }
502 
503  // Not allowed.
504  void remove_field (int /*key_num*/) { request_mutation (); }
505 
506  mxArray * get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
507  {
508  request_mutation ();
509  return nullptr;
510  }
511 
512  // Not allowed.
513  void set_field_by_number (mwIndex /*index*/, int /*key_num*/,
514  mxArray * /*val*/)
515  {
516  request_mutation ();
517  }
518 
519  int get_number_of_fields (void) const { return val.nfields (); }
520 
521  const char * get_field_name_by_number (int /*key_num*/) const
522  {
523  request_mutation ();
524  return nullptr;
525  }
526 
527  int get_field_number (const char * /*key*/) const
528  {
529  request_mutation ();
530  return 0;
531  }
532 
533  int get_string (char *buf, mwSize buflen) const
534  {
535  int retval = 1;
536 
538 
539  if (val.is_string () && nel < buflen)
540  {
542 
543  const char *p = tmp.data ();
544 
545  for (mwIndex i = 0; i < nel; i++)
546  buf[i] = p[i];
547 
548  buf[nel] = 0;
549 
550  retval = 0;
551  }
552 
553  return retval;
554  }
555 
556  char * array_to_string (void) const
557  {
558  // FIXME: this is supposed to handle multi-byte character strings.
559 
560  char *buf = nullptr;
561 
562  if (val.is_string ())
563  {
565 
566  buf = static_cast<char *> (mxArray::malloc (nel + 1));
567 
568  if (buf)
569  {
571 
572  const char *p = tmp.data ();
573 
574  for (mwIndex i = 0; i < nel; i++)
575  buf[i] = p[i];
576 
577  buf[nel] = '\0';
578  }
579  }
580 
581  return buf;
582  }
583 
585  {
586  // Force ndims, dims to be cached.
587  get_dimensions ();
588 
589  return calc_single_subscript_internal (ndims, dims, nsubs, subs);
590  }
591 
592  size_t get_element_size (void) const
593  {
594  // Force id to be cached.
595  get_class_id ();
596 
597  switch (id)
598  {
599  case mxDOUBLE_CLASS: return sizeof (double);
600  case mxSINGLE_CLASS: return sizeof (float);
601  case mxCHAR_CLASS: return sizeof (mxChar);
602  case mxLOGICAL_CLASS: return sizeof (mxLogical);
603  case mxCELL_CLASS: return sizeof (mxArray *);
604  case mxSTRUCT_CLASS: return sizeof (mxArray *);
605  case mxFUNCTION_CLASS: return 0;
606  case mxINT8_CLASS: return 1;
607  case mxUINT8_CLASS: return 1;
608  case mxINT16_CLASS: return 2;
609  case mxUINT16_CLASS: return 2;
610  case mxINT32_CLASS: return 4;
611  case mxUINT32_CLASS: return 4;
612  case mxINT64_CLASS: return 8;
613  case mxUINT64_CLASS: return 8;
614  // FIXME: user-defined objects need their own class ID.
615  // What should they return, size of pointer?
616  default: return 0;
617  }
618  }
619 
620  bool mutation_needed (void) const { return mutate_flag; }
621 
622  void request_mutation (void) const
623  {
624  if (mutate_flag)
625  panic_impossible ();
626 
627  mutate_flag = true;
628  }
629 
630  mxArray * mutate (void) const { return as_mxArray (); }
631 
632  octave_value as_octave_value (void) const { return val; }
633 
634 protected:
635 
637  : mxArray_base (arg), val (arg.val), mutate_flag (arg.mutate_flag),
638  id (arg.id), class_name (mxArray::strsave (arg.class_name)),
639  ndims (arg.ndims),
640  dims (ndims > 0 ? static_cast<mwSize *>
641  (mxArray::malloc (ndims * sizeof (mwSize)))
642  : nullptr)
643  {
644  if (dims)
645  {
646  for (mwIndex i = 0; i < ndims; i++)
647  dims[i] = arg.dims[i];
648  }
649  }
650 
651 private:
652 
654 
655  mutable bool mutate_flag;
656 
657  // Caching these does not cost much or lead to much duplicated
658  // code. For other things, we just request mutation to a
659  // Matlab-style mxArray object.
660 
661  mutable mxClassID id;
662  mutable char *class_name;
663  mutable mwSize ndims;
664  mutable mwSize *dims;
665 };
666 
667 // The base class for the Matlab-style representation, used to handle
668 // things that are common to all Matlab-style objects.
669 
671 {
672 protected:
673 
675  : mxArray_base (), class_name (nullptr), id (id_arg), ndims (0),
676  dims (nullptr)
677  { }
678 
679  mxArray_matlab (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg)
680  : mxArray_base (), class_name (nullptr), id (id_arg),
681  ndims (ndims_arg < 2 ? 2 : ndims_arg),
682  dims (static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize))))
683  {
684  if (ndims_arg == 0)
685  {
686  dims[0] = 0;
687  dims[1] = 0;
688  }
689  else if (ndims_arg < 2)
690  {
691  dims[0] = 1;
692  dims[1] = 1;
693  }
694 
695  for (mwIndex i = 0; i < ndims_arg; i++)
696  dims[i] = dims_arg[i];
697 
698  for (mwIndex i = ndims - 1; i > 1; i--)
699  {
700  if (dims[i] == 1)
701  ndims--;
702  else
703  break;
704  }
705  }
706 
707  mxArray_matlab (mxClassID id_arg, const dim_vector& dv)
708  : mxArray_base (), class_name (nullptr), id (id_arg),
709  ndims (dv.ndims ()),
710  dims (static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize))))
711  {
712  for (mwIndex i = 0; i < ndims; i++)
713  dims[i] = dv(i);
714 
715  for (mwIndex i = ndims - 1; i > 1; i--)
716  {
717  if (dims[i] == 1)
718  ndims--;
719  else
720  break;
721  }
722  }
723 
725  : mxArray_base (), class_name (nullptr), id (id_arg), ndims (2),
726  dims (static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize))))
727  {
728  dims[0] = m;
729  dims[1] = n;
730  }
731 
734  id (val.id), ndims (val.ndims),
735  dims (static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize))))
736  {
737  for (mwIndex i = 0; i < ndims; i++)
738  dims[i] = val.dims[i];
739  }
740 
741 public:
742 
743  // No assignment!
744  // FIXME: should this be implemented?
745  // Note that we *do* have a copy constructor.
746 
748 
750  {
751  mxFree (class_name);
752  mxFree (dims);
753  }
754 
755  int iscell (void) const { return id == mxCELL_CLASS; }
756 
757  int is_char (void) const { return id == mxCHAR_CLASS; }
758 
759  int is_complex (void) const { return 0; }
760 
761  int is_double (void) const { return id == mxDOUBLE_CLASS; }
762 
763  int is_function_handle (void) const { return id == mxFUNCTION_CLASS; }
764 
765  int is_int16 (void) const { return id == mxINT16_CLASS; }
766 
767  int is_int32 (void) const { return id == mxINT32_CLASS; }
768 
769  int is_int64 (void) const { return id == mxINT64_CLASS; }
770 
771  int is_int8 (void) const { return id == mxINT8_CLASS; }
772 
773  int is_logical (void) const { return id == mxLOGICAL_CLASS; }
774 
775  int is_numeric (void) const
776  {
777  return (id == mxDOUBLE_CLASS || id == mxSINGLE_CLASS
778  || id == mxINT8_CLASS || id == mxUINT8_CLASS
779  || id == mxINT16_CLASS || id == mxUINT16_CLASS
780  || id == mxINT32_CLASS || id == mxUINT32_CLASS
781  || id == mxINT64_CLASS || id == mxUINT64_CLASS);
782  }
783 
784  int is_single (void) const { return id == mxSINGLE_CLASS; }
785 
786  int is_sparse (void) const { return 0; }
787 
788  int is_struct (void) const { return id == mxSTRUCT_CLASS; }
789 
790  int is_uint16 (void) const { return id == mxUINT16_CLASS; }
791 
792  int is_uint32 (void) const { return id == mxUINT32_CLASS; }
793 
794  int is_uint64 (void) const { return id == mxUINT64_CLASS; }
795 
796  int is_uint8 (void) const { return id == mxUINT8_CLASS; }
797 
798  int is_logical_scalar_true (void) const
799  {
800  return (is_logical_scalar ()
801  && static_cast<mxLogical *> (get_data ())[0] != 0);
802  }
803 
804  mwSize get_m (void) const { return dims[0]; }
805 
806  mwSize get_n (void) const
807  {
808  mwSize n = 1;
809 
810  for (mwSize i = ndims - 1 ; i > 0 ; i--)
811  n *= dims[i];
812 
813  return n;
814  }
815 
816  mwSize * get_dimensions (void) const { return dims; }
817 
818  mwSize get_number_of_dimensions (void) const { return ndims; }
819 
820  void set_m (mwSize m) { dims[0] = m; }
821 
822  void set_n (mwSize n) { dims[1] = n; }
823 
824  int set_dimensions (mwSize *dims_arg, mwSize ndims_arg)
825  {
826  ndims = ndims_arg;
827 
828  mxFree (dims);
829 
830  if (ndims > 0)
831  {
832  dims
833  = static_cast<mwSize *> (mxArray::malloc (ndims * sizeof (mwSize)));
834 
835  if (dims == nullptr)
836  return 1;
837 
838  for (int i = 0; i < ndims; i++)
839  dims[i] = dims_arg[i];
840 
841  return 0;
842  }
843  else
844  {
845  dims = nullptr;
846  return 0;
847  }
848  }
849 
851  {
852  mwSize retval = dims[0];
853 
854  for (mwIndex i = 1; i < ndims; i++)
855  retval *= dims[i];
856 
857  return retval;
858  }
859 
860  int isempty (void) const { return get_number_of_elements () == 0; }
861 
862  bool is_scalar (void) const
863  {
864  return ndims == 2 && dims[0] == 1 && dims[1] == 1;
865  }
866 
867  mxClassID get_class_id (void) const { return id; }
868 
869  const char * get_class_name (void) const
870  {
871  switch (id)
872  {
873  case mxDOUBLE_CLASS: return "double";
874  case mxSINGLE_CLASS: return "single";
875  case mxCHAR_CLASS: return "char";
876  case mxLOGICAL_CLASS: return "logical";
877  case mxCELL_CLASS: return "cell";
878  case mxSTRUCT_CLASS: return "struct";
879  case mxFUNCTION_CLASS: return "function_handle";
880  case mxINT8_CLASS: return "int8";
881  case mxUINT8_CLASS: return "uint8";
882  case mxINT16_CLASS: return "int16";
883  case mxUINT16_CLASS: return "uint16";
884  case mxINT32_CLASS: return "int32";
885  case mxUINT32_CLASS: return "uint32";
886  case mxINT64_CLASS: return "int64";
887  case mxUINT64_CLASS: return "uint64";
888  case mxUNKNOWN_CLASS: return "unknown";
889  // FIXME: should return the classname of user-defined objects
890  default: return "unknown";
891  }
892  }
893 
894  void set_class_name (const char *name_arg)
895  {
896  mxFree (class_name);
897  class_name = static_cast<char *> (mxArray::malloc (strlen (name_arg) + 1));
898  strcpy (class_name, name_arg);
899  }
900 
901  mxArray * get_cell (mwIndex /*idx*/) const
902  {
903  err_invalid_type ();
904  }
905 
906  void set_cell (mwIndex /*idx*/, mxArray * /*val*/)
907  {
908  err_invalid_type ();
909  }
910 
911  double get_scalar (void) const
912  {
913  err_invalid_type ();
914  }
915 
916  void * get_data (void) const
917  {
918  err_invalid_type ();
919  }
920 
921  void * get_imag_data (void) const
922  {
923  err_invalid_type ();
924  }
925 
926  void set_data (void * /*pr*/)
927  {
928  err_invalid_type ();
929  }
930 
931  void set_imag_data (void * /*pi*/)
932  {
933  err_invalid_type ();
934  }
935 
936  mwIndex * get_ir (void) const
937  {
938  err_invalid_type ();
939  }
940 
941  mwIndex * get_jc (void) const
942  {
943  err_invalid_type ();
944  }
945 
946  mwSize get_nzmax (void) const
947  {
948  err_invalid_type ();
949  }
950 
951  void set_ir (mwIndex * /*ir*/)
952  {
953  err_invalid_type ();
954  }
955 
956  void set_jc (mwIndex * /*jc*/)
957  {
958  err_invalid_type ();
959  }
960 
961  void set_nzmax (mwSize /*nzmax*/)
962  {
963  err_invalid_type ();
964  }
965 
966  int add_field (const char * /*key*/)
967  {
968  err_invalid_type ();
969  }
970 
971  void remove_field (int /*key_num*/)
972  {
973  err_invalid_type ();
974  }
975 
976  mxArray * get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
977  {
978  err_invalid_type ();
979  }
980 
981  void set_field_by_number (mwIndex /*index*/, int /*key_num*/,
982  mxArray * /*val*/)
983  {
984  err_invalid_type ();
985  }
986 
987  int get_number_of_fields (void) const
988  {
989  err_invalid_type ();
990  }
991 
992  const char * get_field_name_by_number (int /*key_num*/) const
993  {
994  err_invalid_type ();
995  }
996 
997  int get_field_number (const char * /*key*/) const
998  {
999  return -1;
1000  }
1001 
1002  int get_string (char * /*buf*/, mwSize /*buflen*/) const
1003  {
1004  err_invalid_type ();
1005  }
1006 
1007  char * array_to_string (void) const
1008  {
1009  err_invalid_type ();
1010  }
1011 
1013  {
1014  return calc_single_subscript_internal (ndims, dims, nsubs, subs);
1015  }
1016 
1017  size_t get_element_size (void) const
1018  {
1019  switch (id)
1020  {
1021  case mxCELL_CLASS: return sizeof (mxArray *);
1022  case mxSTRUCT_CLASS: return sizeof (mxArray *);
1023  case mxLOGICAL_CLASS: return sizeof (mxLogical);
1024  case mxCHAR_CLASS: return sizeof (mxChar);
1025  case mxDOUBLE_CLASS: return sizeof (double);
1026  case mxSINGLE_CLASS: return sizeof (float);
1027  case mxINT8_CLASS: return 1;
1028  case mxUINT8_CLASS: return 1;
1029  case mxINT16_CLASS: return 2;
1030  case mxUINT16_CLASS: return 2;
1031  case mxINT32_CLASS: return 4;
1032  case mxUINT32_CLASS: return 4;
1033  case mxINT64_CLASS: return 8;
1034  case mxUINT64_CLASS: return 8;
1035  case mxFUNCTION_CLASS: return 0;
1036  // FIXME: user-defined objects need their own class ID.
1037  // What should they return, size of pointer?
1038  default: return 0;
1039  }
1040  }
1041 
1042 protected:
1043 
1044  dim_vector
1045  dims_to_dim_vector (void) const
1046  {
1048 
1049  mwSize *d = get_dimensions ();
1050 
1051  dim_vector dv;
1052  dv.resize (nd);
1053 
1054  for (mwIndex i = 0; i < nd; i++)
1055  dv(i) = d[i];
1056 
1057  return dv;
1058  }
1059 
1060 private:
1061 
1062  char *class_name;
1063 
1065 
1068 
1069  OCTAVE_NORETURN void err_invalid_type (void) const
1070  {
1071  error ("invalid type for operation");
1072  }
1073 };
1074 
1075 // Matlab-style numeric, character, and logical data.
1076 
1078 {
1079 public:
1080 
1081  mxArray_number (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg,
1082  mxComplexity flag = mxREAL, bool init = true)
1083  : mxArray_matlab (id_arg, ndims_arg, dims_arg),
1084  pr (init ? mxArray::calloc (get_number_of_elements (),
1085  get_element_size ())
1087  * get_element_size ())),
1088  pi (flag == mxCOMPLEX
1089  ? (init ? mxArray::calloc (get_number_of_elements (),
1090  get_element_size ())
1092  * get_element_size ()))
1093  : nullptr) { }
1094 
1096  mxComplexity flag = mxREAL)
1097  : mxArray_matlab (id_arg, dv),
1099  pi (flag == mxCOMPLEX ? mxArray::calloc (get_number_of_elements (),
1100  get_element_size ())
1101  : nullptr)
1102  { }
1103 
1105  mxComplexity flag = mxREAL, bool init = true)
1106  : mxArray_matlab (id_arg, m, n),
1107  pr (init ? mxArray::calloc (get_number_of_elements (),
1108  get_element_size ())
1110  * get_element_size ())),
1111  pi (flag == mxCOMPLEX
1112  ? (init ? mxArray::calloc (get_number_of_elements (),
1113  get_element_size ())
1115  * get_element_size ()))
1116  : nullptr)
1117  { }
1118 
1119  mxArray_number (mxClassID id_arg, double val)
1120  : mxArray_matlab (id_arg, 1, 1),
1122  pi (nullptr)
1123  {
1124  double *dpr = static_cast<double *> (pr);
1125  dpr[0] = val;
1126  }
1127 
1129  : mxArray_matlab (id_arg, 1, 1),
1131  pi (nullptr)
1132  {
1133  mxLogical *lpr = static_cast<mxLogical *> (pr);
1134  lpr[0] = val;
1135  }
1136 
1137  mxArray_number (const char *str)
1139  str ? (strlen (str) ? 1 : 0) : 0,
1140  str ? strlen (str) : 0),
1142  pi (nullptr)
1143  {
1144  mxChar *cpr = static_cast<mxChar *> (pr);
1145  mwSize nel = get_number_of_elements ();
1146  for (mwIndex i = 0; i < nel; i++)
1147  cpr[i] = str[i];
1148  }
1149 
1150  // FIXME: ???
1151  mxArray_number (mwSize m, const char **str)
1152  : mxArray_matlab (mxCHAR_CLASS, m, max_str_len (m, str)),
1154  pi (nullptr)
1155  {
1156  mxChar *cpr = static_cast<mxChar *> (pr);
1157 
1158  mwSize *dv = get_dimensions ();
1159 
1160  mwSize nc = dv[1];
1161 
1162  for (mwIndex j = 0; j < m; j++)
1163  {
1164  const char *ptr = str[j];
1165 
1166  size_t tmp_len = strlen (ptr);
1167 
1168  for (size_t i = 0; i < tmp_len; i++)
1169  cpr[m*i+j] = static_cast<mxChar> (ptr[i]);
1170 
1171  for (size_t i = tmp_len; i < static_cast<size_t> (nc); i++)
1172  cpr[m*i+j] = static_cast<mxChar> (' ');
1173  }
1174  }
1175 
1176 protected:
1177 
1179  : mxArray_matlab (val),
1182  * get_element_size ())
1183  : nullptr)
1184  {
1185  size_t nbytes = get_number_of_elements () * get_element_size ();
1186 
1187  if (pr)
1188  memcpy (pr, val.pr, nbytes);
1189 
1190  if (pi)
1191  memcpy (pi, val.pi, nbytes);
1192  }
1193 
1194 public:
1195 
1196  // No assignment! FIXME: should this be implemented? Note that we
1197  // do have a copy constructor.
1198 
1200 
1201  mxArray_base * dup (void) const { return new mxArray_number (*this); }
1202 
1204  {
1205  mxFree (pr);
1206  mxFree (pi);
1207  }
1208 
1209  int is_complex (void) const { return pi != nullptr; }
1210 
1211  double get_scalar (void) const
1212  {
1213  double retval = 0;
1214 
1215  switch (get_class_id ())
1216  {
1217  case mxDOUBLE_CLASS:
1218  retval = *(static_cast<double *> (pr));
1219  break;
1220 
1221  case mxSINGLE_CLASS:
1222  retval = *(static_cast<float *> (pr));
1223  break;
1224 
1225  case mxCHAR_CLASS:
1226  retval = *(static_cast<mxChar *> (pr));
1227  break;
1228 
1229  case mxLOGICAL_CLASS:
1230  retval = *(static_cast<bool *> (pr));
1231  break;
1232 
1233  case mxINT8_CLASS:
1234  retval = *(static_cast<int8_t *> (pr));
1235  break;
1236 
1237  case mxUINT8_CLASS:
1238  retval = *(static_cast<uint8_t *> (pr));
1239  break;
1240 
1241  case mxINT16_CLASS:
1242  retval = *(static_cast<int16_t *> (pr));
1243  break;
1244 
1245  case mxUINT16_CLASS:
1246  retval = *(static_cast<uint16_t *> (pr));
1247  break;
1248 
1249  case mxINT32_CLASS:
1250  retval = *(static_cast<int32_t *> (pr));
1251  break;
1252 
1253  case mxUINT32_CLASS:
1254  retval = *(static_cast<uint32_t *> (pr));
1255  break;
1256 
1257  case mxINT64_CLASS:
1258  retval = *(static_cast<int64_t *> (pr));
1259  break;
1260 
1261  case mxUINT64_CLASS:
1262  retval = *(static_cast<uint64_t *> (pr));
1263  break;
1264 
1265  default:
1266  panic_impossible ();
1267  }
1268 
1269  return retval;
1270  }
1271 
1272  void * get_data (void) const { return pr; }
1273 
1274  void * get_imag_data (void) const { return pi; }
1275 
1276  void set_data (void *pr_arg) { pr = pr_arg; }
1277 
1278  void set_imag_data (void *pi_arg) { pi = pi_arg; }
1279 
1280  int get_string (char *buf, mwSize buflen) const
1281  {
1282  int retval = 0;
1283 
1284  mwSize nel = get_number_of_elements ();
1285 
1286  if (! (nel < buflen))
1287  {
1288  retval = 1;
1289  if (buflen > 0)
1290  nel = buflen-1;
1291  }
1292 
1293  if (nel < buflen)
1294  {
1295  mxChar *ptr = static_cast<mxChar *> (pr);
1296 
1297  for (mwIndex i = 0; i < nel; i++)
1298  buf[i] = static_cast<char> (ptr[i]);
1299 
1300  buf[nel] = 0;
1301  }
1302 
1303  return retval;
1304  }
1305 
1306  char * array_to_string (void) const
1307  {
1308  // FIXME: this is supposed to handle multi-byte character strings.
1309 
1310  mwSize nel = get_number_of_elements ();
1311 
1312  char *buf = static_cast<char *> (mxArray::malloc (nel + 1));
1313 
1314  if (buf)
1315  {
1316  mxChar *ptr = static_cast<mxChar *> (pr);
1317 
1318  for (mwIndex i = 0; i < nel; i++)
1319  buf[i] = static_cast<char> (ptr[i]);
1320 
1321  buf[nel] = '\0';
1322  }
1323 
1324  return buf;
1325  }
1326 
1328  {
1330 
1332 
1333  switch (get_class_id ())
1334  {
1335  case mxDOUBLE_CLASS:
1336  {
1337  mwSize nel = get_number_of_elements ();
1338 
1339  double *ppr = static_cast<double *> (pr);
1340 
1341  if (pi)
1342  {
1343  ComplexNDArray val (dv);
1344 
1345  Complex *ptr = val.fortran_vec ();
1346 
1347  double *ppi = static_cast<double *> (pi);
1348 
1349  for (mwIndex i = 0; i < nel; i++)
1350  ptr[i] = Complex (ppr[i], ppi[i]);
1351 
1352  retval = val;
1353  }
1354  else
1355  {
1356  NDArray val (dv);
1357 
1358  double *ptr = val.fortran_vec ();
1359 
1360  for (mwIndex i = 0; i < nel; i++)
1361  ptr[i] = ppr[i];
1362 
1363  retval = val;
1364  }
1365  }
1366  break;
1367 
1368  case mxSINGLE_CLASS:
1369  {
1370  mwSize nel = get_number_of_elements ();
1371 
1372  float *ppr = static_cast<float *> (pr);
1373 
1374  if (pi)
1375  {
1376  FloatComplexNDArray val (dv);
1377 
1378  FloatComplex *ptr = val.fortran_vec ();
1379 
1380  float *ppi = static_cast<float *> (pi);
1381 
1382  for (mwIndex i = 0; i < nel; i++)
1383  ptr[i] = FloatComplex (ppr[i], ppi[i]);
1384 
1385  retval = val;
1386  }
1387  else
1388  {
1389  FloatNDArray val (dv);
1390 
1391  float *ptr = val.fortran_vec ();
1392 
1393  for (mwIndex i = 0; i < nel; i++)
1394  ptr[i] = ppr[i];
1395 
1396  retval = val;
1397  }
1398  }
1399  break;
1400 
1401  case mxCHAR_CLASS:
1402  {
1403  mwSize nel = get_number_of_elements ();
1404 
1405  mxChar *ppr = static_cast<mxChar *> (pr);
1406 
1407  charNDArray val (dv);
1408 
1409  char *ptr = val.fortran_vec ();
1410 
1411  for (mwIndex i = 0; i < nel; i++)
1412  ptr[i] = static_cast<char> (ppr[i]);
1413 
1414  retval = val;
1415  }
1416  break;
1417 
1418  case mxLOGICAL_CLASS:
1419  retval = int_to_ov<mxLogical, boolNDArray, bool> (dv);
1420  break;
1421 
1422  case mxINT8_CLASS:
1423  retval = int_to_ov<int8_t, int8NDArray, octave_int8> (dv);
1424  break;
1425 
1426  case mxUINT8_CLASS:
1427  retval = int_to_ov<uint8_t, uint8NDArray, octave_uint8> (dv);
1428  break;
1429 
1430  case mxINT16_CLASS:
1431  retval = int_to_ov<int16_t, int16NDArray, octave_int16> (dv);
1432  break;
1433 
1434  case mxUINT16_CLASS:
1435  retval = int_to_ov<uint16_t, uint16NDArray, octave_uint16> (dv);
1436  break;
1437 
1438  case mxINT32_CLASS:
1439  retval = int_to_ov<int32_t, int32NDArray, octave_int32> (dv);
1440  break;
1441 
1442  case mxUINT32_CLASS:
1443  retval = int_to_ov<uint32_t, uint32NDArray, octave_uint32> (dv);
1444  break;
1445 
1446  case mxINT64_CLASS:
1447  retval = int_to_ov<int64_t, int64NDArray, octave_int64> (dv);
1448  break;
1449 
1450  case mxUINT64_CLASS:
1451  retval = int_to_ov<uint64_t, uint64NDArray, octave_uint64> (dv);
1452  break;
1453 
1454  default:
1455  panic_impossible ();
1456  }
1457 
1458  return retval;
1459  }
1460 
1461 protected:
1462 
1463  template <typename ELT_T, typename ARRAY_T, typename ARRAY_ELT_T>
1464  octave_value
1465  int_to_ov (const dim_vector& dv) const
1466  {
1467  if (pi)
1468  error ("complex integer types are not supported");
1469 
1470  mwSize nel = get_number_of_elements ();
1471 
1472  ELT_T *ppr = static_cast<ELT_T *> (pr);
1473 
1474  ARRAY_T val (dv);
1475 
1476  ARRAY_ELT_T *ptr = val.fortran_vec ();
1477 
1478  for (mwIndex i = 0; i < nel; i++)
1479  ptr[i] = ppr[i];
1480 
1481  return octave_value (val);
1482  }
1483 
1484 private:
1485 
1486  void *pr;
1487  void *pi;
1488 };
1489 
1490 // Matlab-style sparse arrays.
1491 
1493 {
1494 public:
1495 
1497  mxComplexity flag = mxREAL)
1498  : mxArray_matlab (id_arg, m, n)
1499  {
1500  nzmax = (nzmax_arg > 0 ? nzmax_arg : 1);
1503  : nullptr);
1504  ir = (static_cast<mwIndex *> (mxArray::calloc (nzmax, sizeof (mwIndex))));
1505  jc = (static_cast<mwIndex *> (mxArray::calloc (n + 1, sizeof (mwIndex))));
1506  }
1507 
1508 private:
1509 
1511  : mxArray_matlab (val), nzmax (val.nzmax),
1513  pi (val.pi ? mxArray::malloc (nzmax * get_element_size ()) : nullptr),
1514  ir (static_cast<mwIndex *> (mxArray::malloc (nzmax * sizeof (mwIndex)))),
1515  jc (static_cast<mwIndex *> (mxArray::malloc (nzmax * sizeof (mwIndex))))
1516  {
1517  size_t nbytes = nzmax * get_element_size ();
1518 
1519  if (pr)
1520  memcpy (pr, val.pr, nbytes);
1521 
1522  if (pi)
1523  memcpy (pi, val.pi, nbytes);
1524 
1525  if (ir)
1526  memcpy (ir, val.ir, nzmax * sizeof (mwIndex));
1527 
1528  if (jc)
1529  memcpy (jc, val.jc, (val.get_n () + 1) * sizeof (mwIndex));
1530  }
1531 
1532 public:
1533 
1534  // No assignment! FIXME: should this be implemented? Note that we
1535  // do have a copy constructor.
1536 
1538 
1539  mxArray_base * dup (void) const { return new mxArray_sparse (*this); }
1540 
1542  {
1543  mxFree (pr);
1544  mxFree (pi);
1545  mxFree (ir);
1546  mxFree (jc);
1547  }
1548 
1549  int is_complex (void) const { return pi != nullptr; }
1550 
1551  int is_sparse (void) const { return 1; }
1552 
1553  void * get_data (void) const { return pr; }
1554 
1555  void * get_imag_data (void) const { return pi; }
1556 
1557  void set_data (void *pr_arg) { pr = pr_arg; }
1558 
1559  void set_imag_data (void *pi_arg) { pi = pi_arg; }
1560 
1561  mwIndex * get_ir (void) const { return ir; }
1562 
1563  mwIndex * get_jc (void) const { return jc; }
1564 
1565  mwSize get_nzmax (void) const { return nzmax; }
1566 
1567  void set_ir (mwIndex *ir_arg) { ir = ir_arg; }
1568 
1569  void set_jc (mwIndex *jc_arg) { jc = jc_arg; }
1570 
1571  void set_nzmax (mwSize nzmax_arg)
1572  {
1573  /* Require storage for at least 1 element */
1574  nzmax = (nzmax_arg > 0 ? nzmax_arg : 1);
1575  }
1576 
1578  {
1580 
1582 
1583  switch (get_class_id ())
1584  {
1585  case mxDOUBLE_CLASS:
1586  {
1587  if (pi)
1588  {
1589  double *ppr = static_cast<double *> (pr);
1590  double *ppi = static_cast<double *> (pi);
1591 
1592  SparseComplexMatrix val (get_m (), get_n (),
1593  static_cast<octave_idx_type> (nzmax));
1594 
1595  for (mwIndex i = 0; i < nzmax; i++)
1596  {
1597  val.xdata (i) = Complex (ppr[i], ppi[i]);
1598  val.xridx (i) = ir[i];
1599  }
1600 
1601  for (mwIndex i = 0; i < get_n () + 1; i++)
1602  val.xcidx (i) = jc[i];
1603 
1604  retval = val;
1605  }
1606  else
1607  {
1608  double *ppr = static_cast<double *> (pr);
1609 
1610  SparseMatrix val (get_m (), get_n (),
1611  static_cast<octave_idx_type> (nzmax));
1612 
1613  for (mwIndex i = 0; i < nzmax; i++)
1614  {
1615  val.xdata (i) = ppr[i];
1616  val.xridx (i) = ir[i];
1617  }
1618 
1619  for (mwIndex i = 0; i < get_n () + 1; i++)
1620  val.xcidx (i) = jc[i];
1621 
1622  retval = val;
1623  }
1624  }
1625  break;
1626 
1627  case mxLOGICAL_CLASS:
1628  {
1629  bool *ppr = static_cast<bool *> (pr);
1630 
1631  SparseBoolMatrix val (get_m (), get_n (),
1632  static_cast<octave_idx_type> (nzmax));
1633 
1634  for (mwIndex i = 0; i < nzmax; i++)
1635  {
1636  val.xdata (i) = ppr[i];
1637  val.xridx (i) = ir[i];
1638  }
1639 
1640  for (mwIndex i = 0; i < get_n () + 1; i++)
1641  val.xcidx (i) = jc[i];
1642 
1643  retval = val;
1644  }
1645  break;
1646 
1647  case mxSINGLE_CLASS:
1648  error ("single precision sparse data type not supported");
1649  break;
1650 
1651  default:
1652  panic_impossible ();
1653  }
1654 
1655  return retval;
1656  }
1657 
1658 private:
1659 
1661 
1662  void *pr;
1663  void *pi;
1666 };
1667 
1668 // Matlab-style struct arrays.
1669 
1671 {
1672 public:
1673 
1674  mxArray_struct (mwSize ndims_arg, const mwSize *dims_arg, int num_keys_arg,
1675  const char **keys)
1676  : mxArray_matlab (mxSTRUCT_CLASS, ndims_arg, dims_arg),
1677  nfields (num_keys_arg),
1678  fields (static_cast<char **> (mxArray::calloc (nfields,
1679  sizeof (char *)))),
1680  data (static_cast<mxArray **> (mxArray::calloc (nfields *
1682  sizeof (mxArray *))))
1683  {
1684  init (keys);
1685  }
1686 
1687  mxArray_struct (const dim_vector& dv, int num_keys_arg, const char **keys)
1688  : mxArray_matlab (mxSTRUCT_CLASS, dv), nfields (num_keys_arg),
1689  fields (static_cast<char **> (mxArray::calloc (nfields,
1690  sizeof (char *)))),
1691  data (static_cast<mxArray **> (mxArray::calloc (nfields *
1693  sizeof (mxArray *))))
1694  {
1695  init (keys);
1696  }
1697 
1698  mxArray_struct (mwSize m, mwSize n, int num_keys_arg, const char **keys)
1699  : mxArray_matlab (mxSTRUCT_CLASS, m, n), nfields (num_keys_arg),
1700  fields (static_cast<char **> (mxArray::calloc (nfields,
1701  sizeof (char *)))),
1702  data (static_cast<mxArray **> (mxArray::calloc (nfields *
1704  sizeof (mxArray *))))
1705  {
1706  init (keys);
1707  }
1708 
1709 private:
1710 
1712  : mxArray_matlab (val), nfields (val.nfields),
1713  fields (static_cast<char **> (mxArray::malloc (nfields
1714  * sizeof (char *)))),
1715  data (static_cast<mxArray **> (mxArray::malloc (nfields *
1717  * sizeof (mxArray *))))
1718  {
1719  for (int i = 0; i < nfields; i++)
1720  fields[i] = mxArray::strsave (val.fields[i]);
1721 
1722  mwSize nel = get_number_of_elements ();
1723 
1724  for (mwIndex i = 0; i < nel * nfields; i++)
1725  {
1726  mxArray *ptr = val.data[i];
1727  data[i] = (ptr ? ptr->dup () : nullptr);
1728  }
1729  }
1730 
1731 public:
1732 
1733  // No assignment! FIXME: should this be implemented? Note that we
1734  // do have a copy constructor.
1735 
1737 
1738  void init (const char **keys)
1739  {
1740  for (int i = 0; i < nfields; i++)
1741  fields[i] = mxArray::strsave (keys[i]);
1742  }
1743 
1744  mxArray_base * dup (void) const { return new mxArray_struct (*this); }
1745 
1747  {
1748  for (int i = 0; i < nfields; i++)
1749  mxFree (fields[i]);
1750 
1751  mxFree (fields);
1752 
1754 
1755  for (mwIndex i = 0; i < ntot; i++)
1756  delete data[i];
1757 
1758  mxFree (data);
1759  }
1760 
1761  int add_field (const char *key)
1762  {
1763  int retval = -1;
1764 
1765  if (valid_key (key))
1766  {
1767  nfields++;
1768 
1769  fields = static_cast<char **>
1770  (mxRealloc (fields, nfields * sizeof (char *)));
1771 
1772  if (fields)
1773  {
1774  fields[nfields-1] = mxArray::strsave (key);
1775 
1776  mwSize nel = get_number_of_elements ();
1777 
1778  mwSize ntot = nfields * nel;
1779 
1780  mxArray **new_data;
1781  new_data = static_cast<mxArray **>
1782  (mxArray::malloc (ntot * sizeof (mxArray *)));
1783 
1784  if (new_data)
1785  {
1786  mwIndex j = 0;
1787  mwIndex k = 0;
1788  mwIndex n = 0;
1789 
1790  for (mwIndex i = 0; i < ntot; i++)
1791  {
1792  if (++n == nfields)
1793  {
1794  new_data[j++] = nullptr;
1795  n = 0;
1796  }
1797  else
1798  new_data[j++] = data[k++];
1799  }
1800 
1801  mxFree (data);
1802 
1803  data = new_data;
1804 
1805  retval = nfields - 1;
1806  }
1807  }
1808  }
1809 
1810  return retval;
1811  }
1812 
1813  void remove_field (int key_num)
1814  {
1815  if (key_num >= 0 && key_num < nfields)
1816  {
1817  mwSize nel = get_number_of_elements ();
1818 
1819  mwSize ntot = nfields * nel;
1820 
1821  int new_nfields = nfields - 1;
1822 
1823  char **new_fields = static_cast<char **>
1824  (mxArray::malloc (new_nfields * sizeof (char *)));
1825 
1826  mxArray **new_data = static_cast<mxArray **>
1827  (mxArray::malloc (new_nfields * nel
1828  * sizeof (mxArray *)));
1829 
1830  for (int i = 0; i < key_num; i++)
1831  new_fields[i] = fields[i];
1832 
1833  for (int i = key_num + 1; i < nfields; i++)
1834  new_fields[i-1] = fields[i];
1835 
1836  if (new_nfields > 0)
1837  {
1838  mwIndex j = 0;
1839  mwIndex k = 0;
1840  mwIndex n = 0;
1841 
1842  for (mwIndex i = 0; i < ntot; i++)
1843  {
1844  if (n == key_num)
1845  k++;
1846  else
1847  new_data[j++] = data[k++];
1848 
1849  if (++n == nfields)
1850  n = 0;
1851  }
1852  }
1853 
1854  nfields = new_nfields;
1855 
1856  mxFree (fields);
1857  mxFree (data);
1858 
1859  fields = new_fields;
1860  data = new_data;
1861  }
1862  }
1863 
1864  mxArray * get_field_by_number (mwIndex index, int key_num) const
1865  {
1866  return key_num >= 0 && key_num < nfields
1867  ? data[nfields * index + key_num] : nullptr;
1868  }
1869 
1870  void set_field_by_number (mwIndex index, int key_num, mxArray *val);
1871 
1872  int get_number_of_fields (void) const { return nfields; }
1873 
1874  const char * get_field_name_by_number (int key_num) const
1875  {
1876  return key_num >= 0 && key_num < nfields ? fields[key_num] : nullptr;
1877  }
1878 
1879  int get_field_number (const char *key) const
1880  {
1881  int retval = -1;
1882 
1883  for (int i = 0; i < nfields; i++)
1884  {
1885  if (! strcmp (key, fields[i]))
1886  {
1887  retval = i;
1888  break;
1889  }
1890  }
1891 
1892  return retval;
1893  }
1894 
1895  void * get_data (void) const { return data; }
1896 
1897  void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
1898 
1900  {
1902 
1903  string_vector keys (fields, nfields);
1904 
1905  octave_map m (dv);
1906 
1908 
1909  for (int i = 0; i < nfields; i++)
1910  {
1911  Cell c (dv);
1912 
1913  octave_value *p = c.fortran_vec ();
1914 
1915  mwIndex k = 0;
1916  for (mwIndex j = i; j < ntot; j += nfields)
1917  p[k++] = mxArray::as_octave_value (data[j]);
1918 
1919  m.assign (keys[i], c);
1920  }
1921 
1922  return m;
1923  }
1924 
1925 private:
1926 
1927  int nfields;
1928 
1929  char **fields;
1930 
1932 };
1933 
1934 // Matlab-style cell arrays.
1935 
1937 {
1938 public:
1939 
1940  mxArray_cell (mwSize ndims_arg, const mwSize *dims_arg)
1941  : mxArray_matlab (mxCELL_CLASS, ndims_arg, dims_arg),
1942  data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (),
1943  sizeof (mxArray *)))) { }
1944 
1946  : mxArray_matlab (mxCELL_CLASS, dv),
1947  data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (),
1948  sizeof (mxArray *)))) { }
1949 
1952  data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (),
1953  sizeof (mxArray *)))) { }
1954 
1955 private:
1956 
1958  : mxArray_matlab (val),
1959  data (static_cast<mxArray **> (mxArray::malloc (get_number_of_elements ()
1960  * sizeof (mxArray *))))
1961  {
1962  mwSize nel = get_number_of_elements ();
1963 
1964  for (mwIndex i = 0; i < nel; i++)
1965  {
1966  mxArray *ptr = val.data[i];
1967  data[i] = (ptr ? ptr->dup () : nullptr);
1968  }
1969  }
1970 
1971 public:
1972 
1973  // No assignment! FIXME: should this be implemented? Note that we
1974  // do have a copy constructor.
1975 
1977 
1978  mxArray_base * dup (void) const { return new mxArray_cell (*this); }
1979 
1981  {
1982  mwSize nel = get_number_of_elements ();
1983 
1984  for (mwIndex i = 0; i < nel; i++)
1985  delete data[i];
1986 
1987  mxFree (data);
1988  }
1989 
1990  mxArray * get_cell (mwIndex idx) const
1991  {
1992  return idx >= 0 && idx < get_number_of_elements () ? data[idx] : nullptr;
1993  }
1994 
1995  void set_cell (mwIndex idx, mxArray *val);
1996 
1997  void * get_data (void) const { return data; }
1998 
1999  void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
2000 
2002  {
2004 
2005  Cell c (dv);
2006 
2007  mwSize nel = get_number_of_elements ();
2008 
2009  octave_value *p = c.fortran_vec ();
2010 
2011  for (mwIndex i = 0; i < nel; i++)
2012  p[i] = mxArray::as_octave_value (data[i]);
2013 
2014  return c;
2015  }
2016 
2017 private:
2018 
2020 };
2021 
2022 // ------------------------------------------------------------------
2023 
2025  : rep (new mxArray_octave_value (ov)), name (nullptr) { }
2026 
2027 mxArray::mxArray (mxClassID id, mwSize ndims, const mwSize *dims,
2028  mxComplexity flag, bool init)
2029  : rep (new mxArray_number (id, ndims, dims, flag, init)), name (nullptr) { }
2030 
2032  : rep (new mxArray_number (id, dv, flag)), name (nullptr) { }
2033 
2035  mxComplexity flag, bool init)
2036  : rep (new mxArray_number (id, m, n, flag, init)), name (nullptr) { }
2037 
2038 mxArray::mxArray (mxClassID id, double val)
2039  : rep (new mxArray_number (id, val)), name (nullptr) { }
2040 
2042  : rep (new mxArray_number (id, val)), name (nullptr) { }
2043 
2044 mxArray::mxArray (const char *str)
2045  : rep (new mxArray_number (str)), name (nullptr) { }
2046 
2047 mxArray::mxArray (mwSize m, const char **str)
2048  : rep (new mxArray_number (m, str)), name (nullptr) { }
2049 
2051  mxComplexity flag)
2052  : rep (new mxArray_sparse (id, m, n, nzmax, flag)), name (nullptr) { }
2053 
2054 mxArray::mxArray (mwSize ndims, const mwSize *dims, int num_keys,
2055  const char **keys)
2056  : rep (new mxArray_struct (ndims, dims, num_keys, keys)), name (nullptr) { }
2057 
2058 mxArray::mxArray (const dim_vector& dv, int num_keys, const char **keys)
2059  : rep (new mxArray_struct (dv, num_keys, keys)), name (nullptr) { }
2060 
2061 mxArray::mxArray (mwSize m, mwSize n, int num_keys, const char **keys)
2062  : rep (new mxArray_struct (m, n, num_keys, keys)), name (nullptr) { }
2063 
2064 mxArray::mxArray (mwSize ndims, const mwSize *dims)
2065  : rep (new mxArray_cell (ndims, dims)), name (nullptr) { }
2066 
2068  : rep (new mxArray_cell (dv)), name (nullptr) { }
2069 
2071  : rep (new mxArray_cell (m, n)), name (nullptr) { }
2072 
2074 {
2075  mxFree (name);
2076 
2077  delete rep;
2078 }
2079 
2080 void
2081 mxArray::set_name (const char *name_arg)
2082 {
2083  mxFree (name);
2084  name = mxArray::strsave (name_arg);
2085 }
2086 
2088 mxArray::as_octave_value (const mxArray *ptr, bool null_is_empty)
2089 {
2090  static const octave_value empty_matrix = Matrix ();
2091 
2092  return (ptr
2093  ? ptr->as_octave_value ()
2094  : (null_is_empty ? empty_matrix : octave_value ()));
2095 }
2096 
2099 {
2100  return rep->as_octave_value ();
2101 }
2102 
2103 void
2105 {
2106  if (rep->is_octave_value ())
2107  {
2108  // The mutate function returns a pointer to a complete new
2109  // mxArray object (or 0, if no mutation happened). We just want
2110  // to replace the existing rep with the rep from the new object.
2111 
2112  mxArray *new_val = rep->mutate ();
2113 
2114  if (new_val)
2115  {
2116  delete rep;
2117  rep = new_val->rep;
2118  new_val->rep = nullptr;
2119  delete new_val;
2120  }
2121  }
2122 }
2123 
2124 // ------------------------------------------------------------------
2125 
2126 // A class to manage calls to MEX functions. Mostly deals with memory
2127 // management.
2128 
2129 class mex
2130 {
2131 public:
2132 
2134  : curr_mex_fcn (f), memlist (), arraylist (), fname (nullptr) { }
2135 
2136  // No copying!
2137 
2138  mex (const mex&) = delete;
2139 
2140  mex& operator = (const mex&) = delete;
2141 
2142  ~mex (void)
2143  {
2144  // We can't use mex::free here because it modifies memlist.
2145  while (! memlist.empty ())
2146  {
2147  auto p = memlist.begin ();
2148  xfree (*p);
2149  memlist.erase (p);
2150  }
2151 
2152  // We can't use mex::free_value here because it modifies arraylist.
2153  while (! arraylist.empty ())
2154  {
2155  auto p = arraylist.begin ();
2156  delete *p;
2157  arraylist.erase (p);
2158  }
2159 
2160  if (! (memlist.empty () && arraylist.empty ()))
2161  error ("mex: %s: cleanup failed", function_name ());
2162 
2163  mxFree (fname);
2164  }
2165 
2166  const char * function_name (void) const
2167  {
2168  if (! fname)
2169  {
2171  = octave::__get_evaluator__ ("mex::function_name");
2172 
2173  octave_function *fcn = tw.current_function ();
2174 
2175  if (fcn)
2176  {
2177  std::string nm = fcn->name ();
2178  fname = mxArray::strsave (nm.c_str ());
2179  }
2180  else
2181  fname = mxArray::strsave ("unknown");
2182  }
2183 
2184  return fname;
2185  }
2186 
2187  // Allocate memory.
2188  void * malloc_unmarked (size_t n)
2189  {
2190  void *ptr = std::malloc (n);
2191 
2192  if (! ptr)
2193  {
2194  // FIXME: could use "octave_new_handler();" instead
2195  error ("%s: failed to allocate %zd bytes of memory",
2196  function_name (), n);
2197  }
2198 
2199  global_mark (ptr);
2200 
2201  return ptr;
2202  }
2203 
2204  // Allocate memory to be freed on exit.
2205  void * malloc (size_t n)
2206  {
2207  void *ptr = malloc_unmarked (n);
2208 
2209  mark (ptr);
2210 
2211  return ptr;
2212  }
2213 
2214  // Allocate memory and initialize to 0.
2215  void * calloc_unmarked (size_t n, size_t t)
2216  {
2217  void *ptr = malloc_unmarked (n*t);
2218 
2219  memset (ptr, 0, n*t);
2220 
2221  return ptr;
2222  }
2223 
2224  // Allocate memory to be freed on exit and initialize to 0.
2225  void * calloc (size_t n, size_t t)
2226  {
2227  void *ptr = calloc_unmarked (n, t);
2228 
2229  mark (ptr);
2230 
2231  return ptr;
2232  }
2233 
2234  // Reallocate a pointer obtained from malloc or calloc.
2235  // If the pointer is NULL, allocate using malloc.
2236  // We don't need an "unmarked" version of this.
2237  void * realloc (void *ptr, size_t n)
2238  {
2239  void *v;
2240 
2241  if (ptr)
2242  {
2243  auto p_local = memlist.find (ptr);
2244  auto p_global = global_memlist.find (ptr);
2245 
2246  v = std::realloc (ptr, n);
2247 
2248  if (v)
2249  {
2250  if (p_local != memlist.end ())
2251  {
2252  memlist.erase (p_local);
2253  memlist.insert (v);
2254  }
2255 
2256  if (p_global != global_memlist.end ())
2257  {
2258  global_memlist.erase (p_global);
2259  global_memlist.insert (v);
2260  }
2261  }
2262  }
2263  else
2264  v = malloc (n);
2265 
2266  return v;
2267  }
2268 
2269  // Free a pointer obtained from malloc or calloc.
2270  void free (void *ptr)
2271  {
2272  if (ptr)
2273  {
2274  unmark (ptr);
2275 
2276  auto p = global_memlist.find (ptr);
2277 
2278  if (p != global_memlist.end ())
2279  {
2280  global_memlist.erase (p);
2281 
2282  xfree (ptr);
2283  }
2284  else
2285  {
2286  p = foreign_memlist.find (ptr);
2287 
2288  if (p != foreign_memlist.end ())
2289  foreign_memlist.erase (p);
2290 #if defined (DEBUG)
2291  else
2292  warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc");
2293 #endif
2294  }
2295  }
2296  }
2297 
2298  // Mark a pointer to be freed on exit.
2299  void mark (void *ptr)
2300  {
2301 #if defined (DEBUG)
2302  if (memlist.find (ptr) != memlist.end ())
2303  warning ("%s: double registration ignored", function_name ());
2304 #endif
2305 
2306  memlist.insert (ptr);
2307  }
2308 
2309  // Unmark a pointer to be freed on exit, either because it was
2310  // made persistent, or because it was already freed.
2311  void unmark (void *ptr)
2312  {
2313  auto p = memlist.find (ptr);
2314 
2315  if (p != memlist.end ())
2316  memlist.erase (p);
2317 #if defined (DEBUG)
2318  else
2319  warning ("%s: value not marked", function_name ());
2320 #endif
2321  }
2322 
2324  {
2325  arraylist.insert (ptr);
2326  return ptr;
2327  }
2328 
2329  void unmark_array (mxArray *ptr)
2330  {
2331  auto p = arraylist.find (ptr);
2332 
2333  if (p != arraylist.end ())
2334  arraylist.erase (p);
2335  }
2336 
2337  // Mark a pointer as one we allocated.
2338  void mark_foreign (void *ptr)
2339  {
2340 #if defined (DEBUG)
2341  if (foreign_memlist.find (ptr) != foreign_memlist.end ())
2342  warning ("%s: double registration ignored", function_name ());
2343 #endif
2344 
2345  foreign_memlist.insert (ptr);
2346  }
2347 
2348  // Unmark a pointer as one we allocated.
2349  void unmark_foreign (void *ptr)
2350  {
2351  auto p = foreign_memlist.find (ptr);
2352 
2353  if (p != foreign_memlist.end ())
2354  foreign_memlist.erase (p);
2355 #if defined (DEBUG)
2356  else
2357  warning ("%s: value not marked", function_name ());
2358 #endif
2359 
2360  }
2361 
2362  // Make a new array value and initialize from an octave value; it will be
2363  // freed on exit unless marked as persistent.
2365  {
2366  return mark_array (new mxArray (ov));
2367  }
2368 
2369  // Free an array and its contents.
2370  bool free_value (mxArray *ptr)
2371  {
2372  bool inlist = false;
2373 
2374  auto p = arraylist.find (ptr);
2375 
2376  if (p != arraylist.end ())
2377  {
2378  inlist = true;
2379  arraylist.erase (p);
2380  delete ptr;
2381  }
2382 #if defined (DEBUG)
2383  else
2384  warning ("mex::free_value: skipping memory not allocated by mex::make_value");
2385 #endif
2386 
2387  return inlist;
2388  }
2389 
2391  {
2392  return curr_mex_fcn;
2393  }
2394 
2395  // 1 if error should be returned to MEX file, 0 if abort.
2397 
2398 private:
2399 
2400  // Pointer to the mex function that corresponds to this mex context.
2402 
2403  // List of memory resources that need to be freed upon exit.
2404  std::set<void *> memlist;
2405 
2406  // List of mxArray objects that need to be freed upon exit.
2407  std::set<mxArray *> arraylist;
2408 
2409  // List of memory resources we know about, but that were allocated
2410  // elsewhere.
2411  std::set<void *> foreign_memlist;
2412 
2413  // The name of the currently executing function.
2414  mutable char *fname;
2415 
2416  // List of memory resources we allocated.
2417  static std::set<void *> global_memlist;
2418 
2419  // Mark a pointer as one we allocated.
2420  void global_mark (void *ptr)
2421  {
2422 #if defined (DEBUG)
2423  if (global_memlist.find (ptr) != global_memlist.end ())
2424  warning ("%s: double registration ignored", function_name ());
2425 #endif
2426 
2427  global_memlist.insert (ptr);
2428  }
2429 
2430  // Unmark a pointer as one we allocated.
2431  void global_unmark (void *ptr)
2432  {
2433  auto p = global_memlist.find (ptr);
2434 
2435  if (p != global_memlist.end ())
2436  global_memlist.erase (p);
2437 #if defined (DEBUG)
2438  else
2439  warning ("%s: value not marked", function_name ());
2440 #endif
2441 
2442  }
2443 };
2444 
2445 // List of memory resources we allocated.
2446 std::set<void *> mex::global_memlist;
2447 
2448 // Current context.
2449 mex *mex_context = nullptr;
2450 
2451 void *
2453 {
2455 }
2456 
2457 void *
2458 mxArray::calloc (size_t n, size_t t)
2459 {
2460  return mex_context ? mex_context->calloc_unmarked (n, t) : ::calloc (n, t);
2461 }
2462 
2463 static inline void *
2465 {
2466  if (mex_context)
2467  mex_context->mark_foreign (ptr);
2468 
2469  return ptr;
2470 }
2471 
2472 static inline mxArray *
2474 {
2475  if (mex_context)
2476  mex_context->unmark_array (ptr);
2477 
2478  return ptr;
2479 }
2480 
2481 static inline void *
2482 maybe_unmark (void *ptr)
2483 {
2484  if (mex_context)
2485  mex_context->unmark (ptr);
2486 
2487  return ptr;
2488 }
2489 
2490 void
2492 {
2493  if (key_num >= 0 && key_num < nfields)
2494  data[nfields * index + key_num] = maybe_unmark_array (val);
2495 }
2496 
2497 void
2499 {
2500  if (idx >= 0 && idx < get_number_of_elements ())
2501  data[idx] = maybe_unmark_array (val);
2502 }
2503 
2504 // ------------------------------------------------------------------
2505 
2506 // C interface to mxArray objects:
2507 
2508 // Floating point predicates.
2509 
2510 bool
2511 mxIsFinite (const double v)
2512 {
2513  return lo_ieee_finite (v) != 0;
2514 }
2515 
2516 bool
2517 mxIsInf (const double v)
2518 {
2519  return lo_ieee_isinf (v) != 0;
2520 }
2521 
2522 bool
2523 mxIsNaN (const double v)
2524 {
2525  return lo_ieee_isnan (v) != 0;
2526 }
2527 
2528 double
2529 mxGetEps (void)
2530 {
2531  return std::numeric_limits<double>::epsilon ();
2532 }
2533 
2534 double
2535 mxGetInf (void)
2536 {
2537  return lo_ieee_inf_value ();
2538 }
2539 
2540 double
2541 mxGetNaN (void)
2542 {
2543  return lo_ieee_nan_value ();
2544 }
2545 
2546 // Memory management.
2547 void *
2548 mxCalloc (size_t n, size_t size)
2549 {
2550  return mex_context ? mex_context->calloc (n, size) : ::calloc (n, size);
2551 }
2552 
2553 void *
2554 mxMalloc (size_t n)
2555 {
2556  return mex_context ? mex_context->malloc (n) : std::malloc (n);
2557 }
2558 
2559 void *
2560 mxRealloc (void *ptr, size_t size)
2561 {
2562  return mex_context ? mex_context->realloc (ptr, size)
2563  : std::realloc (ptr, size);
2564 }
2565 
2566 void
2567 mxFree (void *ptr)
2568 {
2569  if (mex_context)
2570  mex_context->free (ptr);
2571  else
2572  xfree (ptr);
2573 }
2574 
2575 static inline mxArray *
2577 {
2578  return mex_context ? mex_context->mark_array (ptr) : ptr;
2579 }
2580 
2581 // Constructors.
2582 mxArray *
2583 mxCreateCellArray (mwSize ndims, const mwSize *dims)
2584 {
2585  return maybe_mark_array (new mxArray (ndims, dims));
2586 }
2587 
2588 mxArray *
2590 {
2591  return maybe_mark_array (new mxArray (m, n));
2592 }
2593 
2594 mxArray *
2595 mxCreateCharArray (mwSize ndims, const mwSize *dims)
2596 {
2597  return maybe_mark_array (new mxArray (mxCHAR_CLASS, ndims, dims));
2598 }
2599 
2600 mxArray *
2602 {
2603  return maybe_mark_array (new mxArray (m, str));
2604 }
2605 
2606 mxArray *
2608 {
2609  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, flag));
2610 }
2611 
2612 mxArray *
2614 {
2615  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, val));
2616 }
2617 
2618 mxArray *
2619 mxCreateLogicalArray (mwSize ndims, const mwSize *dims)
2620 {
2621  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, ndims, dims));
2622 }
2623 
2624 mxArray *
2626 {
2627  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n));
2628 }
2629 
2630 mxArray *
2632 {
2633  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, val));
2634 }
2635 
2636 mxArray *
2637 mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,
2638  mxComplexity flag)
2639 {
2640  return maybe_mark_array (new mxArray (class_id, ndims, dims, flag));
2641 }
2642 
2643 mxArray *
2645  mxComplexity flag)
2646 {
2647  return maybe_mark_array (new mxArray (class_id, m, n, flag));
2648 }
2649 
2650 mxArray *
2652  mxClassID class_id, mxComplexity flag)
2653 {
2654  return maybe_mark_array (new mxArray (class_id, ndims, dims, flag, false));
2655 }
2656 
2657 mxArray *
2659  mxComplexity flag)
2660 {
2661  return maybe_mark_array (new mxArray (class_id, m, n, flag, false));
2662 }
2663 
2664 mxArray *
2666 {
2667  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, nzmax, flag));
2668 }
2669 
2670 mxArray *
2672 {
2673  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n, nzmax));
2674 }
2675 
2676 mxArray *
2677 mxCreateString (const char *str)
2678 {
2679  return maybe_mark_array (new mxArray (str));
2680 }
2681 
2682 mxArray *
2683 mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys,
2684  const char **keys)
2685 {
2686  return maybe_mark_array (new mxArray (ndims, dims, num_keys, keys));
2687 }
2688 
2689 mxArray *
2690 mxCreateStructMatrix (mwSize m, mwSize n, int num_keys, const char **keys)
2691 {
2692  return maybe_mark_array (new mxArray (m, n, num_keys, keys));
2693 }
2694 
2695 // Copy constructor.
2696 mxArray *
2698 {
2699  return maybe_mark_array (ptr->dup ());
2700 }
2701 
2702 // Destructor.
2703 void
2705 {
2706  if (! (mex_context && mex_context->free_value (ptr)))
2707  delete ptr;
2708 }
2709 
2710 // Type Predicates.
2711 bool
2712 mxIsCell (const mxArray *ptr)
2713 {
2714  return ptr->iscell ();
2715 }
2716 
2717 bool
2718 mxIsChar (const mxArray *ptr)
2719 {
2720  return ptr->is_char ();
2721 }
2722 
2723 bool
2724 mxIsClass (const mxArray *ptr, const char *name)
2725 {
2726  return ptr->is_class (name);
2727 }
2728 
2729 bool
2730 mxIsComplex (const mxArray *ptr)
2731 {
2732  return ptr->is_complex ();
2733 }
2734 
2735 bool
2736 mxIsDouble (const mxArray *ptr)
2737 {
2738  return ptr->is_double ();
2739 }
2740 
2741 bool
2743 {
2744  return ptr->is_function_handle ();
2745 }
2746 
2747 bool
2748 mxIsInt16 (const mxArray *ptr)
2749 {
2750  return ptr->is_int16 ();
2751 }
2752 
2753 bool
2754 mxIsInt32 (const mxArray *ptr)
2755 {
2756  return ptr->is_int32 ();
2757 }
2758 
2759 bool
2760 mxIsInt64 (const mxArray *ptr)
2761 {
2762  return ptr->is_int64 ();
2763 }
2764 
2765 bool
2766 mxIsInt8 (const mxArray *ptr)
2767 {
2768  return ptr->is_int8 ();
2769 }
2770 
2771 bool
2772 mxIsLogical (const mxArray *ptr)
2773 {
2774  return ptr->is_logical ();
2775 }
2776 
2777 bool
2778 mxIsNumeric (const mxArray *ptr)
2779 {
2780  return ptr->is_numeric ();
2781 }
2782 
2783 bool
2784 mxIsSingle (const mxArray *ptr)
2785 {
2786  return ptr->is_single ();
2787 }
2788 
2789 bool
2790 mxIsSparse (const mxArray *ptr)
2791 {
2792  return ptr->is_sparse ();
2793 }
2794 
2795 bool
2796 mxIsStruct (const mxArray *ptr)
2797 {
2798  return ptr->is_struct ();
2799 }
2800 
2801 bool
2802 mxIsUint16 (const mxArray *ptr)
2803 {
2804  return ptr->is_uint16 ();
2805 }
2806 
2807 bool
2808 mxIsUint32 (const mxArray *ptr)
2809 {
2810  return ptr->is_uint32 ();
2811 }
2812 
2813 bool
2814 mxIsUint64 (const mxArray *ptr)
2815 {
2816  return ptr->is_uint64 ();
2817 }
2818 
2819 bool
2820 mxIsUint8 (const mxArray *ptr)
2821 {
2822  return ptr->is_uint8 ();
2823 }
2824 
2825 // Odd type+size predicate.
2826 bool
2828 {
2829  return ptr->is_logical_scalar ();
2830 }
2831 
2832 // Odd type+size+value predicate.
2833 bool
2835 {
2836  return ptr->is_logical_scalar_true ();
2837 }
2838 
2839 // Size predicate.
2840 bool
2841 mxIsEmpty (const mxArray *ptr)
2842 {
2843  return ptr->isempty ();
2844 }
2845 
2846 bool
2847 mxIsScalar (const mxArray *ptr)
2848 {
2849  return ptr->is_scalar ();
2850 }
2851 
2852 // FIXME: Just plain odd thing to ask of a value.
2853 // Still, Octave is incompatible because it does not implement this.
2854 bool
2855 mxIsFromGlobalWS (const mxArray * /*ptr*/)
2856 {
2857  mexErrMsgTxt ("mxIsFromGlobalWS() is unimplemented");
2858 
2859  return 0;
2860 }
2861 
2862 // Dimension extractors.
2863 size_t
2864 mxGetM (const mxArray *ptr)
2865 {
2866  return ptr->get_m ();
2867 }
2868 
2869 size_t
2870 mxGetN (const mxArray *ptr)
2871 {
2872  return ptr->get_n ();
2873 }
2874 
2875 const mwSize *
2877 {
2878  return ptr->get_dimensions ();
2879 }
2880 
2881 mwSize
2883 {
2884  return ptr->get_number_of_dimensions ();
2885 }
2886 
2887 size_t
2889 {
2890  return ptr->get_number_of_elements ();
2891 }
2892 
2893 // Dimension setters.
2894 void
2896 {
2897  ptr->set_m (m);
2898 }
2899 
2900 void
2902 {
2903  ptr->set_n (n);
2904 }
2905 
2906 int
2907 mxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims)
2908 {
2909  return (ptr->set_dimensions (static_cast<mwSize *>
2910  (maybe_unmark (const_cast<mwSize *> (dims))),
2911  ndims));
2912 }
2913 
2914 // Data extractors.
2915 double *
2916 mxGetPr (const mxArray *ptr)
2917 {
2918  return static_cast<double *> (ptr->get_data ());
2919 }
2920 
2921 double *
2922 mxGetPi (const mxArray *ptr)
2923 {
2924  return static_cast<double *> (ptr->get_imag_data ());
2925 }
2926 
2927 double
2928 mxGetScalar (const mxArray *ptr)
2929 {
2930  return ptr->get_scalar ();
2931 }
2932 
2933 mxChar *
2934 mxGetChars (const mxArray *ptr)
2935 {
2936  if (mxIsChar (ptr))
2937  return static_cast<mxChar *> (ptr->get_data ());
2938  else
2939  return nullptr;
2940 }
2941 
2942 mxLogical *
2944 {
2945  return static_cast<mxLogical *> (ptr->get_data ());
2946 }
2947 
2948 void *
2949 mxGetData (const mxArray *ptr)
2950 {
2951  return ptr->get_data ();
2952 }
2953 
2954 void *
2956 {
2957  return ptr->get_imag_data ();
2958 }
2959 
2960 // Data setters.
2961 void
2962 mxSetPr (mxArray *ptr, double *pr)
2963 {
2964  ptr->set_data (maybe_unmark (pr));
2965 }
2966 
2967 void
2968 mxSetPi (mxArray *ptr, double *pi)
2969 {
2970  ptr->set_imag_data (maybe_unmark (pi));
2971 }
2972 
2973 void
2974 mxSetData (mxArray *ptr, void *pr)
2975 {
2976  ptr->set_data (maybe_unmark (pr));
2977 }
2978 
2979 void
2980 mxSetImagData (mxArray *ptr, void *pi)
2981 {
2982  ptr->set_imag_data (maybe_unmark (pi));
2983 }
2984 
2985 // Classes.
2986 mxClassID
2987 mxGetClassID (const mxArray *ptr)
2988 {
2989  return ptr->get_class_id ();
2990 }
2991 
2992 const char *
2994 {
2995  return ptr->get_class_name ();
2996 }
2997 
2998 void
2999 mxSetClassName (mxArray *ptr, const char *name)
3000 {
3001  ptr->set_class_name (name);
3002 }
3003 
3004 void
3005 mxSetProperty (mxArray *ptr, mwIndex idx, const char *property_name,
3006  const mxArray *property_value)
3007 {
3008  ptr->set_property (idx, property_name, property_value);
3009 }
3010 
3011 mxArray *
3012 mxGetProperty (const mxArray *ptr, mwIndex idx, const char *property_name)
3013 {
3014  return ptr->get_property (idx, property_name);
3015 }
3016 
3017 // Cell support.
3018 mxArray *
3019 mxGetCell (const mxArray *ptr, mwIndex idx)
3020 {
3021  return ptr->get_cell (idx);
3022 }
3023 
3024 void
3026 {
3027  ptr->set_cell (idx, val);
3028 }
3029 
3030 // Sparse support.
3031 mwIndex *
3032 mxGetIr (const mxArray *ptr)
3033 {
3034  return ptr->get_ir ();
3035 }
3036 
3037 mwIndex *
3038 mxGetJc (const mxArray *ptr)
3039 {
3040  return ptr->get_jc ();
3041 }
3042 
3043 mwSize
3044 mxGetNzmax (const mxArray *ptr)
3045 {
3046  return ptr->get_nzmax ();
3047 }
3048 
3049 void
3051 {
3052  ptr->set_ir (static_cast<mwIndex *> (maybe_unmark (ir)));
3053 }
3054 
3055 void
3057 {
3058  ptr->set_jc (static_cast<mwIndex *> (maybe_unmark (jc)));
3059 }
3060 
3061 void
3063 {
3064  ptr->set_nzmax (nzmax);
3065 }
3066 
3067 // Structure support.
3068 int
3069 mxAddField (mxArray *ptr, const char *key)
3070 {
3071  return ptr->add_field (key);
3072 }
3073 
3074 void
3075 mxRemoveField (mxArray *ptr, int key_num)
3076 {
3077  ptr->remove_field (key_num);
3078 }
3079 
3080 mxArray *
3081 mxGetField (const mxArray *ptr, mwIndex index, const char *key)
3082 {
3083  int key_num = mxGetFieldNumber (ptr, key);
3084  return mxGetFieldByNumber (ptr, index, key_num);
3085 }
3086 
3087 mxArray *
3088 mxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num)
3089 {
3090  return ptr->get_field_by_number (index, key_num);
3091 }
3092 
3093 void
3094 mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val)
3095 {
3096  int key_num = mxGetFieldNumber (ptr, key);
3097  mxSetFieldByNumber (ptr, index, key_num, val);
3098 }
3099 
3100 void
3101 mxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val)
3102 {
3103  ptr->set_field_by_number (index, key_num, val);
3104 }
3105 
3106 int
3108 {
3109  return ptr->get_number_of_fields ();
3110 }
3111 
3112 const char *
3113 mxGetFieldNameByNumber (const mxArray *ptr, int key_num)
3114 {
3115  return ptr->get_field_name_by_number (key_num);
3116 }
3117 
3118 int
3119 mxGetFieldNumber (const mxArray *ptr, const char *key)
3120 {
3121  return ptr->get_field_number (key);
3122 }
3123 
3124 int
3125 mxGetString (const mxArray *ptr, char *buf, mwSize buflen)
3126 {
3127  return ptr->get_string (buf, buflen);
3128 }
3129 
3130 char *
3132 {
3133  return ptr->array_to_string ();
3134 }
3135 
3136 mwIndex
3137 mxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs)
3138 {
3139  return ptr->calc_single_subscript (nsubs, subs);
3140 }
3141 
3142 size_t
3144 {
3145  return ptr->get_element_size ();
3146 }
3147 
3148 // ------------------------------------------------------------------
3149 
3150 typedef void (*cmex_fptr) (int nlhs, mxArray **plhs, int nrhs, mxArray **prhs);
3151 typedef F77_RET_T (*fmex_fptr) (F77_INT& nlhs, mxArray **plhs,
3152  F77_INT& nrhs, mxArray **prhs);
3153 
3156  int nargout_arg)
3157 {
3158  octave_quit ();
3159 
3160  // Use at least 1 for nargout since even for zero specified args,
3161  // still want to be able to return an ans.
3162 
3163  volatile int nargout = nargout_arg;
3164 
3165  int nargin = args.length ();
3166  OCTAVE_LOCAL_BUFFER (mxArray *, argin, nargin);
3167  for (int i = 0; i < nargin; i++)
3168  argin[i] = nullptr;
3169 
3170  int nout = (nargout == 0 ? 1 : nargout);
3171  OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout);
3172  for (int i = 0; i < nout; i++)
3173  argout[i] = nullptr;
3174 
3176 
3177  // Save old mex pointer.
3178  frame.protect_var (mex_context);
3179 
3180  mex context (&mex_fcn);
3181 
3182  for (int i = 0; i < nargin; i++)
3183  argin[i] = context.make_value (args(i));
3184 
3185  mex_context = &context;
3186 
3187  void *mex_fcn_ptr = mex_fcn.mex_fcn_ptr ();
3188 
3189  if (mex_fcn.is_fmex ())
3190  {
3191  fmex_fptr fcn = reinterpret_cast<fmex_fptr> (mex_fcn_ptr);
3192 
3193  F77_INT tmp_nargout = nargout;
3194  F77_INT tmp_nargin = nargin;
3195 
3196  fcn (tmp_nargout, argout, tmp_nargin, argin);
3197  }
3198  else
3199  {
3200  cmex_fptr fcn = reinterpret_cast<cmex_fptr> (mex_fcn_ptr);
3201 
3202  fcn (nargout, argout, nargin, argin);
3203  }
3204 
3205  // Convert returned array entries back into octave values.
3206 
3208 
3209  if (nargout == 0 && argout[0])
3210  {
3211  // We have something for ans.
3212  nargout = 1;
3213  }
3214 
3215  retval.resize (nargout);
3216 
3217  for (int i = 0; i < nargout; i++)
3218  retval(i) = mxArray::as_octave_value (argout[i], false);
3219 
3220  return retval;
3221 }
3222 
3223 // C interface to mex functions:
3224 
3225 const char *
3227 {
3228  return mex_context ? mex_context->function_name () : "unknown";
3229 }
3230 
3231 int
3232 mexCallMATLAB (int nargout, mxArray *argout[], int nargin,
3233  mxArray *argin[], const char *fname)
3234 {
3235  octave_value_list args;
3236 
3237  // FIXME: do we need unwind protect to clean up args? Off hand, I
3238  // would say that this problem is endemic to Octave and we will
3239  // continue to have memory leaks after Ctrl-C until proper exception
3240  // handling is implemented.
3241 
3242  // FIXME: Proper exception handling has been implemented (Jan. 2016).
3243  // Can this code be re-factored?
3244  args.resize (nargin);
3245 
3246  for (int i = 0; i < nargin; i++)
3247  args(i) = mxArray::as_octave_value (argin[i]);
3248 
3249  octave::interpreter& interp = octave::__get_interpreter__ ("mexCallMATLAB");
3250 
3251  bool execution_error = false;
3252 
3254 
3255  try
3256  {
3257  octave::tree_evaluator& tw = interp.get_evaluator ();
3258 
3260  ([&tw] (const std::list<octave::octave_lvalue> *lvl)
3261  {
3262  tw.set_lvalue_list (lvl);
3263  }, tw.lvalue_list ());
3264 
3265  tw.set_lvalue_list (nullptr);
3266 
3267  retval = octave::feval (fname, args, nargout);
3268  }
3269  catch (const octave::execution_exception&)
3270  {
3272  {
3273  // FIXME: is there a way to indicate what error occurred?
3274  // Should the error message be displayed here? Do we need to
3275  // save the exception info for lasterror?
3276 
3277  interp.recover_from_exception ();
3278 
3279  execution_error = true;
3280  }
3281  else
3282  {
3283  args.resize (0);
3284  retval.resize (0);
3285 
3286  throw;
3287  }
3288  }
3289 
3290  int num_to_copy = retval.length ();
3291 
3292  if (nargout < retval.length ())
3293  num_to_copy = nargout;
3294 
3295  for (int i = 0; i < num_to_copy; i++)
3296  {
3297  // FIXME: it would be nice to avoid copying the value here,
3298  // but there is no way to steal memory from a matrix, never mind
3299  // that matrix memory is allocated by new[] and mxArray memory
3300  // is allocated by malloc().
3301  argout[i] = mex_context->make_value (retval(i));
3302  }
3303 
3304  while (num_to_copy < nargout)
3305  argout[num_to_copy++] = nullptr;
3306 
3307  return execution_error ? 1 : 0;
3308 }
3309 
3310 mxArray *
3311 mexCallMATLABWithTrap (int nargout, mxArray *argout[], int nargin,
3312  mxArray *argin[], const char *fname)
3313 {
3314  mxArray *mx = nullptr;
3315 
3316  int old_flag = (mex_context ? mex_context->trap_feval_error : 0);
3317  mexSetTrapFlag (1);
3318  if (mexCallMATLAB (nargout, argout, nargin, argin, fname))
3319  {
3320  const char *field_names[] = {"identifier", "message", "case", "stack"};
3321  mx = mxCreateStructMatrix (1, 1, 4, field_names);
3322  mxSetFieldByNumber (mx, 0, 0, mxCreateString ("Octave:MEX"));
3323  std::string msg = "mexCallMATLABWithTrap: function call <"
3324  + std::string (fname) + "> failed";
3325  mxSetFieldByNumber (mx, 0, 1, mxCreateString (msg.c_str ()));
3326  mxSetFieldByNumber (mx, 0, 2, mxCreateCellMatrix (0, 0));
3327  mxSetFieldByNumber (mx, 0, 3, mxCreateStructMatrix (0, 1, 0, nullptr));
3328  }
3329  mexSetTrapFlag (old_flag);
3330 
3331  return mx;
3332 }
3333 
3334 void
3335 mexSetTrapFlag (int flag)
3336 {
3337  if (mex_context)
3338  mex_context->trap_feval_error = flag;
3339 }
3340 
3341 int
3342 mexEvalString (const char *s)
3343 {
3344  int retval = 0;
3345 
3346  octave::interpreter& interp = octave::__get_interpreter__ ("mexEvalString");
3347 
3348  int parse_status;
3349  bool execution_error = false;
3350 
3351  octave_value_list ret;
3352 
3353  try
3354  {
3355  ret = interp.eval_string (std::string (s), false, parse_status, 0);
3356  }
3357  catch (const octave::execution_exception&)
3358  {
3359  interp.recover_from_exception ();
3360 
3361  execution_error = true;
3362  }
3363 
3364  if (parse_status || execution_error)
3365  retval = 1;
3366 
3367  return retval;
3368 }
3369 
3370 mxArray *
3371 mexEvalStringWithTrap (const char *s)
3372 {
3373  mxArray *mx = nullptr;
3374 
3375  octave::interpreter& interp = octave::__get_interpreter__ ("mexEvalString");
3376 
3377  int parse_status;
3378  bool execution_error = false;
3379 
3380  octave_value_list ret;
3381 
3382  try
3383  {
3384  ret = interp.eval_string (std::string (s), false, parse_status, 0);
3385  }
3386  catch (const octave::execution_exception&)
3387  {
3388  interp.recover_from_exception ();
3389 
3390  execution_error = true;
3391  }
3392 
3393  if (parse_status || execution_error)
3394  {
3395  const char *field_names[] = {"identifier", "message", "case", "stack"};
3396  mx = mxCreateStructMatrix (1, 1, 4, field_names);
3397  mxSetFieldByNumber (mx, 0, 0, mxCreateString ("Octave:MEX"));
3398  std::string msg = "mexEvalStringWithTrap: eval of <"
3399  + std::string (s) + "> failed";
3400  mxSetFieldByNumber (mx, 0, 1, mxCreateString (msg.c_str ()));
3401  mxSetFieldByNumber (mx, 0, 2, mxCreateCellMatrix (0, 0));
3402  mxSetFieldByNumber (mx, 0, 3, mxCreateStructMatrix (0, 1, 0, nullptr));
3403  }
3404 
3405  return mx;
3406 }
3407 
3408 void
3409 mexErrMsgTxt (const char *s)
3410 {
3411  size_t len;
3412 
3413  if (s && (len = strlen (s)) > 0)
3414  {
3415  if (s[len - 1] == '\n')
3416  {
3417  std::string s_tmp (s, len - 1);
3418  error ("%s: %s\n", mexFunctionName (), s_tmp.c_str ());
3419  }
3420  else
3421  error ("%s: %s", mexFunctionName (), s);
3422  }
3423  else
3424  {
3425  // For compatibility with Matlab, print an empty message.
3426  // Octave's error routine requires a non-null input so use a SPACE.
3427  error (" ");
3428  }
3429 }
3430 
3431 void
3432 mexErrMsgIdAndTxt (const char *id, const char *fmt, ...)
3433 {
3434  if (fmt && strlen (fmt) > 0)
3435  {
3436  const char *fname = mexFunctionName ();
3437  size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
3438  OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
3439  sprintf (tmpfmt, "%s: %s", fname, fmt);
3440  va_list args;
3441  va_start (args, fmt);
3442  verror_with_id (id, tmpfmt, args);
3443  va_end (args);
3444  }
3445  else
3446  {
3447  // For compatibility with Matlab, print an empty message.
3448  // Octave's error routine requires a non-null input so use a SPACE.
3449  error (" ");
3450  }
3451 }
3452 
3453 void
3454 mexWarnMsgTxt (const char *s)
3455 {
3456  size_t len;
3457 
3458  if (s && (len = strlen (s)) > 0)
3459  {
3460  if (s[len - 1] == '\n')
3461  {
3462  std::string s_tmp (s, len - 1);
3463  warning ("%s\n", s_tmp.c_str ());
3464  }
3465  else
3466  warning ("%s", s);
3467  }
3468  else
3469  {
3470  // For compatibility with Matlab, print an empty message.
3471  // Octave's warning routine requires a non-null input so use a SPACE.
3472  warning (" ");
3473  }
3474 }
3475 
3476 void
3477 mexWarnMsgIdAndTxt (const char *id, const char *fmt, ...)
3478 {
3479  // FIXME: is this right? What does Matlab do if fmt is NULL or
3480  // an empty string?
3481 
3482  if (fmt && strlen (fmt) > 0)
3483  {
3484  const char *fname = mexFunctionName ();
3485  size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
3486  OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
3487  sprintf (tmpfmt, "%s: %s", fname, fmt);
3488  va_list args;
3489  va_start (args, fmt);
3490  vwarning_with_id (id, tmpfmt, args);
3491  va_end (args);
3492  }
3493 }
3494 
3495 int
3496 mexPrintf (const char *fmt, ...)
3497 {
3498  int retval;
3499  va_list args;
3500  va_start (args, fmt);
3501  retval = octave::vformat (octave_stdout, fmt, args);
3502  va_end (args);
3503  return retval;
3504 }
3505 
3506 mxArray *
3507 mexGetVariable (const char *space, const char *name)
3508 {
3509  mxArray *retval = nullptr;
3510 
3511  octave_value val;
3512 
3513  octave::interpreter& interp = octave::__get_interpreter__ ("mexGetVariable");
3514 
3515  if (! strcmp (space, "global"))
3516  val = interp.global_varval (name);
3517  else
3518  {
3519  // FIXME: should this be in variables.cc?
3520 
3521  octave::unwind_protect frame;
3522 
3523  bool caller = ! strcmp (space, "caller");
3524  bool base = ! strcmp (space, "base");
3525 
3526  if (caller || base)
3527  {
3528  // MEX files don't create a separate frame in the call stack,
3529  // so we are already in the "caller" frame.
3530 
3531  if (base)
3532  {
3533  octave::tree_evaluator& tw = interp.get_evaluator ();
3534 
3537 
3538  tw.goto_base_frame ();
3539  }
3540 
3541  val = interp.varval (name);
3542  }
3543  else
3544  mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
3545  }
3546 
3547  if (val.is_defined ())
3548  {
3549  retval = mex_context->make_value (val);
3550 
3551  retval->set_name (name);
3552  }
3553 
3554  return retval;
3555 }
3556 
3557 const mxArray *
3558 mexGetVariablePtr (const char *space, const char *name)
3559 {
3560  return mexGetVariable (space, name);
3561 }
3562 
3563 int
3564 mexPutVariable (const char *space, const char *name, const mxArray *ptr)
3565 {
3566  if (! ptr)
3567  return 1;
3568 
3569  if (! name)
3570  return 1;
3571 
3572  if (name[0] == '\0')
3573  name = ptr->get_name ();
3574 
3575  if (! name || name[0] == '\0')
3576  return 1;
3577 
3578  octave::interpreter& interp = octave::__get_interpreter__ ("mexPutVariable");
3579 
3580  if (! strcmp (space, "global"))
3582  else
3583  {
3584  // FIXME: should this be in variables.cc?
3585 
3586  octave::unwind_protect frame;
3587 
3588  bool caller = ! strcmp (space, "caller");
3589  bool base = ! strcmp (space, "base");
3590 
3591  if (caller || base)
3592  {
3593  // MEX files don't create a separate frame in the call stack,
3594  // so we are already in the "caller" frame.
3595 
3596  if (base)
3597  {
3598  octave::tree_evaluator& tw = interp.get_evaluator ();
3599 
3602 
3603  tw.goto_base_frame ();
3604  }
3605 
3606  interp.assign (name, mxArray::as_octave_value (ptr));
3607  }
3608  else
3609  mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
3610  }
3611 
3612  return 0;
3613 }
3614 
3615 void
3617 {
3618  maybe_unmark_array (ptr);
3619 }
3620 
3621 void
3623 {
3624  maybe_unmark (ptr);
3625 }
3626 
3627 int
3628 mexAtExit (void (*f) (void))
3629 {
3630  if (mex_context)
3631  {
3633 
3634  assert (curr_mex_fcn);
3635 
3636  curr_mex_fcn->atexit (f);
3637  }
3638 
3639  return 0;
3640 }
3641 
3642 const mxArray *
3643 mexGet (double handle, const char *property)
3644 {
3645  mxArray *m = nullptr;
3646 
3647  octave_value ret = get_property_from_handle (handle, property, "mexGet");
3648 
3649  if (ret.is_defined ())
3650  m = ret.as_mxArray ();
3651 
3652  return m;
3653 }
3654 
3655 int
3656 mexIsGlobal (const mxArray *ptr)
3657 {
3658  return mxIsFromGlobalWS (ptr);
3659 }
3660 
3661 int
3663 {
3664  int retval = 0;
3665 
3666  if (mex_context)
3667  {
3668  const char *fname = mexFunctionName ();
3669 
3670  octave::interpreter& interp = octave::__get_interpreter__ ("mexIsLocked");
3671 
3672  retval = interp.mislocked (fname);
3673  }
3674 
3675  return retval;
3676 }
3677 
3678 std::map<std::string,int> mex_lock_count;
3679 
3680 void
3681 mexLock (void)
3682 {
3683  if (mex_context)
3684  {
3685  const char *fname = mexFunctionName ();
3686 
3687  if (mex_lock_count.find (fname) == mex_lock_count.end ())
3688  mex_lock_count[fname] = 1;
3689  else
3690  mex_lock_count[fname]++;
3691 
3692  octave::interpreter& interp = octave::__get_interpreter__ ("mexLock");
3693 
3694  interp.mlock ();
3695  }
3696 }
3697 
3698 int
3699 mexSet (double handle, const char *property, mxArray *val)
3700 {
3701  bool ret
3703  "mexSet");
3704  return (ret ? 0 : 1);
3705 }
3706 
3707 void
3709 {
3710  if (mex_context)
3711  {
3712  const char *fname = mexFunctionName ();
3713 
3714  auto p = mex_lock_count.find (fname);
3715 
3716  if (p != mex_lock_count.end ())
3717  {
3718  int count = --mex_lock_count[fname];
3719 
3720  if (count == 0)
3721  {
3722  octave::interpreter& interp
3723  = octave::__get_interpreter__ ("mexUnLock");
3724 
3725  interp.munlock (fname);
3726 
3727  mex_lock_count.erase (p);
3728  }
3729  }
3730  }
3731 }
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1011
const T * data(void) const
Size of the specified dimension.
Definition: Array.h:581
const T * fortran_vec(void) const
Size of the specified dimension.
Definition: Array.h:583
Definition: Cell.h:43
Definition: dMatrix.h:42
octave_idx_type * xridx(void)
Definition: Sparse.h:485
octave_idx_type * xcidx(void)
Definition: Sparse.h:498
T * xdata(void)
Definition: Sparse.h:472
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
void resize(int n, int fill_value=0)
Definition: dim-vector.h:349
Definition: mex.cc:2130
mxArray * make_value(const octave_value &ov)
Definition: mex.cc:2364
void * calloc(size_t n, size_t t)
Definition: mex.cc:2225
mex & operator=(const mex &)=delete
std::set< void * > memlist
Definition: mex.cc:2404
const char * function_name(void) const
Definition: mex.cc:2166
std::set< mxArray * > arraylist
Definition: mex.cc:2407
void unmark_array(mxArray *ptr)
Definition: mex.cc:2329
void free(void *ptr)
Definition: mex.cc:2270
std::set< void * > foreign_memlist
Definition: mex.cc:2411
void * calloc_unmarked(size_t n, size_t t)
Definition: mex.cc:2215
~mex(void)
Definition: mex.cc:2142
void mark(void *ptr)
Definition: mex.cc:2299
octave_mex_function * current_mex_function(void) const
Definition: mex.cc:2390
void * malloc_unmarked(size_t n)
Definition: mex.cc:2188
void unmark(void *ptr)
Definition: mex.cc:2311
mex(const mex &)=delete
char * fname
Definition: mex.cc:2414
void global_unmark(void *ptr)
Definition: mex.cc:2431
mex(octave_mex_function *f)
Definition: mex.cc:2133
bool free_value(mxArray *ptr)
Definition: mex.cc:2370
octave_mex_function * curr_mex_fcn
Definition: mex.cc:2401
void * realloc(void *ptr, size_t n)
Definition: mex.cc:2237
void * malloc(size_t n)
Definition: mex.cc:2205
void global_mark(void *ptr)
Definition: mex.cc:2420
void mark_foreign(void *ptr)
Definition: mex.cc:2338
mxArray * mark_array(mxArray *ptr)
Definition: mex.cc:2323
static std::set< void * > global_memlist
Definition: mex.cc:2417
int trap_feval_error
Definition: mex.cc:2396
void unmark_foreign(void *ptr)
Definition: mex.cc:2349
virtual mxArray * mutate(void) const
Definition: mxarray.in.h:302
virtual int is_logical_scalar(void) const
Definition: mxarray.in.h:198
virtual bool is_octave_value(void) const
Definition: mxarray.in.h:148
OCTAVE_NORETURN void err_invalid_type(void) const
Definition: mxarray.in.h:310
virtual octave_value as_octave_value(void) const =0
mxArray_cell & operator=(const mxArray_cell &)
~mxArray_cell(void)
Definition: mex.cc:1980
mxArray_cell(const mxArray_cell &val)
Definition: mex.cc:1957
void * get_data(void) const
Definition: mex.cc:1997
void set_cell(mwIndex idx, mxArray *val)
Definition: mex.cc:2498
mxArray_base * dup(void) const
Definition: mex.cc:1978
mxArray ** data
Definition: mex.cc:2019
mxArray_cell(mwSize ndims_arg, const mwSize *dims_arg)
Definition: mex.cc:1940
octave_value as_octave_value(void) const
Definition: mex.cc:2001
mxArray_cell(mwSize m, mwSize n)
Definition: mex.cc:1950
mxArray_cell(const dim_vector &dv)
Definition: mex.cc:1945
void set_data(void *data_arg)
Definition: mex.cc:1999
mxArray * get_cell(mwIndex idx) const
Definition: mex.cc:1990
void set_cell(mwIndex, mxArray *)
Definition: mex.cc:906
mxArray * get_field_by_number(mwIndex, int) const
Definition: mex.cc:976
void set_field_by_number(mwIndex, int, mxArray *)
Definition: mex.cc:981
void set_class_name(const char *name_arg)
Definition: mex.cc:894
mxArray_matlab & operator=(const mxArray_matlab &)
int add_field(const char *)
Definition: mex.cc:966
size_t get_element_size(void) const
Definition: mex.cc:1017
mxClassID get_class_id(void) const
Definition: mex.cc:867
int is_char(void) const
Definition: mex.cc:757
mxArray_matlab(mxClassID id_arg, const dim_vector &dv)
Definition: mex.cc:707
mxClassID id
Definition: mex.cc:1064
int is_int64(void) const
Definition: mex.cc:769
bool is_scalar(void) const
Definition: mex.cc:862
void set_nzmax(mwSize)
Definition: mex.cc:961
void set_m(mwSize m)
Definition: mex.cc:820
mwSize get_n(void) const
Definition: mex.cc:806
char * class_name
Definition: mex.cc:1062
void * get_imag_data(void) const
Definition: mex.cc:921
int iscell(void) const
Definition: mex.cc:755
mwIndex * get_ir(void) const
Definition: mex.cc:936
int get_number_of_fields(void) const
Definition: mex.cc:987
mwIndex calc_single_subscript(mwSize nsubs, mwIndex *subs) const
Definition: mex.cc:1012
~mxArray_matlab(void)
Definition: mex.cc:749
mwIndex * get_jc(void) const
Definition: mex.cc:941
int isempty(void) const
Definition: mex.cc:860
int is_numeric(void) const
Definition: mex.cc:775
mxArray_matlab(const mxArray_matlab &val)
Definition: mex.cc:732
void * get_data(void) const
Definition: mex.cc:916
int is_complex(void) const
Definition: mex.cc:759
char * array_to_string(void) const
Definition: mex.cc:1007
int is_logical_scalar_true(void) const
Definition: mex.cc:798
mxArray_matlab(mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg)
Definition: mex.cc:679
mwSize get_m(void) const
Definition: mex.cc:804
const char * get_field_name_by_number(int) const
Definition: mex.cc:992
int is_double(void) const
Definition: mex.cc:761
int is_logical(void) const
Definition: mex.cc:773
OCTAVE_NORETURN void err_invalid_type(void) const
Definition: mex.cc:1069
int is_struct(void) const
Definition: mex.cc:788
mwSize * get_dimensions(void) const
Definition: mex.cc:816
void set_n(mwSize n)
Definition: mex.cc:822
int get_field_number(const char *) const
Definition: mex.cc:997
int set_dimensions(mwSize *dims_arg, mwSize ndims_arg)
Definition: mex.cc:824
mxArray_matlab(mxClassID id_arg=mxUNKNOWN_CLASS)
Definition: mex.cc:674
int is_function_handle(void) const
Definition: mex.cc:763
void set_jc(mwIndex *)
Definition: mex.cc:956
int is_uint32(void) const
Definition: mex.cc:792
int is_single(void) const
Definition: mex.cc:784
mxArray_matlab(mxClassID id_arg, mwSize m, mwSize n)
Definition: mex.cc:724
mwSize * dims
Definition: mex.cc:1067
int is_int8(void) const
Definition: mex.cc:771
mxArray * get_cell(mwIndex) const
Definition: mex.cc:901
mwSize get_number_of_dimensions(void) const
Definition: mex.cc:818
mwSize get_nzmax(void) const
Definition: mex.cc:946
int is_int16(void) const
Definition: mex.cc:765
double get_scalar(void) const
Definition: mex.cc:911
int is_uint8(void) const
Definition: mex.cc:796
int is_sparse(void) const
Definition: mex.cc:786
int is_uint64(void) const
Definition: mex.cc:794
void set_ir(mwIndex *)
Definition: mex.cc:951
const char * get_class_name(void) const
Definition: mex.cc:869
void set_imag_data(void *)
Definition: mex.cc:931
int get_string(char *, mwSize) const
Definition: mex.cc:1002
mwSize ndims
Definition: mex.cc:1066
void remove_field(int)
Definition: mex.cc:971
int is_uint16(void) const
Definition: mex.cc:790
dim_vector dims_to_dim_vector(void) const
Definition: mex.cc:1045
mwSize get_number_of_elements(void) const
Definition: mex.cc:850
int is_int32(void) const
Definition: mex.cc:767
void set_data(void *)
Definition: mex.cc:926
int get_string(char *buf, mwSize buflen) const
Definition: mex.cc:1280
mxArray_number(mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg, mxComplexity flag=mxREAL, bool init=true)
Definition: mex.cc:1081
void * get_data(void) const
Definition: mex.cc:1272
int is_complex(void) const
Definition: mex.cc:1209
~mxArray_number(void)
Definition: mex.cc:1203
mxArray_number(mxClassID id_arg, double val)
Definition: mex.cc:1119
mxArray_base * dup(void) const
Definition: mex.cc:1201
void set_data(void *pr_arg)
Definition: mex.cc:1276
mxArray_number(mwSize m, const char **str)
Definition: mex.cc:1151
mxArray_number & operator=(const mxArray_number &)
void * pi
Definition: mex.cc:1487
void * pr
Definition: mex.cc:1486
mxArray_number(mxClassID id_arg, mwSize m, mwSize n, mxComplexity flag=mxREAL, bool init=true)
Definition: mex.cc:1104
mxArray_number(const char *str)
Definition: mex.cc:1137
mxArray_number(mxClassID id_arg, mxLogical val)
Definition: mex.cc:1128
octave_value int_to_ov(const dim_vector &dv) const
Definition: mex.cc:1465
char * array_to_string(void) const
Definition: mex.cc:1306
mxArray_number(const mxArray_number &val)
Definition: mex.cc:1178
octave_value as_octave_value(void) const
Definition: mex.cc:1327
double get_scalar(void) const
Definition: mex.cc:1211
void * get_imag_data(void) const
Definition: mex.cc:1274
void set_imag_data(void *pi_arg)
Definition: mex.cc:1278
mxArray_number(mxClassID id_arg, const dim_vector &dv, mxComplexity flag=mxREAL)
Definition: mex.cc:1095
int is_sparse(void) const
Definition: mex.cc:244
bool mutation_needed(void) const
Definition: mex.cc:620
int set_dimensions(mwSize *, mwSize)
Definition: mex.cc:310
mxClassID get_class_id(void) const
Definition: mex.cc:329
int is_uint16(void) const
Definition: mex.cc:248
const char * get_class_name(void) const
Definition: mex.cc:369
int add_field(const char *)
Definition: mex.cc:497
void * get_data(void) const
Definition: mex.cc:445
void set_nzmax(mwSize)
Definition: mex.cc:494
octave_value as_octave_value(void) const
Definition: mex.cc:632
int isreal(void) const
Definition: mex.cc:258
mwSize get_number_of_elements(void) const
Definition: mex.cc:317
void set_cell(mwIndex, mxArray *)
Definition: mex.cc:423
size_t get_element_size(void) const
Definition: mex.cc:592
void set_ir(mwIndex *)
Definition: mex.cc:488
void set_data(void *)
Definition: mex.cc:470
int is_logical(void) const
Definition: mex.cc:238
int is_uint8(void) const
Definition: mex.cc:254
~mxArray_octave_value(void)
Definition: mex.cc:212
void set_jc(mwIndex *)
Definition: mex.cc:491
mxArray_octave_value(const mxArray_octave_value &arg)
Definition: mex.cc:636
const char * get_field_name_by_number(int) const
Definition: mex.cc:521
int is_uint64(void) const
Definition: mex.cc:252
mxArray_octave_value(const octave_value &ov)
Definition: mex.cc:164
int is_int8(void) const
Definition: mex.cc:236
mxArray_octave_value & operator=(const mxArray_octave_value &)=delete
void set_m(mwSize)
Definition: mex.cc:306
mwSize * dims
Definition: mex.cc:664
int is_int64(void) const
Definition: mex.cc:234
void set_class_name(const char *)
Definition: mex.cc:381
int iscell(void) const
Definition: mex.cc:220
int is_numeric(void) const
Definition: mex.cc:240
mwSize get_m(void) const
Definition: mex.cc:265
mwSize * get_dimensions(void) const
Definition: mex.cc:280
mxClassID id
Definition: mex.cc:661
int is_int16(void) const
Definition: mex.cc:230
int is_char(void) const
Definition: mex.cc:222
mxArray * get_cell(mwIndex) const
Definition: mex.cc:416
void set_imag_data(void *)
Definition: mex.cc:473
int get_field_number(const char *) const
Definition: mex.cc:527
void set_property(mwIndex idx, const char *pname, const mxArray *pval)
Definition: mex.cc:403
bool is_scalar(void) const
Definition: mex.cc:321
void remove_field(int)
Definition: mex.cc:504
int get_number_of_fields(void) const
Definition: mex.cc:519
char * array_to_string(void) const
Definition: mex.cc:556
mwIndex calc_single_subscript(mwSize nsubs, mwIndex *subs) const
Definition: mex.cc:584
int is_int32(void) const
Definition: mex.cc:232
bool is_octave_value(void) const
Definition: mex.cc:218
void * get_imag_data(void) const
Definition: mex.cc:457
void set_n(mwSize)
Definition: mex.cc:308
mxArray_base * dup(void) const
Definition: mex.cc:173
int isempty(void) const
Definition: mex.cc:319
mwIndex * get_jc(void) const
Definition: mex.cc:480
mwIndex * get_ir(void) const
Definition: mex.cc:475
mwSize get_n(void) const
Definition: mex.cc:267
int is_range(void) const
Definition: mex.cc:256
int is_complex(void) const
Definition: mex.cc:224
mwSize get_nzmax(void) const
Definition: mex.cc:485
mxArray * get_property(mwIndex idx, const char *pname) const
Definition: mex.cc:383
int is_double(void) const
Definition: mex.cc:226
void request_mutation(void) const
Definition: mex.cc:622
int is_uint32(void) const
Definition: mex.cc:250
char * class_name
Definition: mex.cc:662
int is_single(void) const
Definition: mex.cc:242
int get_string(char *buf, mwSize buflen) const
Definition: mex.cc:533
mxArray * as_mxArray(void) const
Definition: mex.cc:175
double get_scalar(void) const
Definition: mex.cc:425
octave_value val
Definition: mex.cc:653
mwSize get_number_of_dimensions(void) const
Definition: mex.cc:298
void set_field_by_number(mwIndex, int, mxArray *)
Definition: mex.cc:513
int is_logical_scalar_true(void) const
Definition: mex.cc:260
int is_function_handle(void) const
Definition: mex.cc:228
mxArray * get_field_by_number(mwIndex, int) const
Definition: mex.cc:506
mxArray * mutate(void) const
Definition: mex.cc:630
int is_struct(void) const
Definition: mex.cc:246
mwIndex * get_ir(void) const
Definition: mex.cc:1561
mwSize nzmax
Definition: mex.cc:1660
void set_ir(mwIndex *ir_arg)
Definition: mex.cc:1567
void * get_imag_data(void) const
Definition: mex.cc:1555
void set_nzmax(mwSize nzmax_arg)
Definition: mex.cc:1571
mxArray_sparse(const mxArray_sparse &val)
Definition: mex.cc:1510
void * get_data(void) const
Definition: mex.cc:1553
mxArray_sparse & operator=(const mxArray_sparse &)
void set_data(void *pr_arg)
Definition: mex.cc:1557
void set_jc(mwIndex *jc_arg)
Definition: mex.cc:1569
mxArray_sparse(mxClassID id_arg, mwSize m, mwSize n, mwSize nzmax_arg, mxComplexity flag=mxREAL)
Definition: mex.cc:1496
int is_complex(void) const
Definition: mex.cc:1549
void * pi
Definition: mex.cc:1663
octave_value as_octave_value(void) const
Definition: mex.cc:1577
mxArray_base * dup(void) const
Definition: mex.cc:1539
void * pr
Definition: mex.cc:1662
void set_imag_data(void *pi_arg)
Definition: mex.cc:1559
~mxArray_sparse(void)
Definition: mex.cc:1541
mwSize get_nzmax(void) const
Definition: mex.cc:1565
mwIndex * get_jc(void) const
Definition: mex.cc:1563
mwIndex * jc
Definition: mex.cc:1665
int is_sparse(void) const
Definition: mex.cc:1551
mwIndex * ir
Definition: mex.cc:1664
~mxArray_struct(void)
Definition: mex.cc:1746
int get_number_of_fields(void) const
Definition: mex.cc:1872
octave_value as_octave_value(void) const
Definition: mex.cc:1899
char ** fields
Definition: mex.cc:1929
void remove_field(int key_num)
Definition: mex.cc:1813
int nfields
Definition: mex.cc:1927
mxArray_struct(const mxArray_struct &val)
Definition: mex.cc:1711
mxArray_struct & operator=(const mxArray_struct &val)
int get_field_number(const char *key) const
Definition: mex.cc:1879
mxArray * get_field_by_number(mwIndex index, int key_num) const
Definition: mex.cc:1864
mxArray ** data
Definition: mex.cc:1931
mxArray_struct(const dim_vector &dv, int num_keys_arg, const char **keys)
Definition: mex.cc:1687
const char * get_field_name_by_number(int key_num) const
Definition: mex.cc:1874
mxArray_struct(mwSize m, mwSize n, int num_keys_arg, const char **keys)
Definition: mex.cc:1698
int add_field(const char *key)
Definition: mex.cc:1761
mxArray_struct(mwSize ndims_arg, const mwSize *dims_arg, int num_keys_arg, const char **keys)
Definition: mex.cc:1674
void init(const char **keys)
Definition: mex.cc:1738
void set_data(void *data_arg)
Definition: mex.cc:1897
mxArray_base * dup(void) const
Definition: mex.cc:1744
void * get_data(void) const
Definition: mex.cc:1895
void set_field_by_number(mwIndex index, int key_num, mxArray *val)
Definition: mex.cc:2491
mxClassID get_class_id(void) const
Definition: mxarray.in.h:453
int is_int64(void) const
Definition: mxarray.in.h:399
int is_single(void) const
Definition: mxarray.in.h:407
mxArray(const octave_value &ov)
Definition: mex.cc:2024
void maybe_mutate(void) const
Definition: mex.cc:2104
void * get_imag_data(void) const
Definition: mxarray.in.h:476
size_t get_element_size(void) const
Definition: mxarray.in.h:522
mxArray_base * rep
Definition: mxarray.in.h:556
static void * malloc(size_t n)
Definition: mex.cc:2452
const char * get_class_name(void) const
Definition: mxarray.in.h:455
void set_n(mwSize n)
Definition: mxarray.in.h:437
static void * calloc(size_t n, size_t t)
Definition: mex.cc:2458
int is_logical_scalar_true(void) const
Definition: mxarray.in.h:423
int is_uint32(void) const
Definition: mxarray.in.h:415
int is_char(void) const
Definition: mxarray.in.h:385
~mxArray(void)
Definition: mex.cc:2073
void set_property(mwIndex idx, const char *pname, const mxArray *pval)
Definition: mxarray.in.h:460
void set_m(mwSize m)
Definition: mxarray.in.h:435
mxArray * get_property(mwIndex idx, const char *pname) const
Definition: mxarray.in.h:457
mxArray * dup(void) const
Definition: mxarray.in.h:357
void * get_data(void) const
Definition: mxarray.in.h:474
mwIndex * get_jc(void) const
Definition: mxarray.in.h:485
mwIndex calc_single_subscript(mwSize nsubs, mwIndex *subs) const
Definition: mxarray.in.h:519
int is_function_handle(void) const
Definition: mxarray.in.h:393
int set_dimensions(mwSize *dims_arg, mwSize ndims_arg)
Definition: mxarray.in.h:439
static char * strsave(const char *str)
Definition: mxarray.in.h:532
int isempty(void) const
Definition: mxarray.in.h:445
mwSize get_m(void) const
Definition: mxarray.in.h:426
void set_data(void *pr)
Definition: mxarray.in.h:479
int is_uint64(void) const
Definition: mxarray.in.h:417
int is_struct(void) const
Definition: mxarray.in.h:411
int get_field_number(const char *key) const
Definition: mxarray.in.h:511
int iscell(void) const
Definition: mxarray.in.h:383
mxArray * get_field_by_number(mwIndex index, int key_num) const
Definition: mxarray.in.h:500
int add_field(const char *key)
Definition: mxarray.in.h:495
int is_int8(void) const
Definition: mxarray.in.h:401
int get_number_of_fields(void) const
Definition: mxarray.in.h:506
int is_sparse(void) const
Definition: mxarray.in.h:409
int is_double(void) const
Definition: mxarray.in.h:391
char * name
Definition: mxarray.in.h:558
mwSize get_nzmax(void) const
Definition: mxarray.in.h:487
int is_uint8(void) const
Definition: mxarray.in.h:419
mwIndex * get_ir(void) const
Definition: mxarray.in.h:483
static octave_value as_octave_value(const mxArray *ptr, bool null_is_empty=true)
Definition: mex.cc:2088
bool is_scalar(void) const
Definition: mxarray.in.h:447
void set_nzmax(mwSize nzmax)
Definition: mxarray.in.h:493
int is_logical(void) const
Definition: mxarray.in.h:403
int is_int16(void) const
Definition: mxarray.in.h:395
double get_scalar(void) const
Definition: mxarray.in.h:472
void set_jc(mwIndex *jc)
Definition: mxarray.in.h:491
mwSize get_number_of_dimensions(void) const
Definition: mxarray.in.h:432
const char * get_name(void) const
Definition: mxarray.in.h:449
int is_numeric(void) const
Definition: mxarray.in.h:405
mwSize get_number_of_elements(void) const
Definition: mxarray.in.h:442
const char * get_field_name_by_number(int key_num) const
Definition: mxarray.in.h:508
int get_string(char *buf, mwSize buflen) const
Definition: mxarray.in.h:514
int is_class(const char *name_arg) const
Definition: mxarray.in.h:387
mwSize get_n(void) const
Definition: mxarray.in.h:428
void set_class_name(const char *name_arg)
Definition: mxarray.in.h:463
int is_complex(void) const
Definition: mxarray.in.h:389
void set_name(const char *name_arg)
Definition: mex.cc:2081
int is_uint16(void) const
Definition: mxarray.in.h:413
void set_field_by_number(mwIndex index, int key_num, mxArray *val)
Definition: mxarray.in.h:503
void set_cell(mwIndex idx, mxArray *val)
Definition: mxarray.in.h:469
mxArray * get_cell(mwIndex idx) const
Definition: mxarray.in.h:466
void set_ir(mwIndex *ir)
Definition: mxarray.in.h:489
char * array_to_string(void) const
Definition: mxarray.in.h:517
int is_logical_scalar(void) const
Definition: mxarray.in.h:421
octave_value as_octave_value(void) const
Definition: mex.cc:2098
mwSize * get_dimensions(void) const
Definition: mxarray.in.h:430
void set_imag_data(void *pi)
Definition: mxarray.in.h:481
void remove_field(int key_num)
Definition: mxarray.in.h:497
int is_int32(void) const
Definition: mxarray.in.h:397
void add_method(T *obj, void(T::*method)(Params...), Args &&... args)
void assign(const std::string &name, const octave_value &val=octave_value())
void global_assign(const std::string &name, const octave_value &val=octave_value())
octave_value varval(const std::string &name) const
octave_value global_varval(const std::string &name) const
octave_value_list eval_string(const std::string &eval_str, bool silent, int &parse_status, int nargout)
bool mislocked(bool skip_first=false) const
void recover_from_exception(void)
void mlock(bool skip_first=false) const
void munlock(bool skip_first=false) const
tree_evaluator & get_evaluator(void)
size_t current_call_stack_frame_number(void) const
Definition: pt-eval.h:584
void set_lvalue_list(const std::list< octave_lvalue > *lst)
Definition: pt-eval.h:678
const std::list< octave_lvalue > * lvalue_list(void) const
Definition: pt-eval.h:673
void restore_frame(size_t n)
Definition: pt-eval.cc:1932
void goto_base_frame(void)
Definition: pt-eval.cc:1927
octave_function * current_function(bool skip_first=false) const
Definition: pt-eval.cc:1907
octave_value get_property(octave_idx_type idx, const std::string &name) const
Definition: ov-classdef.h:133
void set_property(octave_idx_type idx, const std::string &name, const octave_value &pval)
Definition: ov-classdef.h:126
std::string name(void) const
Definition: ov-fcn.h:214
bool is_fmex(void) const
Definition: ov-mex-fcn.h:101
void * mex_fcn_ptr(void) const
Definition: ov-mex-fcn.h:99
void atexit(void(*fcn)(void))
Definition: ov-mex-fcn.h:95
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
octave_idx_type length(void) const
Definition: ovl.h:113
bool is_classdef_object(void) const
Definition: ov.h:611
bool iscell(void) const
Definition: ov.h:560
bool isreal(void) const
Definition: ov.h:691
bool issparse(void) const
Definition: ov.h:706
void * mex_get_data(void) const
Definition: ov.h:1325
bool is_uint16_type(void) const
Definition: ov.h:674
mxArray * as_mxArray(void) const
Definition: ov.h:1331
bool is_true(void) const
Definition: ov.h:711
bool is_int8_type(void) const
Definition: ov.h:659
octave_idx_type rows(void) const
Definition: ov.h:504
bool isnumeric(void) const
Definition: ov.h:703
octave_idx_type numel(void) const
Definition: ov.h:518
bool is_string(void) const
Definition: ov.h:593
bool is_defined(void) const
Definition: ov.h:551
charNDArray char_array_value(bool frc_str_conv=false) const
Definition: ov.h:850
bool is_double_type(void) const
Definition: ov.h:648
bool is_function_handle(void) const
Definition: ov.h:721
std::string class_name(void) const
Definition: ov.h:1256
bool is_uint32_type(void) const
Definition: ov.h:677
int ndims(void) const
Definition: ov.h:510
bool is_int64_type(void) const
Definition: ov.h:668
bool isstruct(void) const
Definition: ov.h:605
double scalar_value(bool frc_str_conv=false) const
Definition: ov.h:800
octave_idx_type nfields(void) const
Definition: ov.h:528
bool is_int32_type(void) const
Definition: ov.h:665
bool is_uint64_type(void) const
Definition: ov.h:680
octave_idx_type nzmax(void) const
Definition: ov.h:526
bool is_int16_type(void) const
Definition: ov.h:662
bool is_range(void) const
Definition: ov.h:602
octave_classdef * classdef_object_value(bool silent=false) const
bool isempty(void) const
Definition: ov.h:557
octave_idx_type * mex_get_jc(void) const
Definition: ov.h:1329
bool is_single_type(void) const
Definition: ov.h:651
octave_idx_type * mex_get_ir(void) const
Definition: ov.h:1327
bool is_uint8_type(void) const
Definition: ov.h:671
bool iscomplex(void) const
Definition: ov.h:694
bool islogical(void) const
Definition: ov.h:688
dim_vector dims(void) const
Definition: ov.h:500
void warning(const char *fmt,...)
Definition: error.cc:1050
void vwarning_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:1059
void verror_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:1007
void error(const char *fmt,...)
Definition: error.cc:968
#define panic_impossible()
Definition: error.h:380
octave_f77_int_type F77_INT
Definition: f77-fcn.h:305
bool set_property_in_handle(double handle, const std::string &property, const octave_value &arg, const std::string &func)
Definition: graphics.cc:14072
octave_value get_property_from_handle(double handle, const std::string &property, const std::string &func)
Definition: graphics.cc:14056
QString name
double lo_ieee_inf_value(void)
Definition: lo-ieee.cc:78
double lo_ieee_nan_value(void)
Definition: lo-ieee.cc:94
#define lo_ieee_isnan(x)
Definition: lo-ieee.h:112
#define lo_ieee_isinf(x)
Definition: lo-ieee.h:120
#define lo_ieee_finite(x)
Definition: lo-ieee.h:116
F77_RET_T(F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, const F77_INT &, const F77_INT &, const F77_INT &, F77_INT &, F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, F77_DBLE *, F77_DBLE *, const F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, F77_INT *, F77_INT &F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE const F77_DBLE * f
static char * strsave(const char *s)
Definition: main.in.cc:195
void mxSetIr(mxArray *ptr, mwIndex *ir)
Definition: mex.cc:3050
void mxSetCell(mxArray *ptr, mwIndex idx, mxArray *val)
Definition: mex.cc:3025
bool mxIsUint16(const mxArray *ptr)
Definition: mex.cc:2802
mxArray * mxCreateCellMatrix(mwSize m, mwSize n)
Definition: mex.cc:2589
void mexWarnMsgIdAndTxt(const char *id, const char *fmt,...)
Definition: mex.cc:3477
size_t mxGetN(const mxArray *ptr)
Definition: mex.cc:2870
void * mxGetData(const mxArray *ptr)
Definition: mex.cc:2949
mwIndex mxCalcSingleSubscript(const mxArray *ptr, mwSize nsubs, mwIndex *subs)
Definition: mex.cc:3137
bool mxIsFunctionHandle(const mxArray *ptr)
Definition: mex.cc:2742
bool mxIsStruct(const mxArray *ptr)
Definition: mex.cc:2796
double * mxGetPi(const mxArray *ptr)
Definition: mex.cc:2922
int mxGetFieldNumber(const mxArray *ptr, const char *key)
Definition: mex.cc:3119
void mexErrMsgTxt(const char *s)
Definition: mex.cc:3409
mex * mex_context
Definition: mex.cc:2449
void mxSetField(mxArray *ptr, mwIndex index, const char *key, mxArray *val)
Definition: mex.cc:3094
size_t mxGetNumberOfElements(const mxArray *ptr)
Definition: mex.cc:2888
void(* cmex_fptr)(int nlhs, mxArray **plhs, int nrhs, mxArray **prhs)
Definition: mex.cc:3150
bool mxIsUint32(const mxArray *ptr)
Definition: mex.cc:2808
void mxSetProperty(mxArray *ptr, mwIndex idx, const char *property_name, const mxArray *property_value)
Definition: mex.cc:3005
bool mxIsComplex(const mxArray *ptr)
Definition: mex.cc:2730
std::map< std::string, int > mex_lock_count
Definition: mex.cc:3678
int mexAtExit(void(*f)(void))
Definition: mex.cc:3628
mxArray * mxCreateUninitNumericArray(mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:2651
size_t mxGetElementSize(const mxArray *ptr)
Definition: mex.cc:3143
bool mxIsFinite(const double v)
Definition: mex.cc:2511
bool mxIsScalar(const mxArray *ptr)
Definition: mex.cc:2847
bool mxIsFromGlobalWS(const mxArray *)
Definition: mex.cc:2855
mxArray * mxCreateLogicalArray(mwSize ndims, const mwSize *dims)
Definition: mex.cc:2619
void mxSetFieldByNumber(mxArray *ptr, mwIndex index, int key_num, mxArray *val)
Definition: mex.cc:3101
const char * mxGetClassName(const mxArray *ptr)
Definition: mex.cc:2993
void * mxMalloc(size_t n)
Definition: mex.cc:2554
bool mxIsLogicalScalarTrue(const mxArray *ptr)
Definition: mex.cc:2834
mxArray * mxCreateLogicalScalar(mxLogical val)
Definition: mex.cc:2631
mxClassID mxGetClassID(const mxArray *ptr)
Definition: mex.cc:2987
bool mxIsLogical(const mxArray *ptr)
Definition: mex.cc:2772
mxArray * mxGetProperty(const mxArray *ptr, mwIndex idx, const char *property_name)
Definition: mex.cc:3012
static void * maybe_unmark(void *ptr)
Definition: mex.cc:2482
mxArray * mxCreateCellArray(mwSize ndims, const mwSize *dims)
Definition: mex.cc:2583
void mexWarnMsgTxt(const char *s)
Definition: mex.cc:3454
void mxSetData(mxArray *ptr, void *pr)
Definition: mex.cc:2974
const char * mexFunctionName(void)
Definition: mex.cc:3226
void * mxCalloc(size_t n, size_t size)
Definition: mex.cc:2548
mwIndex * mxGetIr(const mxArray *ptr)
Definition: mex.cc:3032
bool mxIsInt64(const mxArray *ptr)
Definition: mex.cc:2760
mxArray * mxGetFieldByNumber(const mxArray *ptr, mwIndex index, int key_num)
Definition: mex.cc:3088
mxArray * mexCallMATLABWithTrap(int nargout, mxArray *argout[], int nargin, mxArray *argin[], const char *fname)
Definition: mex.cc:3311
int mxSetDimensions(mxArray *ptr, const mwSize *dims, mwSize ndims)
Definition: mex.cc:2907
octave_value_list call_mex(octave_mex_function &mex_fcn, const octave_value_list &args, int nargout_arg)
Definition: mex.cc:3155
int mexPrintf(const char *fmt,...)
Definition: mex.cc:3496
bool mxIsChar(const mxArray *ptr)
Definition: mex.cc:2718
bool mxIsInf(const double v)
Definition: mex.cc:2517
mxArray * mxCreateUninitNumericMatrix(mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:2658
bool mxIsUint8(const mxArray *ptr)
Definition: mex.cc:2820
void mxDestroyArray(mxArray *ptr)
Definition: mex.cc:2704
void mxSetNzmax(mxArray *ptr, mwSize nzmax)
Definition: mex.cc:3062
bool mxIsSingle(const mxArray *ptr)
Definition: mex.cc:2784
void mexErrMsgIdAndTxt(const char *id, const char *fmt,...)
Definition: mex.cc:3432
F77_RET_T(* fmex_fptr)(F77_INT &nlhs, mxArray **plhs, F77_INT &nrhs, mxArray **prhs)
Definition: mex.cc:3151
int mxAddField(mxArray *ptr, const char *key)
Definition: mex.cc:3069
void mexMakeMemoryPersistent(void *ptr)
Definition: mex.cc:3622
bool mxIsInt8(const mxArray *ptr)
Definition: mex.cc:2766
void mxSetImagData(mxArray *ptr, void *pi)
Definition: mex.cc:2980
int mexCallMATLAB(int nargout, mxArray *argout[], int nargin, mxArray *argin[], const char *fname)
Definition: mex.cc:3232
bool mxIsNaN(const double v)
Definition: mex.cc:2523
void mxSetPr(mxArray *ptr, double *pr)
Definition: mex.cc:2962
mxArray * mxCreateSparseLogicalMatrix(mwSize m, mwSize n, mwSize nzmax)
Definition: mex.cc:2671
mxArray * mexEvalStringWithTrap(const char *s)
Definition: mex.cc:3371
mxArray * mexGetVariable(const char *space, const char *name)
Definition: mex.cc:3507
mxArray * mxCreateStructArray(mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
Definition: mex.cc:2683
bool mxIsClass(const mxArray *ptr, const char *name)
Definition: mex.cc:2724
mxArray * mxCreateStructMatrix(mwSize m, mwSize n, int num_keys, const char **keys)
Definition: mex.cc:2690
mxArray * mxCreateDoubleMatrix(mwSize m, mwSize n, mxComplexity flag)
Definition: mex.cc:2607
static mwSize max_str_len(mwSize m, const char **str)
Definition: mex.cc:74
int mxGetNumberOfFields(const mxArray *ptr)
Definition: mex.cc:3107
mxArray * mxCreateCharArray(mwSize ndims, const mwSize *dims)
Definition: mex.cc:2595
mwIndex * mxGetJc(const mxArray *ptr)
Definition: mex.cc:3038
int mexPutVariable(const char *space, const char *name, const mxArray *ptr)
Definition: mex.cc:3564
void mxSetN(mxArray *ptr, mwSize n)
Definition: mex.cc:2901
static mxArray * maybe_mark_array(mxArray *ptr)
Definition: mex.cc:2576
bool mxIsInt32(const mxArray *ptr)
Definition: mex.cc:2754
void mexUnlock(void)
Definition: mex.cc:3708
mxArray * mxCreateCharMatrixFromStrings(mwSize m, const char **str)
Definition: mex.cc:2601
int mexIsGlobal(const mxArray *ptr)
Definition: mex.cc:3656
void mxSetJc(mxArray *ptr, mwIndex *jc)
Definition: mex.cc:3056
bool mxIsInt16(const mxArray *ptr)
Definition: mex.cc:2748
const mwSize * mxGetDimensions(const mxArray *ptr)
Definition: mex.cc:2876
int mexEvalString(const char *s)
Definition: mex.cc:3342
void mexSetTrapFlag(int flag)
Definition: mex.cc:3335
mwSize mxGetNzmax(const mxArray *ptr)
Definition: mex.cc:3044
void mxSetClassName(mxArray *ptr, const char *name)
Definition: mex.cc:2999
const mxArray * mexGetVariablePtr(const char *space, const char *name)
Definition: mex.cc:3558
bool mxIsNumeric(const mxArray *ptr)
Definition: mex.cc:2778
mxArray * mxCreateNumericMatrix(mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:2644
int mexIsLocked(void)
Definition: mex.cc:3662
bool mxIsCell(const mxArray *ptr)
Definition: mex.cc:2712
static mxArray * maybe_unmark_array(mxArray *ptr)
Definition: mex.cc:2473
void mexMakeArrayPersistent(mxArray *ptr)
Definition: mex.cc:3616
double mxGetScalar(const mxArray *ptr)
Definition: mex.cc:2928
void mxRemoveField(mxArray *ptr, int key_num)
Definition: mex.cc:3075
size_t mxGetM(const mxArray *ptr)
Definition: mex.cc:2864
mxArray * mxCreateDoubleScalar(double val)
Definition: mex.cc:2613
int mxGetString(const mxArray *ptr, char *buf, mwSize buflen)
Definition: mex.cc:3125
const char * mxGetFieldNameByNumber(const mxArray *ptr, int key_num)
Definition: mex.cc:3113
bool mxIsLogicalScalar(const mxArray *ptr)
Definition: mex.cc:2827
double mxGetInf(void)
Definition: mex.cc:2535
double mxGetNaN(void)
Definition: mex.cc:2541
mxArray * mxCreateLogicalMatrix(mwSize m, mwSize n)
Definition: mex.cc:2625
static void xfree(void *ptr)
Definition: mex.cc:68
mwSize mxGetNumberOfDimensions(const mxArray *ptr)
Definition: mex.cc:2882
mxLogical * mxGetLogicals(const mxArray *ptr)
Definition: mex.cc:2943
double mxGetEps(void)
Definition: mex.cc:2529
double * mxGetPr(const mxArray *ptr)
Definition: mex.cc:2916
int mexSet(double handle, const char *property, mxArray *val)
Definition: mex.cc:3699
void mexLock(void)
Definition: mex.cc:3681
const mxArray * mexGet(double handle, const char *property)
Definition: mex.cc:3643
bool mxIsEmpty(const mxArray *ptr)
Definition: mex.cc:2841
mxArray * mxGetField(const mxArray *ptr, mwIndex index, const char *key)
Definition: mex.cc:3081
char * mxArrayToString(const mxArray *ptr)
Definition: mex.cc:3131
static int valid_key(const char *key)
Definition: mex.cc:90
void * mxGetImagData(const mxArray *ptr)
Definition: mex.cc:2955
void mxFree(void *ptr)
Definition: mex.cc:2567
mxChar * mxGetChars(const mxArray *ptr)
Definition: mex.cc:2934
mxArray * mxCreateSparse(mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
Definition: mex.cc:2665
bool mxIsSparse(const mxArray *ptr)
Definition: mex.cc:2790
bool mxIsUint64(const mxArray *ptr)
Definition: mex.cc:2814
mxArray * mxCreateNumericArray(mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:2637
bool mxIsDouble(const mxArray *ptr)
Definition: mex.cc:2736
mxArray * mxGetCell(const mxArray *ptr, mwIndex idx)
Definition: mex.cc:3019
void mxSetPi(mxArray *ptr, double *pi)
Definition: mex.cc:2968
mxArray * mxCreateString(const char *str)
Definition: mex.cc:2677
void mxSetM(mxArray *ptr, mwSize m)
Definition: mex.cc:2895
static mwIndex calc_single_subscript_internal(mwSize ndims, const mwSize *dims, mwSize nsubs, const mwIndex *subs)
Definition: mex.cc:116
static void * maybe_mark_foreign(void *ptr)
Definition: mex.cc:2464
mxArray * mxDuplicateArray(const mxArray *ptr)
Definition: mex.cc:2697
void * mxRealloc(void *ptr, size_t size)
Definition: mex.cc:2560
void mxArray
Definition: mex.h:58
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
char mxChar
Definition: mxarray.in.h:87
OCTAVE_IDX_TYPE mwSize
Definition: mxarray.in.h:97
mxClassID
Definition: mxarray.in.h:57
@ mxFUNCTION_CLASS
Definition: mxarray.in.h:74
@ mxINT8_CLASS
Definition: mxarray.in.h:66
@ mxINT64_CLASS
Definition: mxarray.in.h:72
@ mxUINT8_CLASS
Definition: mxarray.in.h:67
@ mxUNKNOWN_CLASS
Definition: mxarray.in.h:58
@ mxLOGICAL_CLASS
Definition: mxarray.in.h:61
@ mxSTRUCT_CLASS
Definition: mxarray.in.h:60
@ mxINT32_CLASS
Definition: mxarray.in.h:70
@ mxSINGLE_CLASS
Definition: mxarray.in.h:65
@ mxDOUBLE_CLASS
Definition: mxarray.in.h:64
@ mxUINT64_CLASS
Definition: mxarray.in.h:73
@ mxCHAR_CLASS
Definition: mxarray.in.h:62
@ mxUINT16_CLASS
Definition: mxarray.in.h:69
@ mxCELL_CLASS
Definition: mxarray.in.h:59
@ mxUINT32_CLASS
Definition: mxarray.in.h:71
@ mxINT16_CLASS
Definition: mxarray.in.h:68
OCTAVE_IDX_TYPE mwIndex
Definition: mxarray.in.h:98
mxComplexity
Definition: mxarray.in.h:79
@ mxREAL
Definition: mxarray.in.h:80
@ mxCOMPLEX
Definition: mxarray.in.h:81
unsigned char mxLogical
Definition: mxarray.in.h:89
static const double pi
Definition: lo-specfun.cc:1995
bool strcmp(const T &str_a, const T &str_b)
True if strings are the same.
Definition: oct-string.cc:122
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:80
interpreter & __get_interpreter__(const std::string &who)
tree_evaluator & __get_evaluator__(const std::string &who)
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:9580
size_t vformat(std::ostream &os, const char *fmt, va_list args)
Definition: utils.cc:1343
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:85
void * malloc(unsigned)
void free(void *)
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
#define octave_stdout
Definition: pager.h:313
F77_RET_T len
Definition: xerbla.cc:61