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