GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
mex.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2006-2023 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 // #define DEBUG 1
31 
32 #if defined (DEBUG)
33 # include <iostream>
34 #endif
35 
36 #include <cstdarg>
37 #include <cstdlib>
38 #include <cstring>
39 #include <cctype>
40 
41 #include <limits>
42 #include <map>
43 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
44 # include <memory_resource>
45 #endif
46 #include <set>
47 #include <string>
48 
49 #include "f77-fcn.h"
50 #include "lo-ieee.h"
51 #include "oct-locbuf.h"
52 #include "quit.h"
53 
54 #include "Cell.h"
55 #include "error.h"
56 #include "interpreter-private.h"
57 #include "interpreter.h"
58 // mxArray must be declared as a class before including mexproto.h.
59 #include "mxarray.h"
60 #include "mexproto.h"
61 #include "oct-map.h"
62 #include "ovl.h"
63 #include "ov.h"
64 #include "ov-classdef.h"
65 #include "ov-mex-fcn.h"
66 #include "ov-usr-fcn.h"
67 #include "pager.h"
68 #include "parse.h"
69 #include "unwind-prot.h"
70 #include "utils.h"
71 #include "variables.h"
72 #include "graphics.h"
73 
74 // These must be declared extern "C" but may be omitted from the set of
75 // symbols declared in mexproto.h, so we declare them here as well.
76 
77 extern "C"
78 {
79  extern OCTINTERP_API const mxArray *
80  mexGet_interleaved (double handle, const char *property);
81 
82  extern OCTINTERP_API mxArray *
83  mxCreateCellArray (mwSize ndims, const mwSize *dims);
84 
85  extern OCTINTERP_API mxArray *
86  mxCreateCellMatrix (mwSize m, mwSize n);
87 
88  extern OCTINTERP_API mxArray *
89  mxCreateCharArray (mwSize ndims, const mwSize *dims);
90 
91  extern OCTINTERP_API mxArray *
92  mxCreateCharMatrixFromStrings (mwSize m, const char **str);
93 
94  extern OCTINTERP_API mxArray *
95  mxCreateDoubleMatrix (mwSize nr, mwSize nc, mxComplexity flag);
96 
97  extern OCTINTERP_API mxArray *
98  mxCreateDoubleScalar (double val);
99 
100  extern OCTINTERP_API mxArray *
101  mxCreateLogicalArray (mwSize ndims, const mwSize *dims);
102 
103  extern OCTINTERP_API mxArray *
104  mxCreateLogicalMatrix (mwSize m, mwSize n);
105 
106  extern OCTINTERP_API mxArray *
107  mxCreateLogicalScalar (mxLogical val);
108 
109  extern OCTINTERP_API mxArray *
110  mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,
111  mxComplexity flag);
112 
113  extern OCTINTERP_API mxArray *
114  mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
115  mxComplexity flag);
116 
117  extern OCTINTERP_API mxArray *
118  mxCreateUninitNumericArray (mwSize ndims, const mwSize *dims,
119  mxClassID class_id, mxComplexity flag);
120 
121  extern OCTINTERP_API mxArray *
122  mxCreateUninitNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
123  mxComplexity flag);
124 
125  extern OCTINTERP_API mxArray *
126  mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag);
127 
128  extern OCTINTERP_API mxArray *
129  mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax);
130 
131  extern OCTINTERP_API mxArray *
132  mxCreateString (const char *str);
133 
134  extern OCTINTERP_API mxArray *
135  mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys,
136  const char **keys);
137 
138  extern OCTINTERP_API mxArray *
139  mxCreateStructMatrix (mwSize rows, mwSize cols, int num_keys,
140  const char **keys);
141 
142  extern OCTINTERP_API mxArray *
143  mxCreateCellArray_interleaved (mwSize ndims, const mwSize *dims);
144 
145  extern OCTINTERP_API mxArray *
146  mxCreateCellMatrix_interleaved (mwSize m, mwSize n);
147 
148  extern OCTINTERP_API mxArray *
149  mxCreateCharArray_interleaved (mwSize ndims, const mwSize *dims);
150 
151  extern OCTINTERP_API mxArray *
152  mxCreateCharMatrixFromStrings_interleaved (mwSize m, const char **str);
153 
154  extern OCTINTERP_API mxArray *
155  mxCreateDoubleMatrix_interleaved (mwSize nr, mwSize nc, mxComplexity flag);
156 
157  extern OCTINTERP_API mxArray *
159 
160  extern OCTINTERP_API mxArray *
161  mxCreateLogicalArray_interleaved (mwSize ndims, const mwSize *dims);
162 
163  extern OCTINTERP_API mxArray *
164  mxCreateLogicalMatrix_interleaved (mwSize m, mwSize n);
165 
166  extern OCTINTERP_API mxArray *
167  mxCreateLogicalScalar_interleaved (mxLogical val);
168 
169  extern OCTINTERP_API mxArray *
170  mxCreateNumericArray_interleaved (mwSize ndims, const mwSize *dims,
171  mxClassID class_id, mxComplexity flag);
172 
173  extern OCTINTERP_API mxArray *
174  mxCreateNumericMatrix_interleaved (mwSize m, mwSize n, mxClassID class_id,
175  mxComplexity flag);
176 
177  extern OCTINTERP_API mxArray *
178  mxCreateUninitNumericArray_interleaved (mwSize ndims, const mwSize *dims,
179  mxClassID class_id,
180  mxComplexity flag);
181 
182  extern OCTINTERP_API mxArray *
184  mxClassID class_id,
185  mxComplexity flag);
186 
187  extern OCTINTERP_API mxArray *
188  mxCreateSparse_interleaved (mwSize m, mwSize n, mwSize nzmax,
189  mxComplexity flag);
190 
191  extern OCTINTERP_API mxArray *
192  mxCreateSparseLogicalMatrix_interleaved (mwSize m, mwSize n, mwSize nzmax);
193 
194  extern OCTINTERP_API mxArray *
195  mxCreateString_interleaved (const char *str);
196 
197  extern OCTINTERP_API mxArray *
198  mxCreateStructArray_interleaved (mwSize ndims, const mwSize *dims,
199  int num_keys, const char **keys);
200 
201  extern OCTINTERP_API mxArray *
202  mxCreateStructMatrix_interleaved (mwSize rows, mwSize cols, int num_keys,
203  const char **keys);
204 
205  extern OCTINTERP_API int mxMakeArrayReal (mxArray *ptr);
206  extern OCTINTERP_API int mxMakeArrayComplex (mxArray *ptr);
207 
208  extern OCTINTERP_API mxDouble * mxGetDoubles (const mxArray *p);
209  extern OCTINTERP_API mxSingle * mxGetSingles (const mxArray *p);
210  extern OCTINTERP_API mxInt8 * mxGetInt8s (const mxArray *p);
211  extern OCTINTERP_API mxInt16 * mxGetInt16s (const mxArray *p);
212  extern OCTINTERP_API mxInt32 * mxGetInt32s (const mxArray *p);
213  extern OCTINTERP_API mxInt64 * mxGetInt64s (const mxArray *p);
214  extern OCTINTERP_API mxUint8 * mxGetUint8s (const mxArray *p);
215  extern OCTINTERP_API mxUint16 * mxGetUint16s (const mxArray *p);
216  extern OCTINTERP_API mxUint32 * mxGetUint32s (const mxArray *p);
217  extern OCTINTERP_API mxUint64 * mxGetUint64s (const mxArray *p);
218 
219  extern OCTINTERP_API mxComplexDouble * mxGetComplexDoubles (const mxArray *p);
220  extern OCTINTERP_API mxComplexSingle * mxGetComplexSingles (const mxArray *p);
221 #if 0
222  /* We don't have these yet. */
223  extern OCTINTERP_API mxComplexInt8 * mxGetComplexInt8s (const mxArray *p);
224  extern OCTINTERP_API mxComplexInt16 * mxGetComplexInt16s (const mxArray *p);
225  extern OCTINTERP_API mxComplexInt32 * mxGetComplexInt32s (const mxArray *p);
226  extern OCTINTERP_API mxComplexInt64 * mxGetComplexInt64s (const mxArray *p);
227  extern OCTINTERP_API mxComplexUint8 * mxGetComplexUint8s (const mxArray *p);
228  extern OCTINTERP_API mxComplexUint16 * mxGetComplexUint16s (const mxArray *p);
229  extern OCTINTERP_API mxComplexUint32 * mxGetComplexUint32s (const mxArray *p);
230  extern OCTINTERP_API mxComplexUint64 * mxGetComplexUint64s (const mxArray *p);
231 #endif
232 
233  extern OCTINTERP_API double * mxGetPi (const mxArray *ptr);
234  extern OCTINTERP_API void * mxGetImagData (const mxArray *ptr);
235 
236  extern OCTINTERP_API int mxSetDoubles (mxArray *p, mxDouble *d);
237  extern OCTINTERP_API int mxSetSingles (mxArray *p, mxSingle *d);
238  extern OCTINTERP_API int mxSetInt8s (mxArray *p, mxInt8 *d);
239  extern OCTINTERP_API int mxSetInt16s (mxArray *p, mxInt16 *d);
240  extern OCTINTERP_API int mxSetInt32s (mxArray *p, mxInt32 *d);
241  extern OCTINTERP_API int mxSetInt64s (mxArray *p, mxInt64 *d);
242  extern OCTINTERP_API int mxSetUint8s (mxArray *p, mxUint8 *d);
243  extern OCTINTERP_API int mxSetUint16s (mxArray *p, mxUint16 *d);
244  extern OCTINTERP_API int mxSetUint32s (mxArray *p, mxUint32 *d);
245  extern OCTINTERP_API int mxSetUint64s (mxArray *p, mxUint64 *d);
246 
247  extern OCTINTERP_API int mxSetComplexDoubles (mxArray *p, mxComplexDouble *d);
248  extern OCTINTERP_API int mxSetComplexSingles (mxArray *p, mxComplexSingle *d);
249 #if 0
250  /* We don't have these yet. */
251  extern OCTINTERP_API int mxSetComplexInt8s (mxArray *p, mxComplexInt8 *d);
252  extern OCTINTERP_API int mxSetComplexInt16s (mxArray *p, mxComplexInt16 *d);
253  extern OCTINTERP_API int mxSetComplexInt32s (mxArray *p, mxComplexInt32 *d);
254  extern OCTINTERP_API int mxSetComplexInt64s (mxArray *p, mxComplexInt64 *d);
255  extern OCTINTERP_API int mxSetComplexUint8s (mxArray *p, mxComplexUint8 *d);
256  extern OCTINTERP_API int mxSetComplexUint16s (mxArray *p, mxComplexUint16 *d);
257  extern OCTINTERP_API int mxSetComplexUint32s (mxArray *p, mxComplexUint32 *d);
258  extern OCTINTERP_API int mxSetComplexUint64s (mxArray *p, mxComplexUint64 *d);
259 #endif
260 
261  extern OCTINTERP_API void mxSetPi (mxArray *ptr, double *pi);
262  extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
263 }
264 
265 static void *
266 xmalloc (size_t n)
267 {
268  void *ptr = std::malloc (n);
269 
270 #if defined (DEBUG)
271  std::cerr << "xmalloc (" << n << ") = " << ptr << std::endl;
272 #endif
273 
274  return ptr;
275 }
276 
277 static void *
278 xrealloc (void *ptr, size_t n)
279 {
280  void *newptr = std::realloc (ptr, n);
281 
282 #if defined (DEBUG)
283  std::cerr << "xrealloc (" << ptr << ", " << n << ") = " << newptr
284  << std::endl;
285 #endif
286 
287  return newptr;
288 }
289 
290 static void
291 xfree (void *ptr)
292 {
293 #if defined (DEBUG)
294  std::cerr << "xfree (" << ptr << ")" << std::endl;
295 #endif
296 
297  std::free (ptr);
298 }
299 
300 static mwSize
301 max_str_len (mwSize m, const char **str)
302 {
303  int max_len = 0;
304 
305  for (mwSize i = 0; i < m; i++)
306  {
307  mwSize tmp = strlen (str[i]);
308 
309  if (tmp > max_len)
310  max_len = tmp;
311  }
312 
313  return max_len;
314 }
315 
316 // FIXME: Is there a better/standard way to do this job?
317 
318 template <typename T>
320 {
321 public:
322  static const bool is_complex = false;
323 };
324 
325 template <>
327 {
328 public:
329  static const bool is_complex = true;
330 };
331 
332 template <>
334 {
335 public:
336  static const bool is_complex = true;
337 };
338 
339 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
340 
341 class mx_deleting_memory_resource : public std::pmr::memory_resource
342 {
343 private:
344 
345  void * do_allocate (std::size_t bytes, size_t /*alignment*/)
346  {
347  void *ptr = xmalloc (bytes);
348 
349  if (! ptr)
350  throw std::bad_alloc ();
351 
352  return ptr;
353  }
354 
355  void do_deallocate (void *ptr, std::size_t /*bytes*/,
356  std::size_t /*alignment*/)
357  {
358  xfree (ptr);
359  }
360 
361  bool do_is_equal (const std::pmr::memory_resource& other) const noexcept
362  {
363  return this == dynamic_cast<const mx_deleting_memory_resource *> (&other);
364  }
365 };
366 
367 class mx_preserving_memory_resource : public std::pmr::memory_resource
368 {
369 private:
370 
371  void * do_allocate (std::size_t bytes, size_t /*alignment*/)
372  {
373  void *ptr = xmalloc (bytes);
374 
375  if (! ptr)
376  throw std::bad_alloc ();
377 
378  return ptr;
379  }
380 
381  void do_deallocate (void * /*ptr*/, std::size_t /*bytes*/,
382  std::size_t /*alignment*/)
383  { }
384 
385  bool do_is_equal (const std::pmr::memory_resource& other) const noexcept
386  {
387  return this == dynamic_cast<const mx_preserving_memory_resource *> (&other);
388  }
389 };
390 
391 // FIXME: Is it OK for the memory resource object to be defined this
392 // way?
393 static mx_deleting_memory_resource the_mx_deleting_memory_resource;
394 static mx_preserving_memory_resource the_mx_preserving_memory_resource;
395 
396 static std::pmr::memory_resource *current_mx_memory_resource = &the_mx_deleting_memory_resource;
397 
398 #endif
399 
400 // ------------------------------------------------------------------
401 
402 mxArray_base::mxArray_base (bool interleaved)
403  : m_interleaved (interleaved)
404 { }
405 
406 static mwIndex
407 calc_single_subscript_internal (mwSize ndims, const mwSize *dims,
408  mwSize nsubs, const mwIndex *subs)
409 {
410  mwIndex retval = 0;
411 
412  switch (nsubs)
413  {
414  case 0:
415  break;
416 
417  case 1:
418  retval = subs[0];
419  break;
420 
421  default:
422  {
423  // Both nsubs and ndims should be at least 2 here.
424 
425  mwSize n = (nsubs <= ndims ? nsubs : ndims);
426 
427  retval = subs[--n];
428 
429  while (--n >= 0)
430  retval = dims[n] * retval + subs[n];
431  }
432  break;
433  }
434 
435  return retval;
436 }
437 
438 // The object that handles values pass to MEX files from Octave. Some
439 // methods in this class may set mutate_flag to TRUE to tell the
440 // mxArray class to convert to the Matlab-style representation and
441 // then invoke the method on that object instead (for example, getting
442 // a pointer to real or imaginary data from a complex object requires
443 // a mutation but getting a pointer to real data from a real object
444 // does not). Changing the representation causes a copy so we try to
445 // avoid it unless it is really necessary. Once the conversion
446 // happens, we delete this representation, so the conversion can only
447 // happen once per call to a MEX file.
448 
449 static inline void * maybe_mark_foreign (void *ptr);
450 
451 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
452 static inline void maybe_disown_ptr (void *ptr);
453 #endif
454 
455 #define VOID_MUTATION_METHOD(FCN_NAME, ARG_LIST) \
456  void FCN_NAME ARG_LIST { request_mutation (); }
457 
458 #define CONST_VOID_MUTATION_METHOD(FCN_NAME, ARG_LIST) \
459  void FCN_NAME ARG_LIST const { request_mutation (); }
460 
461 #define MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL) \
462  RET_TYPE FCN_NAME ARG_LIST { request_mutation (); return RET_VAL; }
463 
464 #define CONST_MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL) \
465  RET_TYPE FCN_NAME ARG_LIST const { request_mutation (); return RET_VAL; }
466 
467 #define GET_DATA_METHOD(RT, FCN_NAME, ID, COMPLEXITY) \
468  RT * FCN_NAME (void) const { return get_data<RT> (ID, COMPLEXITY); }
469 
471 {
472 public:
473 
474  mxArray_octave_value (bool interleaved, const octave_value& ov)
475  : mxArray_base (interleaved), m_val (ov), m_mutate_flag (false),
476  m_id (mxUNKNOWN_CLASS), m_class_name (nullptr), m_ndims (-1),
477  m_dims (nullptr)
478  { }
479 
480  // No assignment! FIXME: should this be implemented? Note that we
481  // do have a copy constructor.
482 
484 
485  mxArray_base * dup (void) const { return new mxArray_octave_value (*this); }
486 
487  mxArray * as_mxArray (void) const
488  {
490 
491  // RETVAL is assumed to be an mxArray_matlab object. Should we
492  // error_unless that condition here?
493 
494  if (retval)
495  {
496  // Preserve cached values of class name and dimensions in case
497  // they will be used after we mutate.
498 
499  // set_class_name will handle deleting class name that comes
500  // from as_mxArray conversion function.
501 
502  if (m_class_name)
503  {
504  retval->set_class_name (m_class_name);
505 
506  m_class_name = nullptr;
507  }
508 
509  if (m_dims)
510  {
511  mwSize *xdims = retval->get_dimensions ();
512 
513  mxFree (xdims);
514 
515  retval->set_dimensions (m_dims, m_ndims);
516 
517  m_dims = nullptr;
518  }
519  }
520 
521  return retval;
522  }
523 
525  {
527  mxFree (m_dims);
528  }
529 
530  bool is_octave_value (void) const { return true; }
531 
532  int iscell (void) const { return m_val.iscell (); }
533 
534  int is_char (void) const { return m_val.is_string (); }
535 
536  int is_complex (void) const { return m_val.iscomplex (); }
537 
538  int is_double (void) const { return m_val.is_double_type (); }
539 
540  int is_function_handle (void) const { return m_val.is_function_handle (); }
541 
542  int is_int16 (void) const { return m_val.is_int16_type (); }
543 
544  int is_int32 (void) const { return m_val.is_int32_type (); }
545 
546  int is_int64 (void) const { return m_val.is_int64_type (); }
547 
548  int is_int8 (void) const { return m_val.is_int8_type (); }
549 
550  int is_logical (void) const { return m_val.islogical (); }
551 
552  int is_numeric (void) const { return m_val.isnumeric (); }
553 
554  int is_single (void) const { return m_val.is_single_type (); }
555 
556  int is_sparse (void) const { return m_val.issparse (); }
557 
558  int is_struct (void) const { return m_val.isstruct (); }
559 
560  int is_uint16 (void) const { return m_val.is_uint16_type (); }
561 
562  int is_uint32 (void) const { return m_val.is_uint32_type (); }
563 
564  int is_uint64 (void) const { return m_val.is_uint64_type (); }
565 
566  int is_uint8 (void) const { return m_val.is_uint8_type (); }
567 
568  int is_range (void) const { return m_val.is_range (); }
569 
570  int isreal (void) const { return m_val.isreal (); }
571 
572  int is_logical_scalar_true (void) const
573  {
574  return (is_logical_scalar () && m_val.is_true ());
575  }
576 
577  mwSize get_m (void) const { return m_val.rows (); }
578 
579  mwSize get_n (void) const
580  {
581  mwSize n = 1;
582 
583  // Force m_dims and m_ndims to be cached.
584  get_dimensions ();
585 
586  for (mwIndex i = m_ndims - 1; i > 0; i--)
587  n *= m_dims[i];
588 
589  return n;
590  }
591 
592  mwSize * get_dimensions (void) const
593  {
594  if (! m_dims)
595  {
596  m_ndims = m_val.ndims ();
597 
598  m_dims = static_cast<mwSize *> (mxArray::malloc (m_ndims
599  * sizeof (mwSize)));
600 
601  dim_vector dv = m_val.dims ();
602 
603  for (mwIndex i = 0; i < m_ndims; i++)
604  m_dims[i] = dv(i);
605  }
606 
607  return m_dims;
608  }
609 
610  mwSize get_number_of_dimensions (void) const
611  {
612  // Force m_dims and m_ndims to be cached.
613  get_dimensions ();
614 
615  return m_ndims;
616  }
617 
620 
621  MUTATION_METHOD (int, set_dimensions, (mwSize *, mwSize), 0)
622 
623  mwSize get_number_of_elements (void) const { return m_val.numel (); }
624 
625  int isempty (void) const { return m_val.isempty (); }
626 
627  bool is_scalar (void) const
628  {
629  // Force m_dims and m_ndims to be cached.
630  get_dimensions ();
631 
632  return m_ndims == 2 && m_dims[0] == 1 && m_dims[1] == 1;
633  }
634 
635  mxClassID get_class_id (void) const
636  {
637  m_id = mxUNKNOWN_CLASS;
638 
639  std::string cn = m_val.class_name ();
640 
641  if (cn == "double")
642  m_id = mxDOUBLE_CLASS;
643  else if (cn == "single")
644  m_id = mxSINGLE_CLASS;
645  else if (cn == "char")
646  m_id = mxCHAR_CLASS;
647  else if (cn == "logical")
648  m_id = mxLOGICAL_CLASS;
649  else if (cn == "cell")
650  m_id = mxCELL_CLASS;
651  else if (cn == "struct")
652  m_id = mxSTRUCT_CLASS;
653  else if (cn == "function_handle")
654  m_id = mxFUNCTION_CLASS;
655  else if (cn == "int8")
656  m_id = mxINT8_CLASS;
657  else if (cn == "uint8")
658  m_id = mxUINT8_CLASS;
659  else if (cn == "int16")
660  m_id = mxINT16_CLASS;
661  else if (cn == "uint16")
662  m_id = mxUINT16_CLASS;
663  else if (cn == "int32")
664  m_id = mxINT32_CLASS;
665  else if (cn == "uint32")
666  m_id = mxUINT32_CLASS;
667  else if (cn == "int64")
668  m_id = mxINT64_CLASS;
669  else if (cn == "uint64")
670  m_id = mxUINT64_CLASS;
671 
672  return m_id;
673  }
674 
675  const char * get_class_name (void) const
676  {
677  if (! m_class_name)
678  {
679  std::string s = m_val.class_name ();
680  m_class_name = mxArray::strsave (s.c_str ());
681  }
682 
683  return m_class_name;
684  }
685 
686  // Not allowed.
688 
689  mxArray * get_property (mwIndex idx, const char *pname) const
690  {
691  mxArray *retval = nullptr;
692 
693  if (m_val.is_classdef_object ())
694  {
696 
697  if (ov_cdef)
698  {
699  octave_value pval = ov_cdef->get_property (idx, pname);
700 
701  if (pval.is_defined())
702  retval = new mxArray (m_interleaved, pval);
703  }
704  }
705 
706  return retval;
707  }
708 
709  void set_property (mwIndex idx, const char *pname, const mxArray *pval)
710  {
711  if (m_val.is_classdef_object ())
712  {
714 
715  if (ov_cdef)
716  ov_cdef->set_property (idx, pname, pval->as_octave_value ());
717  }
718  else
719  err_invalid_type ("set_property");
720  }
721 
722  CONST_MUTATION_METHOD (mxArray *, get_cell, (mwIndex), nullptr)
723 
724  // Not allowed.
726 
727  double get_scalar (void) const
728  {
729  if (m_val.issparse ())
730  {
731  // For sparse arrays, return the first non-zero value.
732  const void *m_data = m_val.mex_get_data ();
733  if (m_data == nullptr)
734  return 0.0;
735 
736  if (m_val.islogical ())
737  return *static_cast<const bool *> (m_data);
738  else if (m_val.isreal ())
739  return *static_cast<const double *> (m_data);
740  else // Complex type, only return real part
741  return *static_cast<const double *> (m_data);
742  }
743  else
744  return m_val.scalar_value (true);
745  }
746 
747  void * get_data (void) const
748  {
749  // Casting away const required for MEX interface.
750 
751  void *retval = const_cast<void *> (m_val.mex_get_data ());
752 
753  if (retval && (m_val.isreal () || m_interleaved))
754  {
755  maybe_mark_foreign (retval);
756  return retval;
757  }
758 
759  request_mutation ();
760  return nullptr;
761  }
762 
763  template <typename T>
764  T * get_data (mxClassID class_id, mxComplexity complexity) const
765  {
766  // Casting away const required for MEX interface.
767 
768  void *ptr = const_cast<void *> (m_val.mex_get_data (class_id, complexity));
769 
770  T *retval = static_cast<T *> (ptr);
771 
772  if (retval && (complexity == mxREAL || m_interleaved))
773  {
774  maybe_mark_foreign (retval);
775  return retval;
776  }
777 
778  request_mutation ();
779  return nullptr;
780  }
781 
782  GET_DATA_METHOD (mxDouble, get_doubles, mxDOUBLE_CLASS, mxREAL);
783 
784  GET_DATA_METHOD (mxSingle, get_singles, mxSINGLE_CLASS, mxREAL);
785 
786  GET_DATA_METHOD (mxInt8, get_int8s, mxINT8_CLASS, mxREAL);
787 
788  GET_DATA_METHOD (mxInt16, get_int16s, mxINT16_CLASS, mxREAL);
789 
790  GET_DATA_METHOD (mxInt32, get_int32s, mxINT32_CLASS, mxREAL);
791 
792  GET_DATA_METHOD (mxInt64, get_int64s, mxINT64_CLASS, mxREAL);
793 
794  GET_DATA_METHOD (mxUint8, get_uint8s, mxUINT8_CLASS, mxREAL);
795 
796  GET_DATA_METHOD (mxUint16, get_uint16s, mxUINT16_CLASS, mxREAL);
797 
798  GET_DATA_METHOD (mxUint32, get_uint32s, mxUINT32_CLASS, mxREAL);
799 
800  GET_DATA_METHOD (mxUint64, get_uint64s, mxUINT64_CLASS, mxREAL);
801 
802  GET_DATA_METHOD (mxComplexDouble, get_complex_doubles,
803  mxDOUBLE_CLASS, mxCOMPLEX);
804 
805  GET_DATA_METHOD (mxComplexSingle, get_complex_singles,
806  mxDOUBLE_CLASS, mxCOMPLEX);
807 
808 #if 0
809  /* We don't have these yet. */
810  GET_DATA_METHOD (mxComplexInt8 *, get_complex_int8s, (void), nullptr);
811 
812  GET_DATA_METHOD (mxComplexInt16 *, get_complex_int16s, (void), nullptr);
813 
814  GET_DATA_METHOD (mxComplexInt32 *, get_complex_int32s, (void), nullptr);
815 
816  GET_DATA_METHOD (mxComplexInt64 *, get_complex_int64s, (void), nullptr);
817 
818  GET_DATA_METHOD (mxComplexUint8 *, get_complex_uint8s, (void), nullptr);
819 
820  GET_DATA_METHOD (mxComplexUint16 *, get_complex_uint16s, (void), nullptr);
821 
822  GET_DATA_METHOD (mxComplexUint32 *, get_complex_uint32s, (void), nullptr);
823 
824  GET_DATA_METHOD (mxComplexUint64 *, get_complex_uint64s, (void), nullptr);
825 #endif
826 
827  void * get_imag_data (void) const
828  {
829  void *retval = nullptr;
830 
831  if (is_numeric () && isreal ())
832  retval = nullptr;
833  else
834  request_mutation ();
835 
836  return retval;
837  }
838 
839  // Not allowed.
841 
842  MUTATION_METHOD (int, set_doubles, (mxDouble *), 0)
843  MUTATION_METHOD (int, set_singles, (mxSingle *), 0)
844  MUTATION_METHOD (int, set_int8s, (mxInt8 *), 0)
845  MUTATION_METHOD (int, set_int16s, (mxInt16 *), 0)
846  MUTATION_METHOD (int, set_int32s, (mxInt32 *), 0)
847  MUTATION_METHOD (int, set_int64s, (mxInt64 *), 0)
848  MUTATION_METHOD (int, set_uint8s, (mxUint8 *), 0)
849  MUTATION_METHOD (int, set_uint16s, (mxUint16 *), 0)
850  MUTATION_METHOD (int, set_uint32s, (mxUint32 *), 0)
851  MUTATION_METHOD (int, set_uint64s, (mxUint64 *), 0)
852 
853  MUTATION_METHOD (int, set_complex_doubles, (mxComplexDouble *), 0)
854  MUTATION_METHOD (int, set_complex_singles, (mxComplexSingle *), 0)
855 #if 0
856  /* We don't have these yet. */
857  MUTATION_METHOD (int, set_complex_int8s, (mxComplexInt8 *), 0)
858  MUTATION_METHOD (int, set_complex_int16s, (mxComplexInt16 *), 0)
859  MUTATION_METHOD (int, set_complex_int32s, (mxComplexInt32 *), 0)
860  MUTATION_METHOD (int, set_complex_int64s, (mxComplexInt64 *), 0)
861  MUTATION_METHOD (int, set_complex_uint8s, (mxComplexUint8 *), 0)
862  MUTATION_METHOD (int, set_complex_uint16s, (mxComplexUint16 *), 0)
863  MUTATION_METHOD (int, set_complex_uint32s, (mxComplexUint32 *), 0)
864  MUTATION_METHOD (int, set_complex_uint64s, (mxComplexUint64 *), 0)
865 #endif
866 
867  // Not allowed.
869 
870  mwIndex * get_ir (void) const
871  {
872  // Casting away const required for MEX interface.
873 
874  octave_idx_type *ptr = const_cast<octave_idx_type *> (m_val.mex_get_ir ());
875  return static_cast<mwIndex *> (maybe_mark_foreign (ptr));
876  }
877 
878  mwIndex * get_jc (void) const
879  {
880  // Casting away const required for MEX interface.
881 
882  octave_idx_type *ptr = const_cast<octave_idx_type *> (m_val.mex_get_jc ());
883  return static_cast<mwIndex *> (maybe_mark_foreign (ptr));
884  }
885 
886  mwSize get_nzmax (void) const { return m_val.nzmax (); }
887 
888  // Not allowed.
890 
891  // Not allowed.
893 
894  // Not allowed.
896 
897  // Not allowed.
898  MUTATION_METHOD (int, add_field, (const char *), 0)
899 
900  // Not allowed.
902 
903  CONST_MUTATION_METHOD (mxArray *, get_field_by_number, (mwIndex, int), nullptr)
904 
905  // Not allowed.
907 
908  int get_number_of_fields (void) const { return m_val.nfields (); }
909 
910  CONST_MUTATION_METHOD (const char *, get_field_name_by_number, (int), nullptr)
911 
912  CONST_MUTATION_METHOD (int, get_field_number, (const char *), 0)
913 
914  int get_string (char *buf, mwSize buflen) const
915  {
916  int retval = 1;
917 
918  mwSize nel = get_number_of_elements ();
919 
920  if (m_val.is_string () && nel < buflen)
921  {
923 
924  const char *p = tmp.data ();
925 
926  for (mwIndex i = 0; i < nel; i++)
927  buf[i] = p[i];
928 
929  buf[nel] = 0;
930 
931  retval = 0;
932  }
933 
934  return retval;
935  }
936 
937  char * array_to_string (void) const
938  {
939  // FIXME: this is supposed to handle multi-byte character strings.
940 
941  char *buf = nullptr;
942 
943  if (m_val.is_string ())
944  {
945  mwSize nel = get_number_of_elements ();
946 
947  buf = static_cast<char *> (mxArray::malloc (nel + 1));
948 
949  if (buf)
950  {
952 
953  const char *p = tmp.data ();
954 
955  for (mwIndex i = 0; i < nel; i++)
956  buf[i] = p[i];
957 
958  buf[nel] = '\0';
959  }
960  }
961 
962  return buf;
963  }
964 
965  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
966  {
967  // Force m_ndims, n_dims to be cached.
968  get_dimensions ();
969 
970  return calc_single_subscript_internal (m_ndims, m_dims, nsubs, subs);
971  }
972 
973  std::size_t get_element_size (void) const
974  {
975  // Force m_id to be cached.
976  get_class_id ();
977 
978  switch (m_id)
979  {
980  case mxCELL_CLASS: return sizeof (mxArray *);
981  case mxSTRUCT_CLASS: return sizeof (mxArray *);
982  case mxLOGICAL_CLASS: return sizeof (mxLogical);
983  case mxCHAR_CLASS: return sizeof (mxChar);
984  case mxDOUBLE_CLASS: return get_numeric_element_size (sizeof (mxDouble));
985  case mxSINGLE_CLASS: return get_numeric_element_size (sizeof (mxSingle));
986  case mxINT8_CLASS: return get_numeric_element_size (sizeof (mxInt8));
987  case mxUINT8_CLASS: return get_numeric_element_size (sizeof (mxUint8));
988  case mxINT16_CLASS: return get_numeric_element_size (sizeof (mxInt16));
989  case mxUINT16_CLASS: return get_numeric_element_size (sizeof (mxUint16));
990  case mxINT32_CLASS: return get_numeric_element_size (sizeof (mxInt32));
991  case mxUINT32_CLASS: return get_numeric_element_size (sizeof (mxUint32));
992  case mxINT64_CLASS: return get_numeric_element_size (sizeof (mxInt64));
993  case mxUINT64_CLASS: return get_numeric_element_size (sizeof (mxUint64));
994  case mxFUNCTION_CLASS: return 0;
995  // FIXME: user-defined objects need their own class ID.
996  // What should they return, size of pointer?
997  default: return 0;
998  }
999  }
1000 
1001  bool mutation_needed (void) const { return m_mutate_flag; }
1002 
1003  void request_mutation (void) const
1004  {
1005  if (m_mutate_flag)
1006  panic_impossible ();
1007 
1008  m_mutate_flag = true;
1009  }
1010 
1011  mxArray * mutate (void) const { return as_mxArray (); }
1012 
1013  octave_value as_octave_value (void) const { return m_val; }
1014 
1015 protected:
1016 
1018  : mxArray_base (arg), m_val (arg.m_val), m_mutate_flag (arg.m_mutate_flag),
1020  m_ndims (arg.m_ndims),
1021  m_dims (m_ndims > 0
1022  ? static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize)))
1023  : nullptr)
1024  {
1025  if (m_dims)
1026  {
1027  for (mwIndex i = 0; i < m_ndims; i++)
1028  m_dims[i] = arg.m_dims[i];
1029  }
1030  }
1031 
1032 private:
1033 
1035 
1036  mutable bool m_mutate_flag;
1037 
1038  // Caching these does not cost much or lead to much duplicated
1039  // code. For other things, we just request mutation to a
1040  // Matlab-style mxArray object.
1041 
1042  mutable mxClassID m_id;
1043  mutable char *m_class_name;
1044  mutable mwSize m_ndims;
1045  mutable mwSize *m_dims;
1046 };
1047 
1048 // The base class for the Matlab-style representation, used to handle
1049 // things that are common to all Matlab-style objects.
1050 
1052 {
1053 public:
1054 
1055  // No assignment!
1056  // FIXME: should this be implemented?
1057  // Note that we *do* have a copy constructor.
1058 
1060 
1062  {
1063  mxFree (m_class_name);
1064  mxFree (m_dims);
1065  }
1066 
1067  int iscell (void) const { return m_id == mxCELL_CLASS; }
1068 
1069  int is_char (void) const { return m_id == mxCHAR_CLASS; }
1070 
1071  int is_complex (void) const { return 0; }
1072 
1073  int is_double (void) const { return m_id == mxDOUBLE_CLASS; }
1074 
1075  int is_function_handle (void) const { return m_id == mxFUNCTION_CLASS; }
1076 
1077  int is_int16 (void) const { return m_id == mxINT16_CLASS; }
1078 
1079  int is_int32 (void) const { return m_id == mxINT32_CLASS; }
1080 
1081  int is_int64 (void) const { return m_id == mxINT64_CLASS; }
1082 
1083  int is_int8 (void) const { return m_id == mxINT8_CLASS; }
1084 
1085  int is_logical (void) const { return m_id == mxLOGICAL_CLASS; }
1086 
1087  int is_numeric (void) const
1088  {
1089  return (m_id == mxDOUBLE_CLASS || m_id == mxSINGLE_CLASS
1090  || m_id == mxINT8_CLASS || m_id == mxUINT8_CLASS
1091  || m_id == mxINT16_CLASS || m_id == mxUINT16_CLASS
1092  || m_id == mxINT32_CLASS || m_id == mxUINT32_CLASS
1093  || m_id == mxINT64_CLASS || m_id == mxUINT64_CLASS);
1094  }
1095 
1096  int is_single (void) const { return m_id == mxSINGLE_CLASS; }
1097 
1098  int is_sparse (void) const { return 0; }
1099 
1100  int is_struct (void) const { return m_id == mxSTRUCT_CLASS; }
1101 
1102  int is_uint16 (void) const { return m_id == mxUINT16_CLASS; }
1103 
1104  int is_uint32 (void) const { return m_id == mxUINT32_CLASS; }
1105 
1106  int is_uint64 (void) const { return m_id == mxUINT64_CLASS; }
1107 
1108  int is_uint8 (void) const { return m_id == mxUINT8_CLASS; }
1109 
1110  int is_logical_scalar_true (void) const
1111  {
1112  return (is_logical_scalar ()
1113  && static_cast<mxLogical *> (get_data ())[0] != 0);
1114  }
1115 
1116  mwSize get_m (void) const { return m_dims[0]; }
1117 
1118  mwSize get_n (void) const
1119  {
1120  mwSize n = 1;
1121 
1122  for (mwSize i = m_ndims - 1 ; i > 0 ; i--)
1123  n *= m_dims[i];
1124 
1125  return n;
1126  }
1127 
1128  mwSize * get_dimensions (void) const { return m_dims; }
1129 
1130  mwSize get_number_of_dimensions (void) const { return m_ndims; }
1131 
1132  void set_m (mwSize m) { m_dims[0] = m; }
1133 
1134  void set_n (mwSize n) { m_dims[1] = n; }
1135 
1136  int set_dimensions (mwSize *dims, mwSize ndims)
1137  {
1138  m_ndims = ndims;
1139 
1140  mxFree (m_dims);
1141 
1142  if (m_ndims > 0)
1143  {
1144  m_dims
1145  = static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize)));
1146 
1147  if (m_dims == nullptr)
1148  return 1;
1149 
1150  for (int i = 0; i < m_ndims; i++)
1151  m_dims[i] = dims[i];
1152 
1153  return 0;
1154  }
1155  else
1156  {
1157  m_dims = nullptr;
1158  return 0;
1159  }
1160  }
1161 
1162  mwSize get_number_of_elements (void) const
1163  {
1164  mwSize retval = m_dims[0];
1165 
1166  for (mwIndex i = 1; i < m_ndims; i++)
1167  retval *= m_dims[i];
1168 
1169  return retval;
1170  }
1171 
1172  int isempty (void) const { return get_number_of_elements () == 0; }
1173 
1174  bool is_scalar (void) const
1175  {
1176  return m_ndims == 2 && m_dims[0] == 1 && m_dims[1] == 1;
1177  }
1178 
1179  mxClassID get_class_id (void) const { return m_id; }
1180 
1181  const char * get_class_name (void) const
1182  {
1183  switch (m_id)
1184  {
1185  case mxDOUBLE_CLASS: return "double";
1186  case mxSINGLE_CLASS: return "single";
1187  case mxCHAR_CLASS: return "char";
1188  case mxLOGICAL_CLASS: return "logical";
1189  case mxCELL_CLASS: return "cell";
1190  case mxSTRUCT_CLASS: return "struct";
1191  case mxFUNCTION_CLASS: return "function_handle";
1192  case mxINT8_CLASS: return "int8";
1193  case mxUINT8_CLASS: return "uint8";
1194  case mxINT16_CLASS: return "int16";
1195  case mxUINT16_CLASS: return "uint16";
1196  case mxINT32_CLASS: return "int32";
1197  case mxUINT32_CLASS: return "uint32";
1198  case mxINT64_CLASS: return "int64";
1199  case mxUINT64_CLASS: return "uint64";
1200  case mxUNKNOWN_CLASS: return "unknown";
1201  // FIXME: should return the classname of user-defined objects
1202  default: return "unknown";
1203  }
1204  }
1205 
1206  void set_class_name (const char *name)
1207  {
1208  mxFree (m_class_name);
1209  m_class_name = static_cast<char *> (mxArray::malloc (strlen (name) + 1));
1210  strcpy (m_class_name, name);
1211  }
1212 
1213  mxArray * get_cell (mwIndex /*idx*/) const
1214  {
1215  err_invalid_type ("get_cell");
1216  }
1217 
1218  void set_cell (mwIndex /*idx*/, mxArray * /*val*/)
1219  {
1220  err_invalid_type ("set_cell");
1221  }
1222 
1223  double get_scalar (void) const
1224  {
1225  err_invalid_type ("get_scalar");
1226  }
1227 
1228  void * get_data (void) const
1229  {
1230  err_invalid_type ("get_data");
1231  }
1232 
1233  mxDouble * get_doubles (void) const
1234  {
1235  err_invalid_type ("get_doubles");
1236  }
1237 
1238  mxSingle * get_singles (void) const
1239  {
1240  err_invalid_type ("get_singles");
1241  }
1242 
1243  mxInt8 * get_int8s (void) const
1244  {
1245  err_invalid_type ("get_int8s");
1246  }
1247 
1248  mxInt16 * get_int16s (void) const
1249  {
1250  err_invalid_type ("get_int16s");
1251  }
1252 
1253  mxInt32 * get_int32s (void) const
1254  {
1255  err_invalid_type ("get_int32s");
1256  }
1257 
1258  mxInt64 * get_int64s (void) const
1259  {
1260  err_invalid_type ("get_int64s");
1261  }
1262 
1263  mxUint8 * get_uint8s (void) const
1264  {
1265  err_invalid_type ("get_uint8s");
1266  }
1267 
1268  mxUint16 * get_uint16s (void) const
1269  {
1270  err_invalid_type ("get_uint16s");
1271  }
1272 
1273  mxUint32 * get_uint32s (void) const
1274  {
1275  err_invalid_type ("get_uint32s");
1276  }
1277 
1278  mxUint64 * get_uint64s (void) const
1279  {
1280  err_invalid_type ("get_uint64s");
1281  }
1282 
1283  mxComplexDouble * get_complex_doubles (void) const
1284  {
1285  err_invalid_type ("get_complex_doubles");
1286  }
1287 
1288  mxComplexSingle * get_complex_singles (void) const
1289  {
1290  err_invalid_type ("get_complex_singles");
1291  }
1292 
1293 #if 0
1294  /* We don't have these yet. */
1295  mxComplexInt8 * get_complex_int8s (void) const
1296  {
1297  err_invalid_type ("get_complex_int8s");
1298  }
1299 
1300  mxComplexInt16 * get_complex_int16s (void) const
1301  {
1302  err_invalid_type ("get_complex_int16s");
1303  }
1304 
1305  mxComplexInt32 * get_complex_int32s (void) const
1306  {
1307  err_invalid_type ("get_complex_int32s");
1308  }
1309 
1310  mxComplexInt64 * get_complex_int64s (void) const
1311  {
1312  err_invalid_type ("get_complex_int64s");
1313  }
1314 
1315  mxComplexUint8 * get_complex_uint8s (void) const
1316  {
1317  err_invalid_type ("get_complex_uint8s");
1318  }
1319 
1320  mxComplexUint16 * get_complex_uint16s (void) const
1321  {
1322  err_invalid_type ("get_complex_uint16s");
1323  }
1324 
1325  mxComplexUint32 * get_complex_uint32s (void) const
1326  {
1327  err_invalid_type ("get_complex_uint32s");
1328  }
1329 
1330  mxComplexUint64 * get_complex_uint64s (void) const
1331  {
1332  err_invalid_type ("get_complex_uint64s");
1333  }
1334 #endif
1335 
1336  void * get_imag_data (void) const
1337  {
1338  err_invalid_type ("get_imag_data");
1339  }
1340 
1341  void set_data (void * /*pr*/)
1342  {
1343  err_invalid_type ("set_data");
1344  }
1345 
1346  int set_doubles (mxDouble *)
1347  {
1348  err_invalid_type ("set_doubles");
1349  }
1350 
1351  int set_singles (mxSingle *)
1352  {
1353  err_invalid_type ("set_singles");
1354  }
1355 
1356  int set_int8s (mxInt8 *)
1357  {
1358  err_invalid_type ("set_int8s");
1359  }
1360 
1361  int set_int16s (mxInt16 *)
1362  {
1363  err_invalid_type ("set_int16s");
1364  }
1365 
1366  int set_int32s (mxInt32 *)
1367  {
1368  err_invalid_type ("set_int32s");
1369  }
1370 
1371  int set_int64s (mxInt64 *)
1372  {
1373  err_invalid_type ("set_int64s");
1374  }
1375 
1376  int set_uint8s (mxUint8 *)
1377  {
1378  err_invalid_type ("set_uint8s");
1379  }
1380 
1381  int set_uint16s (mxUint16 *)
1382  {
1383  err_invalid_type ("set_uint16s");
1384  }
1385 
1386  int set_uint32s (mxUint32 *)
1387  {
1388  err_invalid_type ("set_uint32s");
1389  }
1390 
1391  int set_uint64s (mxUint64 *)
1392  {
1393  err_invalid_type ("set_uint64s");
1394  }
1395 
1396  int set_complex_doubles (mxComplexDouble *)
1397  {
1398  err_invalid_type ("set_complex_doubles");
1399  }
1400 
1401  int set_complex_singles (mxComplexSingle *)
1402  {
1403  err_invalid_type ("set_complex_singles");
1404  }
1405 
1406 #if 0
1407  /* We don't have these yet. */
1408  int set_complex_int8s (mxComplexInt8 *)
1409  {
1410  err_invalid_type ("set_complex_int8s");
1411  }
1412 
1413  int set_complex_int16s (mxComplexInt16 *)
1414  {
1415  err_invalid_type ("set_complex_int16s");
1416  }
1417 
1418  int set_complex_int32s (mxComplexInt32 *)
1419  {
1420  err_invalid_type ("set_complex_int32s");
1421  }
1422 
1423  int set_complex_int64s (mxComplexInt64 *)
1424  {
1425  err_invalid_type ("set_complex_int64s");
1426  }
1427 
1428  int set_complex_uint8s (mxComplexUint8 *)
1429  {
1430  err_invalid_type ("set_complex_uint8s");
1431  }
1432 
1433  int set_complex_uint16s (mxComplexUint16 *)
1434  {
1435  err_invalid_type ("set_complex_uint16s");
1436  }
1437 
1438  int set_complex_uint32s (mxComplexUint32 *)
1439  {
1440  err_invalid_type ("set_complex_uint32s");
1441  }
1442 
1443  int set_complex_uint64s (mxComplexUint64 *)
1444  {
1445  err_invalid_type ("set_complex_uint64s");
1446  }
1447 #endif
1448 
1449  void set_imag_data (void * /*pi*/)
1450  {
1451  err_invalid_type ("set_imag_data");
1452  }
1453 
1454  mwIndex * get_ir (void) const
1455  {
1456  err_invalid_type ("get_ir");
1457  }
1458 
1459  mwIndex * get_jc (void) const
1460  {
1461  err_invalid_type ("get_jc");
1462  }
1463 
1464  mwSize get_nzmax (void) const
1465  {
1466  err_invalid_type ("get_nzmax");
1467  }
1468 
1469  void set_ir (mwIndex * /*ir*/)
1470  {
1471  err_invalid_type ("set_ir");
1472  }
1473 
1474  void set_jc (mwIndex * /*jc*/)
1475  {
1476  err_invalid_type ("set_jc");
1477  }
1478 
1479  void set_nzmax (mwSize /*nzmax*/)
1480  {
1481  err_invalid_type ("set_nzmax");
1482  }
1483 
1484  int add_field (const char * /*key*/)
1485  {
1486  err_invalid_type ("add_field");
1487  }
1488 
1489  void remove_field (int /*key_num*/)
1490  {
1491  err_invalid_type ("remove_field");
1492  }
1493 
1494  mxArray * get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
1495  {
1496  err_invalid_type ("get_field_by_number");
1497  }
1498 
1499  void set_field_by_number (mwIndex /*index*/, int /*key_num*/,
1500  mxArray * /*val*/)
1501  {
1502  err_invalid_type ("set_field_by_number");
1503  }
1504 
1505  int get_number_of_fields (void) const
1506  {
1507  err_invalid_type ("get_number_of_fields");
1508  }
1509 
1510  const char * get_field_name_by_number (int /*key_num*/) const
1511  {
1512  err_invalid_type ("get_field_name_by_number");
1513  }
1514 
1515  int get_field_number (const char * /*key*/) const
1516  {
1517  return -1;
1518  }
1519 
1520  int get_string (char * /*buf*/, mwSize /*buflen*/) const
1521  {
1522  err_invalid_type ("get_string");
1523  }
1524 
1525  char * array_to_string (void) const
1526  {
1527  err_invalid_type ("array_to_string");
1528  }
1529 
1530  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
1531  {
1532  return calc_single_subscript_internal (m_ndims, m_dims, nsubs, subs);
1533  }
1534 
1535  std::size_t get_element_size (void) const
1536  {
1537  switch (m_id)
1538  {
1539  case mxCELL_CLASS: return sizeof (mxArray *);
1540  case mxSTRUCT_CLASS: return sizeof (mxArray *);
1541  case mxLOGICAL_CLASS: return sizeof (mxLogical);
1542  case mxCHAR_CLASS: return sizeof (mxChar);
1543  case mxDOUBLE_CLASS: return get_numeric_element_size (sizeof (mxDouble));
1544  case mxSINGLE_CLASS: return get_numeric_element_size (sizeof (mxSingle));
1545  case mxINT8_CLASS: return get_numeric_element_size (sizeof (mxInt8));
1546  case mxUINT8_CLASS: return get_numeric_element_size (sizeof (mxUint8));
1547  case mxINT16_CLASS: return get_numeric_element_size (sizeof (mxInt16));
1548  case mxUINT16_CLASS: return get_numeric_element_size (sizeof (mxUint16));
1549  case mxINT32_CLASS: return get_numeric_element_size (sizeof (mxInt32));
1550  case mxUINT32_CLASS: return get_numeric_element_size (sizeof (mxUint32));
1551  case mxINT64_CLASS: return get_numeric_element_size (sizeof (mxInt64));
1552  case mxUINT64_CLASS: return get_numeric_element_size (sizeof (mxUint64));
1553  case mxFUNCTION_CLASS: return 0;
1554  // FIXME: user-defined objects need their own class ID.
1555  // What should they return, size of pointer?
1556  default: return 0;
1557  }
1558  }
1559 
1560 protected:
1561 
1562  mxArray_matlab (bool interleaved, mxClassID id = mxUNKNOWN_CLASS)
1563  : mxArray_base (interleaved), m_class_name (nullptr), m_id (id),
1564  m_ndims (0), m_dims (nullptr)
1565  { }
1566 
1567  mxArray_matlab (bool interleaved, mxClassID id, mwSize ndims,
1568  const mwSize *dims)
1569  : mxArray_base (interleaved), m_class_name (nullptr), m_id (id),
1570  m_ndims (ndims < 2 ? 2 : ndims),
1571  m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))
1572  {
1573  if (ndims == 0)
1574  {
1575  m_dims[0] = 0;
1576  m_dims[1] = 0;
1577  }
1578  else if (ndims < 2)
1579  {
1580  m_dims[0] = 1;
1581  m_dims[1] = 1;
1582  }
1583 
1584  for (mwIndex i = 0; i < ndims; i++)
1585  m_dims[i] = dims[i];
1586 
1587  for (mwIndex i = m_ndims - 1; i > 1; i--)
1588  {
1589  if (m_dims[i] == 1)
1590  m_ndims--;
1591  else
1592  break;
1593  }
1594  }
1595 
1596  mxArray_matlab (bool interleaved, mxClassID id, const dim_vector& dv)
1597  : mxArray_base (interleaved), m_class_name (nullptr), m_id (id),
1598  m_ndims (dv.ndims ()),
1599  m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))
1600  {
1601  for (mwIndex i = 0; i < m_ndims; i++)
1602  m_dims[i] = dv(i);
1603 
1604  for (mwIndex i = m_ndims - 1; i > 1; i--)
1605  {
1606  if (m_dims[i] == 1)
1607  m_ndims--;
1608  else
1609  break;
1610  }
1611  }
1612 
1613  mxArray_matlab (bool interleaved, mxClassID id, mwSize m, mwSize n)
1614  : mxArray_base (interleaved), m_class_name (nullptr), m_id (id),
1615  m_ndims (2),
1616  m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))
1617  {
1618  m_dims[0] = m;
1619  m_dims[1] = n;
1620  }
1621 
1624  m_id (val.m_id), m_ndims (val.m_ndims),
1625  m_dims (static_cast<mwSize *> (mxArray::malloc (m_ndims * sizeof (mwSize))))
1626  {
1627  for (mwIndex i = 0; i < m_ndims; i++)
1628  m_dims[i] = val.m_dims[i];
1629  }
1630 
1631  dim_vector
1632  dims_to_dim_vector (void) const
1633  {
1634  mwSize nd = get_number_of_dimensions ();
1635 
1636  mwSize *d = get_dimensions ();
1637 
1638  dim_vector dv;
1639  dv.resize (nd);
1640 
1641  for (mwIndex i = 0; i < nd; i++)
1642  dv(i) = d[i];
1643 
1644  return dv;
1645  }
1646 
1647 private:
1648 
1650 
1651  mxClassID m_id;
1652 
1653  mwSize m_ndims;
1654  mwSize *m_dims;
1655 };
1656 
1657 
1658 // Matlab-style numeric, character, and logical data.
1659 
1661 {
1662 public:
1663 
1664  mxArray_base_full (bool interleaved, mxClassID id, mwSize ndims,
1665  const mwSize *dims, bool init = true)
1666  : mxArray_matlab (interleaved, id, ndims, dims),
1667  m_pr (mxArray::alloc (init, get_number_of_elements (), get_element_size ()))
1668  { }
1669 
1670  mxArray_base_full (bool interleaved, mxClassID id, const dim_vector& dv)
1671  : mxArray_matlab (interleaved, id, dv),
1673  { }
1674 
1675  mxArray_base_full (bool interleaved, mxClassID id, mwSize m, mwSize n,
1676  bool init = true)
1677  : mxArray_matlab (interleaved, id, m, n),
1678  m_pr (mxArray::alloc (init, get_number_of_elements (), get_element_size ()))
1679  { }
1680 
1681  mxArray_base_full (bool interleaved, mxClassID id, double val)
1682  : mxArray_matlab (interleaved, id, 1, 1),
1684  {
1685  double *dpr = static_cast<double *> (m_pr);
1686  dpr[0] = val;
1687  }
1688 
1689  mxArray_base_full (bool interleaved, mxClassID id, mxLogical val)
1690  : mxArray_matlab (interleaved, id, 1, 1),
1692  {
1693  mxLogical *lpr = static_cast<mxLogical *> (m_pr);
1694  lpr[0] = val;
1695  }
1696 
1697  mxArray_base_full (bool interleaved, const char *str)
1698  : mxArray_matlab (interleaved, mxCHAR_CLASS,
1699  str ? (strlen (str) ? 1 : 0) : 0,
1700  str ? strlen (str) : 0),
1702  {
1703  mxChar *cpr = static_cast<mxChar *> (m_pr);
1704  mwSize nel = get_number_of_elements ();
1705  for (mwIndex i = 0; i < nel; i++)
1706  cpr[i] = str[i];
1707  }
1708 
1709  // FIXME: ???
1710  mxArray_base_full (bool interleaved, mwSize m, const char **str)
1711  : mxArray_matlab (interleaved, mxCHAR_CLASS, m, max_str_len (m, str)),
1713  {
1714  mxChar *cpr = static_cast<mxChar *> (m_pr);
1715 
1716  mwSize *dv = get_dimensions ();
1717 
1718  mwSize nc = dv[1];
1719 
1720  for (mwIndex j = 0; j < m; j++)
1721  {
1722  const char *ptr = str[j];
1723 
1724  std::size_t tmp_len = strlen (ptr);
1725 
1726  for (std::size_t i = 0; i < tmp_len; i++)
1727  cpr[m*i+j] = static_cast<mxChar> (ptr[i]);
1728 
1729  for (std::size_t i = tmp_len; i < static_cast<std::size_t> (nc); i++)
1730  cpr[m*i+j] = static_cast<mxChar> (' ');
1731  }
1732  }
1733 
1734  // No assignment! FIXME: should this be implemented? Note that we
1735  // do have a copy constructor.
1736 
1738 
1739  mxArray_base * dup (void) const
1740  {
1741  return new mxArray_base_full (*this);
1742  }
1743 
1745  {
1746  mxFree (m_pr);
1747  }
1748 
1749  double get_scalar (void) const
1750  {
1751  // FIXME: how does this work for interleaved complex arrays?
1752 
1753  double retval = 0;
1754 
1755  switch (get_class_id ())
1756  {
1757  case mxDOUBLE_CLASS:
1758  retval = *(static_cast<double *> (m_pr));
1759  break;
1760 
1761  case mxSINGLE_CLASS:
1762  retval = *(static_cast<float *> (m_pr));
1763  break;
1764 
1765  case mxCHAR_CLASS:
1766  retval = *(static_cast<mxChar *> (m_pr));
1767  break;
1768 
1769  case mxLOGICAL_CLASS:
1770  retval = *(static_cast<bool *> (m_pr));
1771  break;
1772 
1773  case mxINT8_CLASS:
1774  retval = *(static_cast<int8_t *> (m_pr));
1775  break;
1776 
1777  case mxUINT8_CLASS:
1778  retval = *(static_cast<uint8_t *> (m_pr));
1779  break;
1780 
1781  case mxINT16_CLASS:
1782  retval = *(static_cast<int16_t *> (m_pr));
1783  break;
1784 
1785  case mxUINT16_CLASS:
1786  retval = *(static_cast<uint16_t *> (m_pr));
1787  break;
1788 
1789  case mxINT32_CLASS:
1790  retval = *(static_cast<int32_t *> (m_pr));
1791  break;
1792 
1793  case mxUINT32_CLASS:
1794  retval = *(static_cast<uint32_t *> (m_pr));
1795  break;
1796 
1797  case mxINT64_CLASS:
1798  retval = *(static_cast<int64_t *> (m_pr));
1799  break;
1800 
1801  case mxUINT64_CLASS:
1802  retval = *(static_cast<uint64_t *> (m_pr));
1803  break;
1804 
1805  default:
1806  panic_impossible ();
1807  }
1808 
1809  return retval;
1810  }
1811 
1812  void * get_data (void) const { return m_pr; }
1813 
1814  void set_data (void *pr) { m_pr = pr; }
1815 
1816  // The typed get and set functions only work for interleaved data but
1817  // they are defined here because this class owns PR. There are
1818  // definitions in the mxArray_separate_full class that override these
1819  // functions.
1820 
1821  mxDouble * get_doubles (void) const
1822  {
1823  return static_cast<mxDouble *> (m_pr);
1824  }
1825 
1826  mxSingle * get_singles (void) const
1827  {
1828  return static_cast<mxSingle *> (m_pr);
1829  }
1830 
1831  mxInt8 * get_int8s (void) const
1832  {
1833  return static_cast<mxInt8 *> (m_pr);
1834  }
1835 
1836  mxInt16 * get_int16s (void) const
1837  {
1838  return static_cast<mxInt16 *> (m_pr);
1839  }
1840 
1841  mxInt32 * get_int32s (void) const
1842  {
1843  return static_cast<mxInt32 *> (m_pr);
1844  }
1845 
1846  mxInt64 * get_int64s (void) const
1847  {
1848  return static_cast<mxInt64 *> (m_pr);
1849  }
1850 
1851  mxUint8 * get_uint8s (void) const
1852  {
1853  return static_cast<mxUint8 *> (m_pr);
1854  }
1855 
1856  mxUint16 * get_uint16s (void) const
1857  {
1858  return static_cast<mxUint16 *> (m_pr);
1859  }
1860 
1861  mxUint32 * get_uint32s (void) const
1862  {
1863  return static_cast<mxUint32 *> (m_pr);
1864  }
1865 
1866  mxUint64 * get_uint64s (void) const
1867  {
1868  return static_cast<mxUint64 *> (m_pr);
1869  }
1870 
1871  mxComplexDouble * get_complex_doubles (void) const
1872  {
1873  return static_cast<mxComplexDouble *> (m_pr);
1874  }
1875 
1876  mxComplexSingle * get_complex_singles (void) const
1877  {
1878  return static_cast<mxComplexSingle *> (m_pr);
1879  }
1880 
1881 #if 0
1882  // We don't have these data types.
1883 
1884  int get_complex_int8s (mxComplexInt8 *d)
1885  {
1886  m_pr = d;
1887  return 0;
1888  }
1889 
1890  int get_complex_int16s (mxComplexInt16 *d)
1891  {
1892  m_pr = d;
1893  return 0;
1894  }
1895 
1896  int get_complex_int32s (mxComplexInt32 *d)
1897  {
1898  m_pr = d;
1899  return 0;
1900  }
1901 
1902  int get_complex_int64s (mxComplexInt64 *d)
1903  {
1904  m_pr = d;
1905  return 0;
1906  }
1907 
1908  int get_complex_uint8s (mxComplexUint8 *d)
1909  {
1910  m_pr = d;
1911  return 0;
1912  }
1913 
1914  int get_complex_uint16s (mxComplexUint16 *d)
1915  {
1916  m_pr = d;
1917  return 0;
1918  }
1919 
1920  int get_complex_uint32s (mxComplexUint32 *d)
1921  {
1922  m_pr = d;
1923  return 0;
1924  }
1925 
1926  int get_complex_uint64s (mxComplexUint64 *d)
1927  {
1928  m_pr = d;
1929  return 0;
1930  }
1931 #endif
1932 
1933  int set_doubles (mxDouble *d)
1934  {
1935  m_pr = d;
1936  return 0;
1937  }
1938 
1939  int set_singles (mxSingle *d)
1940  {
1941  m_pr = d;
1942  return 0;
1943  }
1944 
1945  int set_int8s (mxInt8 *d)
1946  {
1947  m_pr = d;
1948  return 0;
1949  }
1950 
1951  int set_int16s (mxInt16 *d)
1952  {
1953  m_pr = d;
1954  return 0;
1955  }
1956 
1957  int set_int32s (mxInt32 *d)
1958  {
1959  m_pr = d;
1960  return 0;
1961  }
1962 
1963  int set_int64s (mxInt64 *d)
1964  {
1965  m_pr = d;
1966  return 0;
1967  }
1968 
1969  int set_uint8s (mxUint8 *d)
1970  {
1971  m_pr = d;
1972  return 0;
1973  }
1974 
1975  int set_uint16s (mxUint16 *d)
1976  {
1977  m_pr = d;
1978  return 0;
1979  }
1980 
1981  int set_uint32s (mxUint32 *d)
1982  {
1983  m_pr = d;
1984  return 0;
1985  }
1986 
1987  int set_uint64s (mxUint64 *d)
1988  {
1989  m_pr = d;
1990  return 0;
1991  }
1992 
1993  int set_complex_doubles (mxComplexDouble *d)
1994  {
1995  m_pr = d;
1996  return 0;
1997  }
1998 
1999  int set_complex_singles (mxComplexSingle *d)
2000  {
2001  m_pr = d;
2002  return 0;
2003  }
2004 
2005 #if 0
2006  // We don't have these data types.
2007 
2008  int set_complex_int8s (mxComplexInt8 *d)
2009  {
2010  m_pr = d;
2011  return 0;
2012  }
2013 
2014  int set_complex_int16s (mxComplexInt16 *d)
2015  {
2016  m_pr = d;
2017  return 0;
2018  }
2019 
2020  int set_complex_int32s (mxComplexInt32 *d)
2021  {
2022  m_pr = d;
2023  return 0;
2024  }
2025 
2026  int set_complex_int64s (mxComplexInt64 *d)
2027  {
2028  m_pr = d;
2029  return 0;
2030  }
2031 
2032  int set_complex_uint8s (mxComplexUint8 *d)
2033  {
2034  m_pr = d;
2035  return 0;
2036  }
2037 
2038  int set_complex_uint16s (mxComplexUint16 *d)
2039  {
2040  m_pr = d;
2041  return 0;
2042  }
2043 
2044  int set_complex_uint32s (mxComplexUint32 *d)
2045  {
2046  m_pr = d;
2047  return 0;
2048  }
2049 
2050  int set_complex_uint64s (mxComplexUint64 *d)
2051  {
2052  m_pr = d;
2053  return 0;
2054  }
2055 #endif
2056 
2057  int get_string (char *buf, mwSize buflen) const
2058  {
2059  int retval = 0;
2060 
2061  mwSize nel = get_number_of_elements ();
2062 
2063  if (! (nel < buflen))
2064  {
2065  retval = 1;
2066  if (buflen > 0)
2067  nel = buflen-1;
2068  }
2069 
2070  if (nel < buflen)
2071  {
2072  mxChar *ptr = static_cast<mxChar *> (m_pr);
2073 
2074  for (mwIndex i = 0; i < nel; i++)
2075  buf[i] = static_cast<char> (ptr[i]);
2076 
2077  buf[nel] = 0;
2078  }
2079 
2080  return retval;
2081  }
2082 
2083  char * array_to_string (void) const
2084  {
2085  // FIXME: this is supposed to handle multi-byte character strings.
2086 
2087  mwSize nel = get_number_of_elements ();
2088 
2089  char *buf = static_cast<char *> (mxArray::malloc (nel + 1));
2090 
2091  if (buf)
2092  {
2093  mxChar *ptr = static_cast<mxChar *> (m_pr);
2094 
2095  for (mwIndex i = 0; i < nel; i++)
2096  buf[i] = static_cast<char> (ptr[i]);
2097 
2098  buf[nel] = '\0';
2099  }
2100 
2101  return buf;
2102  }
2103 
2105  {
2106  octave_value retval;
2107 
2109 
2110  switch (get_class_id ())
2111  {
2112  case mxDOUBLE_CLASS:
2113  return (is_complex ()
2114  ? fp_to_ov<Complex> (dv) : fp_to_ov<double> (dv));
2115 
2116  case mxSINGLE_CLASS:
2117  return (is_complex ()
2118  ? fp_to_ov<FloatComplex> (dv) : fp_to_ov<float> (dv));
2119 
2120  case mxCHAR_CLASS:
2121  return int_to_ov<mxChar, charNDArray, char> (dv);
2122 
2123  case mxLOGICAL_CLASS:
2124  return int_to_ov<mxLogical, boolNDArray, bool> (dv);
2125 
2126  case mxINT8_CLASS:
2127  return int_to_ov<int8_t, int8NDArray, octave_int8> (dv);
2128 
2129  case mxUINT8_CLASS:
2130  return int_to_ov<uint8_t, uint8NDArray, octave_uint8> (dv);
2131 
2132  case mxINT16_CLASS:
2133  return int_to_ov<int16_t, int16NDArray, octave_int16> (dv);
2134 
2135  case mxUINT16_CLASS:
2136  return int_to_ov<uint16_t, uint16NDArray, octave_uint16> (dv);
2137 
2138  case mxINT32_CLASS:
2139  return int_to_ov<int32_t, int32NDArray, octave_int32> (dv);
2140 
2141  case mxUINT32_CLASS:
2142  return int_to_ov<uint32_t, uint32NDArray, octave_uint32> (dv);
2143 
2144  case mxINT64_CLASS:
2145  return int_to_ov<int64_t, int64NDArray, octave_int64> (dv);
2146 
2147  case mxUINT64_CLASS:
2148  return int_to_ov<uint64_t, uint64NDArray, octave_uint64> (dv);
2149 
2150  default:
2151  panic_impossible ();
2152  }
2153 
2154  return retval;
2155  }
2156 
2157 protected:
2158 
2160  : mxArray_matlab (val),
2162  {
2163  if (m_pr)
2164  memcpy (m_pr, val.m_pr, get_number_of_elements () * get_element_size ());
2165  }
2166 
2167  template <typename ELT_T>
2168  octave_value
2169  fp_to_ov (const dim_vector& dv) const
2170  {
2171  octave_value retval;
2172 
2173  ELT_T *ppr = static_cast<ELT_T *> (m_pr);
2174 
2175 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
2176 
2177  if (current_mx_memory_resource == &the_mx_deleting_memory_resource)
2178  {
2179  octave::unwind_action act ([=] () { maybe_disown_ptr (m_pr); });
2180 
2181  return octave_value (Array<ELT_T> (ppr, dv, current_mx_memory_resource));
2182  }
2183  else
2184  return octave_value (Array<ELT_T> (ppr, dv, current_mx_memory_resource));
2185 
2186 #else
2187 
2188  // Copy data instead of allowing the octave_value object to borrow
2189  // the mxArray object data.
2190 
2191  Array<ELT_T> val (dv);
2192 
2193  ELT_T *ptr = val.fortran_vec ();
2194 
2195  mwSize nel = get_number_of_elements ();
2196 
2197  for (mwIndex i = 0; i < nel; i++)
2198  ptr[i] = ppr[i];
2199 
2200  return octave_value (val);
2201 
2202 #endif
2203  }
2204 
2205  template <typename ELT_T, typename ARRAY_T, typename ARRAY_ELT_T>
2206  octave_value
2207  int_to_ov (const dim_vector& dv) const
2208  {
2209  if (is_complex ())
2210  error ("complex integer types are not supported");
2211 
2212  ELT_T *ppr = static_cast<ELT_T *> (m_pr);
2213 
2214 #if 0 && defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
2215 
2216  // FIXME: Currently not allowed because we don't have the necessary
2217  // constructors for integer arrays.
2218 
2219  octave::unwind_action act ([=] () { maybe_disown_ptr (m_pr); });
2220 
2221  return ARRAY_T (ppr, dv, current_mx_memory_resource);
2222 
2223 #else
2224 
2225  // Copy data instead of allowing the octave_value object to borrow
2226  // the mxArray object data.
2227 
2228  ARRAY_T val (dv);
2229 
2230  ARRAY_ELT_T *ptr = val.fortran_vec ();
2231 
2232  mwSize nel = get_number_of_elements ();
2233 
2234  for (mwIndex i = 0; i < nel; i++)
2235  ptr[i] = ppr[i];
2236 
2237  return octave_value (val);
2238 
2239 #endif
2240  }
2241 
2242 protected:
2243 
2244  // If using interleaved complex storage, this is the pointer to data
2245  // (real, complex, or logical). Otherwise, it is the pointer to the
2246  // real part of the data.
2247  void *m_pr;
2248 };
2249 
2251 {
2252 public:
2253 
2254  mxArray_interleaved_full (mxClassID id, mwSize ndims, const mwSize *dims,
2255  mxComplexity flag = mxREAL, bool init = true)
2256  : mxArray_base_full (true, id, ndims, dims, init),
2257  m_complex (flag == mxCOMPLEX)
2258  { }
2259 
2260  mxArray_interleaved_full (mxClassID id, const dim_vector& dv,
2261  mxComplexity flag = mxREAL)
2262  : mxArray_base_full (true, id, dv),
2263  m_complex (flag == mxCOMPLEX)
2264  { }
2265 
2266  mxArray_interleaved_full (mxClassID id, mwSize m, mwSize n,
2267  mxComplexity flag = mxREAL, bool init = true)
2268  : mxArray_base_full (true, id, m, n, init),
2269  m_complex (flag == mxCOMPLEX)
2270  { }
2271 
2272  mxArray_interleaved_full (mxClassID id, double val)
2273  : mxArray_base_full (true, id, val), m_complex (false)
2274  { }
2275 
2276  mxArray_interleaved_full (mxClassID id, mxLogical val)
2277  : mxArray_base_full (true, id, val), m_complex (false)
2278  { }
2279 
2280  mxArray_interleaved_full (const char *str)
2281  : mxArray_base_full (true, str), m_complex (false)
2282  { }
2283 
2284  // FIXME: ???
2285  mxArray_interleaved_full (mwSize m, const char **str)
2286  : mxArray_base_full (true, m, str), m_complex (false)
2287  { }
2288 
2289  // No assignment! FIXME: should this be implemented? Note that we
2290  // do have a copy constructor.
2291 
2293 
2294  mxArray_base * dup (void) const
2295  {
2296  return new mxArray_interleaved_full (*this);
2297  }
2298 
2299  ~mxArray_interleaved_full (void) = default;
2300 
2301  int is_complex (void) const { return m_complex; }
2302 
2303  void * get_imag_data (void) const { panic_impossible (); }
2304 
2305  void set_imag_data (void */*pi*/) { panic_impossible (); }
2306 
2307 protected:
2308 
2310  : mxArray_base_full (val), m_complex (val.m_complex)
2311  { }
2312 
2313  // Flag to identify complex object.
2315 };
2316 
2318 {
2319 public:
2320 
2321  mxArray_separate_full (mxClassID id, mwSize ndims, const mwSize *dims,
2322  mxComplexity flag = mxREAL, bool init = true)
2323  : mxArray_base_full (false, id, ndims, dims, init),
2324  m_pi (flag == mxCOMPLEX
2325  ? mxArray::alloc (init, get_number_of_elements (), get_element_size ())
2326  : nullptr)
2327  { }
2328 
2329  mxArray_separate_full (mxClassID id, const dim_vector& dv,
2330  mxComplexity flag = mxREAL)
2331  : mxArray_base_full (false, id, dv),
2332  m_pi (flag == mxCOMPLEX
2334  : nullptr)
2335  { }
2336 
2337  mxArray_separate_full (mxClassID id, mwSize m, mwSize n,
2338  mxComplexity flag = mxREAL, bool init = true)
2339  : mxArray_base_full (false, id, m, n, init),
2340  m_pi (flag == mxCOMPLEX
2341  ? (mxArray::alloc (init, get_number_of_elements (), get_element_size ()))
2342  : nullptr)
2343  { }
2344 
2345  mxArray_separate_full (mxClassID id, double val)
2346  : mxArray_base_full (false, id, val), m_pi (nullptr)
2347  { }
2348 
2349  mxArray_separate_full (mxClassID id, mxLogical val)
2350  : mxArray_base_full (false, id, val), m_pi (nullptr)
2351  { }
2352 
2353  mxArray_separate_full (const char *str)
2354  : mxArray_base_full (false, str), m_pi (nullptr)
2355  { }
2356 
2357  // FIXME: ???
2358  mxArray_separate_full (mwSize m, const char **str)
2359  : mxArray_base_full (false, m, str), m_pi (nullptr)
2360  { }
2361 
2362  // No assignment! FIXME: should this be implemented? Note that we
2363  // do have a copy constructor.
2364 
2366 
2367  mxArray_base * dup (void) const
2368  {
2369  return new mxArray_separate_full (*this);
2370  }
2371 
2373  {
2374  mxFree (m_pi);
2375  }
2376 
2377  int is_complex (void) const { return m_pi != nullptr; }
2378 
2379  void * get_imag_data (void) const { return m_pi; }
2380 
2381  void set_imag_data (void *pi) { m_pi = pi; }
2382 
2383  mxDouble * get_doubles (void) const { panic_impossible (); }
2384  mxSingle * get_singles (void) const { panic_impossible (); }
2385  mxInt8 * get_int8s (void) const { panic_impossible (); }
2386  mxInt16 * get_int16s (void) const { panic_impossible (); }
2387  mxInt32 * get_int32s (void) const { panic_impossible (); }
2388  mxInt64 * get_int64s (void) const { panic_impossible (); }
2389  mxUint8 * get_uint8s (void) const { panic_impossible (); }
2390  mxUint16 * get_uint16s (void) const { panic_impossible (); }
2391  mxUint32 * get_uint32s (void) const { panic_impossible (); }
2392  mxUint64 * get_uint64s (void) const { panic_impossible (); }
2393 
2394  mxComplexDouble * get_complex_doubles (void) const { panic_impossible (); }
2395  mxComplexSingle * get_complex_singles (void) const { panic_impossible (); }
2396 
2397  // We don't have complex integer types, but for separate storage they
2398  // still would not work.
2399  mxComplexInt8 * get_complex_int8s (void) const { panic_impossible (); }
2400  mxComplexInt16 * get_complex_int16s (void) const { panic_impossible (); }
2401  mxComplexInt32 * get_complex_int32s (void) const { panic_impossible (); }
2402  mxComplexInt64 * get_complex_int64s (void) const { panic_impossible (); }
2403  mxComplexUint8 * get_complex_uint8s (void) const { panic_impossible (); }
2404  mxComplexUint16 * get_complex_uint16s (void) const { panic_impossible (); }
2405  mxComplexUint32 * get_complex_uint32s (void) const { panic_impossible (); }
2406  mxComplexUint64 * get_complex_uint64s (void) const { panic_impossible (); }
2407 
2408  int set_doubles (mxDouble *) { panic_impossible (); }
2409  int set_singles (mxSingle *) { panic_impossible (); }
2410  int set_int8s (mxInt8 *) { panic_impossible (); }
2411  int set_int16s (mxInt16 *) { panic_impossible (); }
2412  int set_int32s (mxInt32 *) { panic_impossible (); }
2413  int set_int64s (mxInt64 *) { panic_impossible (); }
2414  int set_uint8s (mxUint8 *) { panic_impossible (); }
2415  int set_uint16s (mxUint16 *) { panic_impossible (); }
2416  int set_uint32s (mxUint32 *) { panic_impossible (); }
2417  int set_uint64s (mxUint64 *) { panic_impossible (); }
2418 
2419  int set_complex_doubles (mxComplexDouble *) { panic_impossible (); }
2420  int set_complex_singles (mxComplexSingle *) { panic_impossible (); }
2421 
2422  // We don't have complex integer types, but for separate storage they
2423  // still would not work.
2424  int set_complex_int8s (mxComplexInt8 *) { panic_impossible (); }
2425  int set_complex_int16s (mxComplexInt16 *) { panic_impossible (); }
2426  int set_complex_int32s (mxComplexInt32 *) { panic_impossible (); }
2427  int set_complex_int64s (mxComplexInt64 *) { panic_impossible (); }
2428  int set_complex_uint8s (mxComplexUint8 *) { panic_impossible (); }
2429  int set_complex_uint16s (mxComplexUint16 *) { panic_impossible (); }
2430  int set_complex_uint32s (mxComplexUint32 *) { panic_impossible (); }
2431  int set_complex_uint64s (mxComplexUint64 *) { panic_impossible (); }
2432 
2434  {
2435  if (! is_complex ())
2437 
2438  octave_value retval;
2439 
2441 
2442  switch (get_class_id ())
2443  {
2444  case mxDOUBLE_CLASS:
2445  return to_ov<double> (dv);
2446 
2447  case mxSINGLE_CLASS:
2448  return to_ov<float> (dv);
2449 
2450  case mxLOGICAL_CLASS:
2451  case mxINT8_CLASS:
2452  case mxUINT8_CLASS:
2453  case mxINT16_CLASS:
2454  case mxUINT16_CLASS:
2455  case mxINT32_CLASS:
2456  case mxUINT32_CLASS:
2457  case mxINT64_CLASS:
2458  case mxUINT64_CLASS:
2459  error ("complex integer types are not supported");
2460 
2461  default:
2462  panic_impossible ();
2463  }
2464 
2465  return retval;
2466  }
2467 
2468 protected:
2469 
2471  : mxArray_base_full (val),
2472  m_pi (val.m_pi
2474  : nullptr)
2475  {
2476  if (m_pi)
2477  memcpy (m_pi, val.m_pi, get_number_of_elements () * get_element_size ());
2478  }
2479 
2480 private:
2481 
2482  template <typename T>
2483  octave_value
2484  to_ov (const dim_vector& dv) const
2485  {
2486  mwSize nel = get_number_of_elements ();
2487 
2488  T *ppr = static_cast<T *> (m_pr);
2489 
2490  // We allocate in the Array<T> constructor and copy here, so we
2491  // don't need the custom allocator for this object.
2492 
2493  Array<std::complex<T>> val (dv);
2494 
2495  std::complex<T> *ptr = val.fortran_vec ();
2496 
2497  T *ppi = static_cast<T *> (m_pi);
2498 
2499  for (mwIndex i = 0; i < nel; i++)
2500  ptr[i] = std::complex<T> (ppr[i], ppi[i]);
2501 
2502  return octave_value (val);
2503  }
2504 
2505  // Pointer to the imaginary part of the data.
2506  void *m_pi;
2507 };
2508 
2509 // Matlab-style sparse arrays.
2510 
2512 {
2513 public:
2514 
2515  mxArray_base_sparse (bool interleaved, mxClassID id, mwSize m, mwSize n,
2516  mwSize nzmax)
2517  : mxArray_matlab (interleaved, id, m, n),
2518 
2519  m_nzmax (nzmax > 0 ? nzmax : 1),
2520  m_ir (static_cast<mwIndex *> (mxArray::calloc (m_nzmax, sizeof (mwIndex)))),
2521  m_jc (static_cast<mwIndex *> (mxArray::calloc (n + 1, sizeof (mwIndex)))),
2522  m_pr (mxArray::calloc (m_nzmax, get_element_size ()))
2523  { }
2524 
2525 protected:
2526 
2528  : mxArray_matlab (val), m_nzmax (val.m_nzmax),
2529  m_ir (static_cast<mwIndex *> (mxArray::malloc (m_nzmax * sizeof (mwIndex)))),
2530  m_jc (static_cast<mwIndex *> (mxArray::malloc (m_nzmax * sizeof (mwIndex)))),
2532  {
2533  if (m_ir)
2534  memcpy (m_ir, val.m_ir, m_nzmax * sizeof (mwIndex));
2535 
2536  if (m_jc)
2537  memcpy (m_jc, val.m_jc, (val.get_n () + 1) * sizeof (mwIndex));
2538 
2539  if (m_pr)
2540  memcpy (m_pr, val.m_pr, m_nzmax * get_element_size ());
2541  }
2542 
2543 public:
2544 
2545  // No assignment! FIXME: should this be implemented? Note that we
2546  // do have a copy constructor.
2547 
2549 
2550  mxArray_base * dup (void) const
2551  {
2552  return new mxArray_base_sparse (*this);
2553  }
2554 
2556  {
2557  mxFree (m_ir);
2558  mxFree (m_jc);
2559  mxFree (m_pr);
2560  }
2561 
2562  int is_sparse (void) const { return 1; }
2563 
2564  void * get_data (void) const { return m_pr; }
2565 
2566  void set_data (void *pr) { m_pr = pr; }
2567 
2568  mxDouble * get_doubles (void) const
2569  {
2570  return static_cast<mxDouble *> (m_pr);
2571  }
2572 
2573  mxComplexDouble * get_complex_doubles (void) const
2574  {
2575  return static_cast<mxComplexDouble *> (m_pr);
2576  }
2577 
2578  int set_doubles (mxDouble *d)
2579  {
2580  m_pr = d;
2581  return 0;
2582  }
2583 
2584  int set_complex_doubles (mxComplexDouble *d)
2585  {
2586  m_pr = d;
2587  return 0;
2588  }
2589 
2590  mwIndex * get_ir (void) const { return m_ir; }
2591 
2592  mwIndex * get_jc (void) const { return m_jc; }
2593 
2594  mwSize get_nzmax (void) const { return m_nzmax; }
2595 
2596  void set_ir (mwIndex *ir) { m_ir = ir; }
2597 
2598  void set_jc (mwIndex *jc) { m_jc = jc; }
2599 
2600  void set_nzmax (mwSize nzmax)
2601  {
2602  /* Require storage for at least 1 element */
2603  m_nzmax = (nzmax > 0 ? nzmax : 1);
2604  }
2605 
2607  {
2608  octave_value retval;
2609 
2611 
2612  switch (get_class_id ())
2613  {
2614  case mxDOUBLE_CLASS:
2615  return is_complex () ? to_ov<Complex> (dv): to_ov<double> (dv);
2616 
2617  case mxSINGLE_CLASS:
2618  error ("single precision sparse data type not supported");
2619 
2620  case mxLOGICAL_CLASS:
2621  return to_ov<bool> (dv);
2622 
2623  default:
2624  panic_impossible ();
2625  }
2626 
2627  return retval;
2628  }
2629 
2630 protected:
2631 
2632  template <typename ELT_T>
2633  octave_value
2634  to_ov (const dim_vector& dv) const
2635  {
2636  ELT_T *ppr = static_cast<ELT_T *> (m_pr);
2637 
2638 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
2639 
2640  if (current_mx_memory_resource == &the_mx_deleting_memory_resource)
2641  {
2642  octave::unwind_action act ([=] ()
2643  {
2644  maybe_disown_ptr (m_pr);
2645  maybe_disown_ptr (m_ir);
2646  maybe_disown_ptr (m_jc);
2647  });
2648 
2649  return octave_value
2650  (Sparse<ELT_T> (dv, static_cast<octave_idx_type> (m_nzmax),
2651  ppr, m_ir, m_jc, current_mx_memory_resource));
2652  }
2653  else
2654  return octave_value
2655  (Sparse<ELT_T> (dv, static_cast<octave_idx_type> (m_nzmax),
2656  ppr, m_ir, m_jc, current_mx_memory_resource));
2657 #else
2658 
2659  // Copy data instead of allowing the octave_value object to borrow
2660  // the mxArray object data.
2661 
2662  octave_idx_type m = dv(0);
2663  octave_idx_type n = dv(1);
2664 
2665  Sparse<ELT_T> val (m, n, static_cast<octave_idx_type> (m_nzmax));
2666 
2667  for (mwIndex i = 0; i < m_nzmax; i++)
2668  {
2669  val.xdata (i) = ppr[i];
2670  val.xridx (i) = m_ir[i];
2671  }
2672 
2673  for (mwIndex i = 0; i < n + 1; i++)
2674  val.xcidx (i) = m_jc[i];
2675 
2676  return octave_value (val);
2677 
2678 #endif
2679  }
2680 
2681  // Maximun number of nonzero elements.
2682  mwSize m_nzmax;
2683 
2684  // Sparse storage indexing arrays.
2685  mwIndex *m_ir;
2686  mwIndex *m_jc;
2687 
2688  // If using interleaved complex storage, this is the pointer to data
2689  // (real, complex, or logical). Otherwise, it is the pointer to the
2690  // real part of the data.
2691  void *m_pr;
2692 };
2693 
2695 {
2696 public:
2697 
2698  mxArray_interleaved_sparse (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
2699  mxComplexity flag = mxREAL)
2700  : mxArray_base_sparse (true, id, m, n, nzmax),
2701  m_complex (flag == mxCOMPLEX)
2702  { }
2703 
2704 private:
2705 
2707  : mxArray_base_sparse (val), m_complex (val.m_complex)
2708  { }
2709 
2710 public:
2711 
2712  // No assignment! FIXME: should this be implemented? Note that we
2713  // do have a copy constructor.
2714 
2716 
2717  mxArray_base * dup (void) const
2718  {
2719  return new mxArray_interleaved_sparse (*this);
2720  }
2721 
2723 
2724  int is_complex (void) const { return m_complex; }
2725 
2726  void * get_imag_data (void) const { panic_impossible (); }
2727 
2728  void set_imag_data (void */*pi*/) { panic_impossible (); }
2729 
2730 private:
2731 
2732  // Flag to identify complex object if using interleaved data and PI is
2733  // always nullptr.
2735 };
2736 
2738 {
2739 public:
2740 
2741  mxArray_separate_sparse (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
2742  mxComplexity flag = mxREAL)
2743  : mxArray_base_sparse (false, id, m, n, nzmax),
2744  m_pi (flag == mxCOMPLEX
2745  ? mxArray::calloc (m_nzmax, get_element_size ())
2746  : nullptr)
2747  { }
2748 
2749 private:
2750 
2752  : mxArray_base_sparse (val),
2753  m_pi (val.m_pi
2755  : nullptr)
2756  {
2757  if (m_pi)
2758  memcpy (m_pi, val.m_pi, m_nzmax * get_element_size ());
2759  }
2760 
2761 public:
2762 
2763  // No assignment! FIXME: should this be implemented? Note that we
2764  // do have a copy constructor.
2765 
2767 
2768  mxArray_base * dup (void) const
2769  {
2770  return new mxArray_separate_sparse (*this);
2771  }
2772 
2774  {
2775  mxFree (m_pi);
2776  }
2777 
2778  int is_complex (void) const
2779  {
2780  return m_pi != nullptr;
2781  }
2782 
2783  void * get_imag_data (void) const { return m_pi; }
2784 
2785  void set_imag_data (void *pi) { m_pi = pi; }
2786 
2787  mxDouble * get_doubles (void) const { panic_impossible (); }
2788  mxComplexDouble * get_complex_doubles (void) const { panic_impossible (); }
2789 
2790  int set_doubles (mxDouble *) { panic_impossible (); }
2791  int set_complex_doubles (mxComplexDouble *) { panic_impossible (); }
2792 
2794  {
2795  if (! is_complex ())
2797 
2798  octave_value retval;
2799 
2801 
2802  switch (get_class_id ())
2803  {
2804  case mxDOUBLE_CLASS:
2805  {
2806  double *ppr = static_cast<double *> (m_pr);
2807  double *ppi = static_cast<double *> (m_pi);
2808 
2809  SparseComplexMatrix val (get_m (), get_n (),
2810  static_cast<octave_idx_type> (m_nzmax));
2811 
2812  for (mwIndex i = 0; i < m_nzmax; i++)
2813  {
2814  val.xdata (i) = Complex (ppr[i], ppi[i]);
2815  val.xridx (i) = m_ir[i];
2816  }
2817 
2818  for (mwIndex i = 0; i < get_n () + 1; i++)
2819  val.xcidx (i) = m_jc[i];
2820 
2821  retval = val;
2822  }
2823  break;
2824 
2825  case mxSINGLE_CLASS:
2826  error ("single precision sparse data type not supported");
2827 
2828  default:
2829  panic_impossible ();
2830  }
2831 
2832  return retval;
2833  }
2834 
2835 private:
2836 
2837  // Pointer to the imaginary part of the data.
2838  void *m_pi;
2839 };
2840 
2841 // Matlab-style struct arrays.
2842 
2844 {
2845 public:
2846 
2847  mxArray_struct (bool interleaved, mwSize ndims, const mwSize *dims,
2848  int num_keys, const char **keys)
2849  : mxArray_matlab (interleaved, mxSTRUCT_CLASS, ndims, dims),
2850  m_nfields (num_keys),
2851  m_fields (static_cast<char **> (mxArray::calloc (m_nfields,
2852  sizeof (char *)))),
2853  m_data (static_cast<mxArray * *> (mxArray::calloc (m_nfields *
2855  sizeof (mxArray *))))
2856  {
2857  init (keys);
2858  }
2859 
2860  mxArray_struct (bool interleaved, const dim_vector& dv, int num_keys,
2861  const char **keys)
2862  : mxArray_matlab (interleaved, mxSTRUCT_CLASS, dv),
2863  m_nfields (num_keys),
2864  m_fields (static_cast<char **> (mxArray::calloc (m_nfields,
2865  sizeof (char *)))),
2866  m_data (static_cast<mxArray * *> (mxArray::calloc (m_nfields *
2868  sizeof (mxArray *))))
2869  {
2870  init (keys);
2871  }
2872 
2873  mxArray_struct (bool interleaved, mwSize m, mwSize n, int num_keys,
2874  const char **keys)
2875  : mxArray_matlab (interleaved, mxSTRUCT_CLASS, m, n),
2876  m_nfields (num_keys),
2877  m_fields (static_cast<char **> (mxArray::calloc (m_nfields,
2878  sizeof (char *)))),
2879  m_data (static_cast<mxArray * *> (mxArray::calloc (m_nfields *
2881  sizeof (mxArray *))))
2882  {
2883  init (keys);
2884  }
2885 
2886 private:
2887 
2889  : mxArray_matlab (val), m_nfields (val.m_nfields),
2890  m_fields (static_cast<char **> (mxArray::malloc (m_nfields
2891  * sizeof (char *)))),
2892  m_data (static_cast<mxArray * *> (mxArray::malloc (m_nfields *
2894  * sizeof (mxArray *))))
2895  {
2896  for (int i = 0; i < m_nfields; i++)
2897  m_fields[i] = mxArray::strsave (val.m_fields[i]);
2898 
2899  mwSize nel = get_number_of_elements ();
2900 
2901  for (mwIndex i = 0; i < nel * m_nfields; i++)
2902  {
2903  mxArray *ptr = val.m_data[i];
2904  m_data[i] = (ptr ? ptr->dup () : nullptr);
2905  }
2906  }
2907 
2908 public:
2909 
2910  // No assignment! FIXME: should this be implemented? Note that we
2911  // do have a copy constructor.
2912 
2914 
2915  void init (const char **keys)
2916  {
2917  for (int i = 0; i < m_nfields; i++)
2918  m_fields[i] = mxArray::strsave (keys[i]);
2919  }
2920 
2921  mxArray_base * dup (void) const { return new mxArray_struct (*this); }
2922 
2924  {
2925  for (int i = 0; i < m_nfields; i++)
2926  mxFree (m_fields[i]);
2927 
2928  mxFree (m_fields);
2929 
2930  mwSize ntot = m_nfields * get_number_of_elements ();
2931 
2932  for (mwIndex i = 0; i < ntot; i++)
2933  delete m_data[i];
2934 
2935  mxFree (m_data);
2936  }
2937 
2938  int add_field (const char *key)
2939  {
2940  int retval = -1;
2941 
2942  m_nfields++;
2943 
2944  m_fields = static_cast<char **>
2945  (mxRealloc (m_fields, m_nfields * sizeof (char *)));
2946 
2947  if (m_fields)
2948  {
2949  m_fields[m_nfields-1] = mxArray::strsave (key);
2950 
2951  mwSize nel = get_number_of_elements ();
2952 
2953  mwSize ntot = m_nfields * nel;
2954 
2955  mxArray **new_data;
2956  new_data = static_cast<mxArray **>
2957  (mxArray::malloc (ntot * sizeof (mxArray *)));
2958 
2959  if (new_data)
2960  {
2961  mwIndex j = 0;
2962  mwIndex k = 0;
2963  mwIndex n = 0;
2964 
2965  for (mwIndex i = 0; i < ntot; i++)
2966  {
2967  if (++n == m_nfields)
2968  {
2969  new_data[j++] = nullptr;
2970  n = 0;
2971  }
2972  else
2973  new_data[j++] = m_data[k++];
2974  }
2975 
2976  mxFree (m_data);
2977 
2978  m_data = new_data;
2979 
2980  retval = m_nfields - 1;
2981  }
2982  }
2983 
2984  return retval;
2985  }
2986 
2987  void remove_field (int key_num)
2988  {
2989  if (key_num >= 0 && key_num < m_nfields)
2990  {
2991  mwSize nel = get_number_of_elements ();
2992 
2993  mwSize ntot = m_nfields * nel;
2994 
2995  int new_nfields = m_nfields - 1;
2996 
2997  char **new_fields = static_cast<char **>
2998  (mxArray::malloc (new_nfields * sizeof (char *)));
2999 
3000  mxArray **new_data = static_cast<mxArray **>
3001  (mxArray::malloc (new_nfields * nel
3002  * sizeof (mxArray *)));
3003 
3004  for (int i = 0; i < key_num; i++)
3005  new_fields[i] = m_fields[i];
3006 
3007  for (int i = key_num + 1; i < m_nfields; i++)
3008  new_fields[i-1] = m_fields[i];
3009 
3010  if (new_nfields > 0)
3011  {
3012  mwIndex j = 0;
3013  mwIndex k = 0;
3014  mwIndex n = 0;
3015 
3016  for (mwIndex i = 0; i < ntot; i++)
3017  {
3018  if (n == key_num)
3019  k++;
3020  else
3021  new_data[j++] = m_data[k++];
3022 
3023  if (++n == m_nfields)
3024  n = 0;
3025  }
3026  }
3027 
3028  m_nfields = new_nfields;
3029 
3030  mxFree (m_fields);
3031  mxFree (m_data);
3032 
3033  m_fields = new_fields;
3034  m_data = new_data;
3035  }
3036  }
3037 
3038  mxArray * get_field_by_number (mwIndex index, int key_num) const
3039  {
3040  return key_num >= 0 && key_num < m_nfields
3041  ? m_data[m_nfields * index + key_num] : nullptr;
3042  }
3043 
3044  void set_field_by_number (mwIndex index, int key_num, mxArray *val);
3045 
3046  int get_number_of_fields (void) const { return m_nfields; }
3047 
3048  const char * get_field_name_by_number (int key_num) const
3049  {
3050  return key_num >= 0 && key_num < m_nfields ? m_fields[key_num] : nullptr;
3051  }
3052 
3053  int get_field_number (const char *key) const
3054  {
3055  int retval = -1;
3056 
3057  for (int i = 0; i < m_nfields; i++)
3058  {
3059  if (! strcmp (key, m_fields[i]))
3060  {
3061  retval = i;
3062  break;
3063  }
3064  }
3065 
3066  return retval;
3067  }
3068 
3069  void * get_data (void) const { return m_data; }
3070 
3071  void set_data (void *data) { m_data = static_cast<mxArray **> (data); }
3072 
3074  {
3076 
3078 
3079  octave_map m (dv);
3080 
3081  mwSize ntot = m_nfields * get_number_of_elements ();
3082 
3083  for (int i = 0; i < m_nfields; i++)
3084  {
3085  Cell c (dv);
3086 
3087  octave_value *p = c.fortran_vec ();
3088 
3089  mwIndex k = 0;
3090  for (mwIndex j = i; j < ntot; j += m_nfields)
3091  p[k++] = mxArray::as_octave_value (m_data[j]);
3092 
3093  m.assign (keys[i], c);
3094  }
3095 
3096  return m;
3097  }
3098 
3099 private:
3100 
3102 
3103  char **m_fields;
3104 
3106 };
3107 
3108 // Matlab-style cell arrays.
3109 
3111 {
3112 public:
3113 
3114  mxArray_cell (bool interleaved, mwSize ndims, const mwSize *dims)
3115  : mxArray_matlab (interleaved, mxCELL_CLASS, ndims, dims),
3116  m_data (static_cast<mxArray * *> (
3117  mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
3118  { }
3119 
3120  mxArray_cell (bool interleaved, const dim_vector& dv)
3121  : mxArray_matlab (interleaved, mxCELL_CLASS, dv),
3122  m_data (static_cast<mxArray * *> (
3123  mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
3124  { }
3125 
3126  mxArray_cell (bool interleaved, mwSize m, mwSize n)
3127  : mxArray_matlab (interleaved, mxCELL_CLASS, m, n),
3128  m_data (static_cast<mxArray * *> (
3129  mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
3130  { }
3131 
3132 private:
3133 
3135  : mxArray_matlab (val),
3136  m_data (static_cast<mxArray * *> (
3137  mxArray::malloc (get_number_of_elements () * sizeof (mxArray *))))
3138  {
3139  mwSize nel = get_number_of_elements ();
3140 
3141  for (mwIndex i = 0; i < nel; i++)
3142  {
3143  mxArray *ptr = val.m_data[i];
3144  m_data[i] = (ptr ? ptr->dup () : nullptr);
3145  }
3146  }
3147 
3148 public:
3149 
3150  // No assignment! FIXME: should this be implemented? Note that we
3151  // do have a copy constructor.
3152 
3154 
3155  mxArray_base * dup (void) const { return new mxArray_cell (*this); }
3156 
3158  {
3159  mwSize nel = get_number_of_elements ();
3160 
3161  for (mwIndex i = 0; i < nel; i++)
3162  delete m_data[i];
3163 
3164  mxFree (m_data);
3165  }
3166 
3167  mxArray * get_cell (mwIndex idx) const
3168  {
3169  return idx >= 0 && idx < get_number_of_elements () ? m_data[idx] : nullptr;
3170  }
3171 
3172  void set_cell (mwIndex idx, mxArray *val);
3173 
3174  void * get_data (void) const { return m_data; }
3175 
3176  void set_data (void *data) { m_data = static_cast<mxArray **> (data); }
3177 
3179  {
3181 
3182  Cell c (dv);
3183 
3184  mwSize nel = get_number_of_elements ();
3185 
3186  octave_value *p = c.fortran_vec ();
3187 
3188  for (mwIndex i = 0; i < nel; i++)
3189  p[i] = mxArray::as_octave_value (m_data[i]);
3190 
3191  return c;
3192  }
3193 
3194 private:
3195 
3197 };
3198 
3199 // ------------------------------------------------------------------
3200 
3201 mxArray::mxArray (bool interleaved, const octave_value& ov)
3202  : m_rep (create_rep (interleaved, ov)), m_name (nullptr)
3203 { }
3204 
3205 mxArray::mxArray (bool interleaved, mxClassID id, mwSize ndims,
3206  const mwSize *dims, mxComplexity flag, bool init)
3207  : m_rep (create_rep (interleaved, id, ndims, dims, flag, init)),
3208  m_name (nullptr)
3209 { }
3210 
3211 mxArray::mxArray (bool interleaved, mxClassID id, const dim_vector& dv,
3212  mxComplexity flag)
3213  : m_rep (create_rep (interleaved, id, dv, flag)), m_name (nullptr)
3214 { }
3215 
3216 mxArray::mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,
3217  mxComplexity flag, bool init)
3218  : m_rep (create_rep (interleaved, id, m, n, flag, init)), m_name (nullptr)
3219 { }
3220 
3221 mxArray::mxArray (bool interleaved, mxClassID id, double val)
3222  : m_rep (create_rep (interleaved, id, val)), m_name (nullptr)
3223 { }
3224 
3225 mxArray::mxArray (bool interleaved, mxClassID id, mxLogical val)
3226  : m_rep (create_rep (interleaved, id, val)), m_name (nullptr)
3227 { }
3228 
3229 mxArray::mxArray (bool interleaved, const char *str)
3230  : m_rep (create_rep (interleaved, str)), m_name (nullptr)
3231 { }
3232 
3233 mxArray::mxArray (bool interleaved, mwSize m, const char **str)
3234  : m_rep (create_rep (interleaved, m, str)), m_name (nullptr)
3235 { }
3236 
3237 mxArray::mxArray (bool interleaved, mxClassID id, mwSize m, mwSize n,
3238  mwSize nzmax, mxComplexity flag)
3239  : m_rep (create_rep (interleaved, id, m, n, nzmax, flag)), m_name (nullptr)
3240 { }
3241 
3242 mxArray::mxArray (bool interleaved, mwSize ndims, const mwSize *dims,
3243  int num_keys,
3244  const char **keys)
3245  : m_rep (new mxArray_struct (interleaved, ndims, dims, num_keys, keys)),
3246  m_name (nullptr)
3247 { }
3248 
3249 mxArray::mxArray (bool interleaved, const dim_vector& dv, int num_keys,
3250  const char **keys)
3251  : m_rep (new mxArray_struct (interleaved, dv, num_keys, keys)),
3252  m_name (nullptr)
3253 { }
3254 
3255 mxArray::mxArray (bool interleaved, mwSize m, mwSize n, int num_keys,
3256  const char **keys)
3257  : m_rep (new mxArray_struct (interleaved, m, n, num_keys, keys)),
3258  m_name (nullptr)
3259 { }
3260 
3261 mxArray::mxArray (bool interleaved, mwSize ndims, const mwSize *dims)
3262  : m_rep (new mxArray_cell (interleaved, ndims, dims)), m_name (nullptr)
3263 { }
3264 
3265 mxArray::mxArray (bool interleaved, const dim_vector& dv)
3266  : m_rep (new mxArray_cell (interleaved, dv)), m_name (nullptr)
3267 { }
3268 
3269 mxArray::mxArray (bool interleaved, mwSize m, mwSize n)
3270  : m_rep (new mxArray_cell (interleaved, m, n)), m_name (nullptr)
3271 { }
3272 
3274 {
3275  mxFree (m_name);
3276 
3277  delete m_rep;
3278 }
3279 
3280 void
3281 mxArray::set_name (const char *name)
3282 {
3283  mxFree (m_name);
3284  m_name = mxArray::strsave (name);
3285 }
3286 
3288 mxArray::as_octave_value (const mxArray *ptr, bool null_is_empty)
3289 {
3290  static const octave_value empty_matrix = Matrix ();
3291 
3292  return (ptr
3293  ? ptr->as_octave_value ()
3294  : (null_is_empty ? empty_matrix : octave_value ()));
3295 }
3296 
3299 {
3300  return m_rep->as_octave_value ();
3301 }
3302 
3303 mxArray_base *
3304 mxArray::create_rep (bool interleaved, const octave_value& ov)
3305 {
3306  return new mxArray_octave_value (interleaved, ov);
3307 }
3308 
3309 mxArray_base *
3310 mxArray::create_rep (bool interleaved, mxClassID id, mwSize ndims,
3311  const mwSize *dims, mxComplexity flag, bool init)
3312 {
3313  if (interleaved)
3314  return new mxArray_interleaved_full (id, ndims, dims, flag, init);
3315  else
3316  return new mxArray_separate_full (id, ndims, dims, flag, init);
3317 }
3318 
3319 mxArray_base *
3320 mxArray::create_rep (bool interleaved, mxClassID id, const dim_vector& dv,
3321  mxComplexity flag)
3322 {
3323  if (interleaved)
3324  return new mxArray_interleaved_full (id, dv, flag);
3325  else
3326  return new mxArray_separate_full (id, dv, flag);
3327 }
3328 
3329 mxArray_base *
3330 mxArray::create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,
3331  mxComplexity flag, bool init)
3332 {
3333  if (interleaved)
3334  return new mxArray_interleaved_full (id, m, n, flag, init);
3335  else
3336  return new mxArray_separate_full (id, m, n, flag, init);
3337 }
3338 
3339 mxArray_base *
3340 mxArray::create_rep (bool interleaved, mxClassID id, double val)
3341 {
3342  if (interleaved)
3343  return new mxArray_interleaved_full (id, val);
3344  else
3345  return new mxArray_separate_full (id, val);
3346 }
3347 
3348 mxArray_base *
3349 mxArray::create_rep (bool interleaved, mxClassID id, mxLogical val)
3350 {
3351  if (interleaved)
3352  return new mxArray_interleaved_full (id, val);
3353  else
3354  return new mxArray_separate_full (id, val);
3355 }
3356 
3357 mxArray_base *
3358 mxArray::create_rep (bool interleaved, const char *str)
3359 {
3360  if (interleaved)
3361  return new mxArray_interleaved_full (str);
3362  else
3363  return new mxArray_separate_full (str);
3364 }
3365 
3366 mxArray_base *
3367 mxArray::create_rep (bool interleaved, mwSize m, const char **str)
3368 {
3369  if (interleaved)
3370  return new mxArray_interleaved_full (m, str);
3371  else
3372  return new mxArray_separate_full (m, str);
3373 }
3374 
3375 mxArray_base *
3376 mxArray::create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,
3377  mwSize nzmax, mxComplexity flag)
3378 {
3379  if (interleaved)
3380  return new mxArray_interleaved_sparse (id, m, n, nzmax, flag);
3381  else
3382  return new mxArray_separate_sparse (id, m, n, nzmax, flag);
3383 }
3384 
3385 void
3387 {
3388  if (m_rep->is_octave_value ())
3389  {
3390  // The mutate function returns a pointer to a complete new
3391  // mxArray object (or 0, if no mutation happened). We just want
3392  // to replace the existing rep with the rep from the new object.
3393 
3394  mxArray *new_val = m_rep->mutate ();
3395 
3396  if (new_val)
3397  {
3398  delete m_rep;
3399  m_rep = new_val->m_rep;
3400  new_val->m_rep = nullptr;
3401  delete new_val;
3402  }
3403  }
3404 }
3405 
3406 // ------------------------------------------------------------------
3407 
3408 // A class to manage calls to MEX functions. Mostly deals with memory
3409 // management.
3410 
3411 class mex
3412 {
3413 public:
3414 
3416  : m_curr_mex_fcn (f), m_memlist (), m_arraylist (), m_fname (nullptr) { }
3417 
3418  // No copying!
3419 
3420  mex (const mex&) = delete;
3421 
3422  mex& operator = (const mex&) = delete;
3423 
3424  ~mex (void)
3425  {
3426  // We can't use mex::free here because it modifies memlist.
3427  while (! m_memlist.empty ())
3428  {
3429  auto p = m_memlist.begin ();
3430  xfree (*p);
3431  m_memlist.erase (p);
3432  }
3433 
3434  // We can't use mex::free_value here because it modifies arraylist.
3435  while (! m_arraylist.empty ())
3436  {
3437  auto p = m_arraylist.begin ();
3438  delete *p;
3439  m_arraylist.erase (p);
3440  }
3441 
3442  if (! (m_memlist.empty () && m_arraylist.empty ()))
3443  error ("mex: %s: cleanup failed", function_name ());
3444 
3445  mxFree (m_fname);
3446  }
3447 
3448  const char * function_name (void) const
3449  {
3450  if (! m_fname)
3451  {
3452  octave::tree_evaluator& tw = octave::__get_evaluator__ ();
3453 
3454  octave_function *fcn = tw.current_function ();
3455 
3456  if (fcn)
3457  {
3458  std::string nm = fcn->name ();
3459  m_fname = mxArray::strsave (nm.c_str ());
3460  }
3461  else
3462  m_fname = mxArray::strsave ("unknown");
3463  }
3464 
3465  return m_fname;
3466  }
3467 
3468  // Allocate memory.
3469  void * malloc_unmarked (std::size_t n)
3470  {
3471  void *ptr = xmalloc (n);
3472 
3473  if (! ptr)
3474  {
3475  // FIXME: could use "octave_new_handler();" instead
3476  error ("%s: failed to allocate %zd bytes of memory",
3477  function_name (), n);
3478  }
3479 
3480  global_mark (ptr);
3481 
3482  return ptr;
3483  }
3484 
3485  // Allocate memory to be freed on exit.
3486  void * malloc (std::size_t n)
3487  {
3488  void *ptr = malloc_unmarked (n);
3489 
3490  mark (ptr);
3491 
3492  return ptr;
3493  }
3494 
3495  // Allocate memory and initialize to 0.
3496  void * calloc_unmarked (std::size_t n, std::size_t t)
3497  {
3498  void *ptr = malloc_unmarked (n*t);
3499 
3500  memset (ptr, 0, n*t);
3501 
3502  return ptr;
3503  }
3504 
3505  // Allocate memory to be freed on exit and initialize to 0.
3506  void * calloc (std::size_t n, std::size_t t)
3507  {
3508  void *ptr = calloc_unmarked (n, t);
3509 
3510  mark (ptr);
3511 
3512  return ptr;
3513  }
3514 
3515  // Reallocate a pointer obtained from malloc or calloc.
3516  // If the pointer is NULL, allocate using malloc.
3517  // We don't need an "unmarked" version of this.
3518  void * realloc (void *ptr, std::size_t n)
3519  {
3520  void *v;
3521 
3522  if (ptr)
3523  {
3524  auto p_local = m_memlist.find (ptr);
3525  auto p_global = s_global_memlist.find (ptr);
3526 
3527  v = xrealloc (ptr, n);
3528 
3529  if (v)
3530  {
3531  if (p_local != m_memlist.end ())
3532  {
3533  m_memlist.erase (p_local);
3534  m_memlist.insert (v);
3535  }
3536 
3537  if (p_global != s_global_memlist.end ())
3538  {
3539  s_global_memlist.erase (p_global);
3540  s_global_memlist.insert (v);
3541  }
3542  }
3543  }
3544  else
3545  v = malloc (n);
3546 
3547  return v;
3548  }
3549 
3550  // Free a pointer obtained from malloc or calloc.
3551  void free (void *ptr)
3552  {
3553  if (ptr)
3554  {
3555  unmark (ptr);
3556 
3557  auto p = s_global_memlist.find (ptr);
3558 
3559  if (p != s_global_memlist.end ())
3560  {
3561  s_global_memlist.erase (p);
3562 
3563  xfree (ptr);
3564  }
3565  else
3566  {
3567  p = m_foreign_memlist.find (ptr);
3568 
3569  if (p != m_foreign_memlist.end ())
3570  m_foreign_memlist.erase (p);
3571 #if defined (DEBUG)
3572  else
3573  warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc");
3574 #endif
3575  }
3576  }
3577  }
3578 
3579  // Mark a pointer to be freed on exit.
3580  void mark (void *ptr)
3581  {
3582 #if defined (DEBUG)
3583  if (m_memlist.find (ptr) != m_memlist.end ())
3584  warning ("%s: double registration ignored", function_name ());
3585 #endif
3586 
3587  m_memlist.insert (ptr);
3588  }
3589 
3590  // Unmark a pointer to be freed on exit, either because it was
3591  // made persistent, or because it was already freed.
3592  void unmark (void *ptr)
3593  {
3594  auto p = m_memlist.find (ptr);
3595 
3596  if (p != m_memlist.end ())
3597  m_memlist.erase (p);
3598 #if defined (DEBUG)
3599  else
3600  warning ("%s: value not marked", function_name ());
3601 #endif
3602  }
3603 
3605  {
3606  m_arraylist.insert (ptr);
3607  return ptr;
3608  }
3609 
3610  void unmark_array (mxArray *ptr)
3611  {
3612  auto p = m_arraylist.find (ptr);
3613 
3614  if (p != m_arraylist.end ())
3615  m_arraylist.erase (p);
3616  }
3617 
3618  // Mark a pointer as one we allocated.
3619  void mark_foreign (void *ptr)
3620  {
3621 #if defined (DEBUG)
3622  if (m_foreign_memlist.find (ptr) != m_foreign_memlist.end ())
3623  warning ("%s: double registration ignored", function_name ());
3624 #endif
3625 
3626  m_foreign_memlist.insert (ptr);
3627  }
3628 
3629  // Unmark a pointer as one we allocated.
3630  void unmark_foreign (void *ptr)
3631  {
3632  auto p = m_foreign_memlist.find (ptr);
3633 
3634  if (p != m_foreign_memlist.end ())
3635  m_foreign_memlist.erase (p);
3636 #if defined (DEBUG)
3637  else
3638  warning ("%s: value not marked", function_name ());
3639 #endif
3640 
3641  }
3642 
3643  // Make a new array value and initialize from an octave value; it will be
3644  // freed on exit unless marked as persistent.
3646  {
3647  bool interleaved = m_curr_mex_fcn.use_interleaved_complex ();
3648 
3649  return mark_array (new mxArray (interleaved, ov));
3650  }
3651 
3652  // Free an array and its contents.
3653  bool free_value (mxArray *ptr)
3654  {
3655  bool inlist = false;
3656 
3657  auto p = m_arraylist.find (ptr);
3658 
3659  if (p != m_arraylist.end ())
3660  {
3661  inlist = true;
3662  m_arraylist.erase (p);
3663  delete ptr;
3664  }
3665 #if defined (DEBUG)
3666  else
3667  warning ("mex::free_value: skipping memory not allocated by mex::make_value");
3668 #endif
3669 
3670  return inlist;
3671  }
3672 
3674  {
3675  return m_curr_mex_fcn;
3676  }
3677 
3678  // 1 if error should be returned to MEX file, 0 if abort.
3680 
3681  // Mark a pointer as one we allocated.
3682  void global_mark (void *ptr)
3683  {
3684 #if defined (DEBUG)
3685  if (s_global_memlist.find (ptr) != s_global_memlist.end ())
3686  warning ("%s: double registration ignored", function_name ());
3687 #endif
3688 
3689  s_global_memlist.insert (ptr);
3690  }
3691 
3692  // Unmark a pointer as one we allocated.
3693  void global_unmark (void *ptr)
3694  {
3695  auto p = s_global_memlist.find (ptr);
3696 
3697  if (p != s_global_memlist.end ())
3698  s_global_memlist.erase (p);
3699 #if defined (DEBUG)
3700  else
3701  warning ("%s: value not marked", function_name ());
3702 #endif
3703  }
3704 
3705 private:
3706 
3707  // Pointer to the mex function that corresponds to this mex context.
3709 
3710  // List of memory resources that need to be freed upon exit.
3711  std::set<void *> m_memlist;
3712 
3713  // List of mxArray objects that need to be freed upon exit.
3714  std::set<mxArray *> m_arraylist;
3715 
3716  // List of memory resources we know about, but that were allocated
3717  // elsewhere.
3718  std::set<void *> m_foreign_memlist;
3719 
3720  // The name of the currently executing function.
3721  mutable char *m_fname;
3722 
3723  // List of memory resources we allocated.
3724  static std::set<void *> s_global_memlist;
3725 
3726 };
3727 
3728 // List of memory resources we allocated.
3729 std::set<void *> mex::s_global_memlist;
3730 
3731 // Current context.
3732 mex *mex_context = nullptr;
3733 
3734 void *
3735 mxArray::malloc (std::size_t n)
3736 {
3738 }
3739 
3740 void *
3741 mxArray::calloc (std::size_t n, std::size_t t)
3742 {
3743  return mex_context ? mex_context->calloc_unmarked (n, t) : ::calloc (n, t);
3744 }
3745 
3746 void *
3747 mxArray::alloc (bool init, std::size_t n, std::size_t t)
3748 {
3749  return init ? mxArray::calloc (n, t) : mxArray::malloc (n * t);
3750 }
3751 
3752 static inline void *
3754 {
3755  if (mex_context)
3756  mex_context->mark_foreign (ptr);
3757 
3758  return ptr;
3759 }
3760 
3761 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
3762 
3763 static inline void
3764 maybe_disown_ptr (void *ptr)
3765 {
3766  if (mex_context)
3767  {
3768  mex_context->unmark (ptr);
3769  mex_context->global_unmark (ptr);
3770  mex_context->mark_foreign (ptr);
3771  }
3772 }
3773 
3774 #endif
3775 
3776 static inline mxArray *
3778 {
3779  if (mex_context)
3780  mex_context->unmark_array (ptr);
3781 
3782  return ptr;
3783 }
3784 
3785 template <typename T>
3786 static inline T *
3788 {
3789  if (mex_context)
3790  mex_context->unmark (ptr);
3791 
3792  return ptr;
3793 }
3794 
3795 void
3796 mxArray_struct::set_field_by_number (mwIndex index, int key_num, mxArray *val)
3797 {
3798  if (key_num >= 0 && key_num < m_nfields)
3799  m_data[m_nfields * index + key_num] = maybe_unmark_array (val);
3800 }
3801 
3802 void
3803 mxArray_cell::set_cell (mwIndex idx, mxArray *val)
3804 {
3805  if (idx >= 0 && idx < get_number_of_elements ())
3806  m_data[idx] = maybe_unmark_array (val);
3807 }
3808 
3809 // ------------------------------------------------------------------
3810 
3811 // C interface to mxArray objects:
3812 
3813 // Floating point predicates.
3814 
3815 bool
3816 mxIsFinite (const double v)
3817 {
3818  return lo_ieee_isfinite (v) != 0;
3819 }
3820 
3821 bool
3822 mxIsInf (const double v)
3823 {
3824  return lo_ieee_isinf (v) != 0;
3825 }
3826 
3827 bool
3828 mxIsNaN (const double v)
3829 {
3830  return lo_ieee_isnan (v) != 0;
3831 }
3832 
3833 double
3834 mxGetEps (void)
3835 {
3836  return std::numeric_limits<double>::epsilon ();
3837 }
3838 
3839 double
3840 mxGetInf (void)
3841 {
3842  return lo_ieee_inf_value ();
3843 }
3844 
3845 double
3846 mxGetNaN (void)
3847 {
3848  return lo_ieee_nan_value ();
3849 }
3850 
3851 // Memory management.
3852 void *
3853 mxCalloc (std::size_t n, std::size_t size)
3854 {
3855  return mex_context ? mex_context->calloc (n, size) : ::calloc (n, size);
3856 }
3857 
3858 void *
3859 mxMalloc (std::size_t n)
3860 {
3861  return mex_context ? mex_context->malloc (n) : xmalloc (n);
3862 }
3863 
3864 void *
3865 mxRealloc (void *ptr, std::size_t size)
3866 {
3867  return (mex_context
3868  ? mex_context->realloc (ptr, size) : xrealloc (ptr, size));
3869 }
3870 
3871 void
3872 mxFree (void *ptr)
3873 {
3874  if (mex_context)
3875  mex_context->free (ptr);
3876  else
3877  xfree (ptr);
3878 }
3879 
3880 static inline mxArray *
3882 {
3883  return mex_context ? mex_context->mark_array (ptr) : ptr;
3884 }
3885 
3886 // Constructors.
3887 mxArray *
3888 mxCreateCellArray_interleaved (mwSize ndims, const mwSize *dims)
3889 {
3890  return maybe_mark_array (new mxArray (true, ndims, dims));
3891 }
3892 
3893 mxArray *
3894 mxCreateCellArray (mwSize ndims, const mwSize *dims)
3895 {
3896  return maybe_mark_array (new mxArray (false, ndims, dims));
3897 }
3898 
3899 mxArray *
3901 {
3902  return maybe_mark_array (new mxArray (true, m, n));
3903 }
3904 
3905 mxArray *
3906 mxCreateCellMatrix (mwSize m, mwSize n)
3907 {
3908  return maybe_mark_array (new mxArray (false, m, n));
3909 }
3910 
3911 mxArray *
3912 mxCreateCharArray_interleaved (mwSize ndims, const mwSize *dims)
3913 {
3914  return maybe_mark_array (new mxArray (true, mxCHAR_CLASS, ndims, dims));
3915 }
3916 
3917 mxArray *
3918 mxCreateCharArray (mwSize ndims, const mwSize *dims)
3919 {
3920  return maybe_mark_array (new mxArray (false, mxCHAR_CLASS, ndims, dims));
3921 }
3922 
3923 mxArray *
3925 {
3926  return maybe_mark_array (new mxArray (true, m, str));
3927 }
3928 
3929 mxArray *
3930 mxCreateCharMatrixFromStrings (mwSize m, const char **str)
3931 {
3932  return maybe_mark_array (new mxArray (false, m, str));
3933 }
3934 
3935 mxArray *
3936 mxCreateDoubleMatrix_interleaved (mwSize m, mwSize n, mxComplexity flag)
3937 {
3938  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, m, n, flag));
3939 }
3940 
3941 mxArray *
3942 mxCreateDoubleMatrix (mwSize m, mwSize n, mxComplexity flag)
3943 {
3944  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, m, n, flag));
3945 }
3946 
3947 mxArray *
3949 {
3950  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, val));
3951 }
3952 
3953 mxArray *
3955 {
3956  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, val));
3957 }
3958 
3959 mxArray *
3960 mxCreateLogicalArray_interleaved (mwSize ndims, const mwSize *dims)
3961 {
3962  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, ndims, dims));
3963 }
3964 
3965 mxArray *
3966 mxCreateLogicalArray (mwSize ndims, const mwSize *dims)
3967 {
3968  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, ndims, dims));
3969 }
3970 
3971 mxArray *
3973 {
3974  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, m, n));
3975 }
3976 
3977 mxArray *
3978 mxCreateLogicalMatrix (mwSize m, mwSize n)
3979 {
3980  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, m, n));
3981 }
3982 
3983 mxArray *
3985 {
3986  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, val));
3987 }
3988 
3989 mxArray *
3990 mxCreateLogicalScalar (mxLogical val)
3991 {
3992  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, val));
3993 }
3994 
3995 mxArray *
3996 mxCreateNumericArray_interleaved (mwSize ndims, const mwSize *dims,
3997  mxClassID class_id, mxComplexity flag)
3998 {
3999  return maybe_mark_array (new mxArray (true, class_id, ndims, dims, flag));
4000 }
4001 
4002 mxArray *
4003 mxCreateNumericArray (mwSize ndims, const mwSize *dims,
4004  mxClassID class_id, mxComplexity flag)
4005 {
4006  return maybe_mark_array (new mxArray (false, class_id, ndims, dims, flag));
4007 }
4008 
4009 mxArray *
4010 mxCreateNumericMatrix_interleaved (mwSize m, mwSize n, mxClassID class_id,
4011  mxComplexity flag)
4012 {
4013  return maybe_mark_array (new mxArray (true, class_id, m, n, flag));
4014 }
4015 
4016 mxArray *
4017 mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
4018  mxComplexity flag)
4019 {
4020  return maybe_mark_array (new mxArray (false, class_id, m, n, flag));
4021 }
4022 
4023 mxArray *
4024 mxCreateUninitNumericArray_interleaved (mwSize ndims, const mwSize *dims,
4025  mxClassID class_id, mxComplexity flag)
4026 {
4027  return maybe_mark_array (new mxArray (true, class_id, ndims, dims, flag,
4028  false));
4029 }
4030 
4031 mxArray *
4032 mxCreateUninitNumericArray (mwSize ndims, const mwSize *dims,
4033  mxClassID class_id, mxComplexity flag)
4034 {
4035  return maybe_mark_array (new mxArray (false, class_id, ndims, dims, flag,
4036  false));
4037 }
4038 
4039 mxArray *
4041  mxClassID class_id, mxComplexity flag)
4042 {
4043  return maybe_mark_array (new mxArray (true, class_id, m, n, flag, false));
4044 }
4045 
4046 mxArray *
4047 mxCreateUninitNumericMatrix (mwSize m, mwSize n, mxClassID class_id,
4048  mxComplexity flag)
4049 {
4050  return maybe_mark_array (new mxArray (false, class_id, m, n, flag, false));
4051 }
4052 
4053 mxArray *
4054 mxCreateSparse_interleaved (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
4055 {
4056  return maybe_mark_array (new mxArray (true, mxDOUBLE_CLASS, m, n, nzmax,
4057  flag));
4058 }
4059 
4060 mxArray *
4061 mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
4062 {
4063  return maybe_mark_array (new mxArray (false, mxDOUBLE_CLASS, m, n, nzmax,
4064  flag));
4065 }
4066 
4067 mxArray *
4068 mxCreateSparseLogicalMatrix_interleaved (mwSize m, mwSize n, mwSize nzmax)
4069 {
4070  return maybe_mark_array (new mxArray (true, mxLOGICAL_CLASS, m, n, nzmax));
4071 }
4072 
4073 mxArray *
4074 mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax)
4075 {
4076  return maybe_mark_array (new mxArray (false, mxLOGICAL_CLASS, m, n, nzmax));
4077 }
4078 
4079 mxArray *
4081 {
4082  return maybe_mark_array (new mxArray (true, str));
4083 }
4084 
4085 mxArray *
4086 mxCreateString (const char *str)
4087 {
4088  return maybe_mark_array (new mxArray (false, str));
4089 }
4090 
4091 mxArray *
4092 mxCreateStructArray_interleaved (mwSize ndims, const mwSize *dims,
4093  int num_keys, const char **keys)
4094 {
4095  return maybe_mark_array (new mxArray (true, ndims, dims, num_keys, keys));
4096 }
4097 
4098 mxArray *
4099 mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys,
4100  const char **keys)
4101 {
4102  return maybe_mark_array (new mxArray (false, ndims, dims, num_keys, keys));
4103 }
4104 
4105 mxArray *
4106 mxCreateStructMatrix_interleaved (mwSize m, mwSize n, int num_keys,
4107  const char **keys)
4108 {
4109  return maybe_mark_array (new mxArray (true, m, n, num_keys, keys));
4110 }
4111 
4112 mxArray *
4113 mxCreateStructMatrix (mwSize m, mwSize n, int num_keys,
4114  const char **keys)
4115 {
4116  return maybe_mark_array (new mxArray (false, m, n, num_keys, keys));
4117 }
4118 
4119 // Copy constructor.
4120 mxArray *
4122 {
4123  return maybe_mark_array (ptr->dup ());
4124 }
4125 
4126 // Destructor.
4127 void
4129 {
4130  if (! (mex_context && mex_context->free_value (ptr)))
4131  delete ptr;
4132 }
4133 
4134 // Type Predicates.
4135 bool
4136 mxIsCell (const mxArray *ptr)
4137 {
4138  return ptr->iscell ();
4139 }
4140 
4141 bool
4142 mxIsChar (const mxArray *ptr)
4143 {
4144  return ptr->is_char ();
4145 }
4146 
4147 bool
4148 mxIsClass (const mxArray *ptr, const char *name)
4149 {
4150  return ptr->is_class (name);
4151 }
4152 
4153 bool
4154 mxIsComplex (const mxArray *ptr)
4155 {
4156  return ptr->is_complex ();
4157 }
4158 
4159 bool
4160 mxIsDouble (const mxArray *ptr)
4161 {
4162  return ptr->is_double ();
4163 }
4164 
4165 bool
4167 {
4168  return ptr->is_function_handle ();
4169 }
4170 
4171 bool
4172 mxIsInt16 (const mxArray *ptr)
4173 {
4174  return ptr->is_int16 ();
4175 }
4176 
4177 bool
4178 mxIsInt32 (const mxArray *ptr)
4179 {
4180  return ptr->is_int32 ();
4181 }
4182 
4183 bool
4184 mxIsInt64 (const mxArray *ptr)
4185 {
4186  return ptr->is_int64 ();
4187 }
4188 
4189 bool
4190 mxIsInt8 (const mxArray *ptr)
4191 {
4192  return ptr->is_int8 ();
4193 }
4194 
4195 bool
4196 mxIsLogical (const mxArray *ptr)
4197 {
4198  return ptr->is_logical ();
4199 }
4200 
4201 bool
4202 mxIsNumeric (const mxArray *ptr)
4203 {
4204  return ptr->is_numeric ();
4205 }
4206 
4207 bool
4208 mxIsSingle (const mxArray *ptr)
4209 {
4210  return ptr->is_single ();
4211 }
4212 
4213 bool
4214 mxIsSparse (const mxArray *ptr)
4215 {
4216  return ptr->is_sparse ();
4217 }
4218 
4219 bool
4220 mxIsStruct (const mxArray *ptr)
4221 {
4222  return ptr->is_struct ();
4223 }
4224 
4225 bool
4226 mxIsUint16 (const mxArray *ptr)
4227 {
4228  return ptr->is_uint16 ();
4229 }
4230 
4231 bool
4232 mxIsUint32 (const mxArray *ptr)
4233 {
4234  return ptr->is_uint32 ();
4235 }
4236 
4237 bool
4238 mxIsUint64 (const mxArray *ptr)
4239 {
4240  return ptr->is_uint64 ();
4241 }
4242 
4243 bool
4244 mxIsUint8 (const mxArray *ptr)
4245 {
4246  return ptr->is_uint8 ();
4247 }
4248 
4249 // Odd type+size predicate.
4250 bool
4252 {
4253  return ptr->is_logical_scalar ();
4254 }
4255 
4256 // Odd type+size+value predicate.
4257 bool
4259 {
4260  return ptr->is_logical_scalar_true ();
4261 }
4262 
4263 // Size predicate.
4264 bool
4265 mxIsEmpty (const mxArray *ptr)
4266 {
4267  return ptr->isempty ();
4268 }
4269 
4270 bool
4271 mxIsScalar (const mxArray *ptr)
4272 {
4273  return ptr->is_scalar ();
4274 }
4275 
4276 // FIXME: Just plain odd thing to ask of a value.
4277 // Still, Octave is incompatible because it does not implement this.
4278 bool
4279 mxIsFromGlobalWS (const mxArray * /*ptr*/)
4280 {
4281  mexErrMsgTxt ("mxIsFromGlobalWS() is unimplemented");
4282 
4283  return 0;
4284 }
4285 
4286 // Dimension extractors.
4287 std::size_t
4288 mxGetM (const mxArray *ptr)
4289 {
4290  return ptr->get_m ();
4291 }
4292 
4293 std::size_t
4294 mxGetN (const mxArray *ptr)
4295 {
4296  return ptr->get_n ();
4297 }
4298 
4299 const mwSize *
4301 {
4302  return ptr->get_dimensions ();
4303 }
4304 
4305 mwSize
4307 {
4308  return ptr->get_number_of_dimensions ();
4309 }
4310 
4311 std::size_t
4313 {
4314  return ptr->get_number_of_elements ();
4315 }
4316 
4317 // Dimension setters.
4318 void
4319 mxSetM (mxArray *ptr, mwSize m)
4320 {
4321  ptr->set_m (m);
4322 }
4323 
4324 void
4325 mxSetN (mxArray *ptr, mwSize n)
4326 {
4327  ptr->set_n (n);
4328 }
4329 
4330 int
4331 mxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims)
4332 {
4333  return (ptr->set_dimensions (static_cast<mwSize *>
4334  (maybe_unmark (const_cast<mwSize *> (dims))),
4335  ndims));
4336 }
4337 
4338 // Data extractors.
4339 double *
4340 mxGetPr (const mxArray *ptr)
4341 {
4342  return static_cast<double *> (ptr->get_data ());
4343 }
4344 
4345 double
4346 mxGetScalar (const mxArray *ptr)
4347 {
4348  return ptr->get_scalar ();
4349 }
4350 
4351 mxChar *
4352 mxGetChars (const mxArray *ptr)
4353 {
4354  if (mxIsChar (ptr))
4355  return static_cast<mxChar *> (ptr->get_data ());
4356  else
4357  return nullptr;
4358 }
4359 
4360 mxLogical *
4362 {
4363  return static_cast<mxLogical *> (ptr->get_data ());
4364 }
4365 
4366 void *
4367 mxGetData (const mxArray *ptr)
4368 {
4369  return ptr->get_data ();
4370 }
4371 
4372 double *
4373 mxGetPi (const mxArray *ptr)
4374 {
4375  return static_cast<double *> (ptr->get_imag_data ());
4376 }
4377 
4378 void *
4380 {
4381  return ptr->get_imag_data ();
4382 }
4383 
4384 mxDouble * mxGetDoubles (const mxArray *ptr)
4385 {
4386  return ptr->get_doubles ();
4387 }
4388 
4389 mxSingle * mxGetSingles (const mxArray *ptr)
4390 {
4391  return ptr->get_singles ();
4392 }
4393 
4394 mxInt8 * mxGetInt8s (const mxArray *ptr)
4395 {
4396  return ptr->get_int8s ();
4397 }
4398 
4399 mxInt16 * mxGetInt16s (const mxArray *ptr)
4400 {
4401  return ptr->get_int16s ();
4402 }
4403 
4404 mxInt32 * mxGetInt32s (const mxArray *ptr)
4405 {
4406  return ptr->get_int32s ();
4407 }
4408 
4409 mxInt64 * mxGetInt64s (const mxArray *ptr)
4410 {
4411  return ptr->get_int64s ();
4412 }
4413 
4414 mxUint8 * mxGetUint8s (const mxArray *ptr)
4415 {
4416  return ptr->get_uint8s ();
4417 }
4418 
4419 mxUint16 * mxGetUint16s (const mxArray *ptr)
4420 {
4421  return ptr->get_uint16s ();
4422 }
4423 
4424 mxUint32 * mxGetUint32s (const mxArray *ptr)
4425 {
4426  return ptr->get_uint32s ();
4427 }
4428 
4429 mxUint64 * mxGetUint64s (const mxArray *ptr)
4430 {
4431  return ptr->get_uint64s ();
4432 }
4433 
4434 mxComplexDouble * mxGetComplexDoubles (const mxArray *ptr)
4435 {
4436  return ptr->get_complex_doubles ();
4437 }
4438 
4439 mxComplexSingle * mxGetComplexSingles (const mxArray *ptr)
4440 {
4441  return ptr->get_complex_singles ();
4442 }
4443 
4444 #if 0
4445 /* We don't have these yet. */
4446 mxComplexInt8 * mxGetComplexInt8s (const mxArray *ptr)
4447 {
4448  return ptr->get_complex_int8s ();
4449 }
4450 
4451 mxComplexInt16 * mxGetComplexInt16s (const mxArray *ptr)
4452 {
4453  return ptr->get_complex_int16s ();
4454 }
4455 
4456 mxComplexInt32 * mxGetComplexInt32s (const mxArray *ptr)
4457 {
4458  return ptr->get_complex_int32s ();
4459 }
4460 
4461 mxComplexInt64 * mxGetComplexInt64s (const mxArray *ptr)
4462 {
4463  return ptr->get_complex_int64s ();
4464 }
4465 
4466 mxComplexUint8 * mxGetComplexUint8s (const mxArray *ptr)
4467 {
4468  return ptr->get_complex_uint8s ();
4469 }
4470 
4471 mxComplexUint16 * mxGetComplexUint16s (const mxArray *ptr)
4472 {
4473  return ptr->get_complex_uint16s ();
4474 }
4475 
4476 mxComplexUint32 * mxGetComplexUint32s (const mxArray *ptr)
4477 {
4478  return ptr->get_complex_uint32s ();
4479 }
4480 
4481 mxComplexUint64 * mxGetComplexUint64s (const mxArray *ptr)
4482 {
4483  return ptr->get_complex_uint64s ();
4484 }
4485 #endif
4486 
4487 // Data setters.
4488 void
4489 mxSetPr (mxArray *ptr, double *pr)
4490 {
4491  ptr->set_data (maybe_unmark (pr));
4492 }
4493 
4494 void
4495 mxSetData (mxArray *ptr, void *pr)
4496 {
4497  ptr->set_data (maybe_unmark (pr));
4498 }
4499 
4500 int mxSetDoubles (mxArray *ptr, mxDouble *data)
4501 {
4502  return ptr->set_doubles (maybe_unmark (data));
4503 }
4504 
4505 int mxSetSingles (mxArray *ptr, mxSingle *data)
4506 {
4507  return ptr->set_singles (maybe_unmark (data));
4508 }
4509 
4510 int mxSetInt8s (mxArray *ptr, mxInt8 *data)
4511 {
4512  return ptr->set_int8s (maybe_unmark (data));
4513 }
4514 
4515 int mxSetInt16s (mxArray *ptr, mxInt16 *data)
4516 {
4517  return ptr->set_int16s (maybe_unmark (data));
4518 }
4519 
4520 int mxSetInt32s (mxArray *ptr, mxInt32 *data)
4521 {
4522  return ptr->set_int32s (maybe_unmark (data));
4523 }
4524 
4525 int mxSetInt64s (mxArray *ptr, mxInt64 *data)
4526 {
4527  return ptr->set_int64s (maybe_unmark (data));
4528 }
4529 
4530 int mxSetUint8s (mxArray *ptr, mxUint8 *data)
4531 {
4532  return ptr->set_uint8s (maybe_unmark (data));
4533 }
4534 
4535 int mxSetUint16s (mxArray *ptr, mxUint16 *data)
4536 {
4537  return ptr->set_uint16s (maybe_unmark (data));
4538 }
4539 
4540 int mxSetUint32s (mxArray *ptr, mxUint32 *data)
4541 {
4542  return ptr->set_uint32s (maybe_unmark (data));
4543 }
4544 
4545 int mxSetUint64s (mxArray *ptr, mxUint64 *data)
4546 {
4547  return ptr->set_uint64s (maybe_unmark (data));
4548 }
4549 
4550 int mxSetComplexDoubles (mxArray *ptr, mxComplexDouble *data)
4551 {
4552  return ptr->set_complex_doubles (maybe_unmark (data));
4553 }
4554 
4555 int mxSetComplexSingles (mxArray *ptr, mxComplexSingle *data)
4556 {
4557  return ptr->set_complex_singles (maybe_unmark (data));
4558 }
4559 
4560 #if 0
4561 /* We don't have these yet. */
4562 int mxSetComplexInt8s (mxArray *ptr, mxComplexInt8 *data)
4563 {
4564  return ptr->set_complex_int8s (maybe_unmark (data));
4565 }
4566 
4567 int mxSetComplexInt16s (mxArray *ptr, mxComplexInt16 *data)
4568 {
4569  return ptr->set_complex_int16s (maybe_unmark (data));
4570 }
4571 
4572 int mxSetComplexInt32s (mxArray *ptr, mxComplexInt32 *data)
4573 {
4574  return ptr->set_complex_int32s (maybe_unmark (data));
4575 }
4576 
4577 int mxSetComplexInt64s (mxArray *ptr, mxComplexInt64 *data)
4578 {
4579  return ptr->set_complex_int64s (maybe_unmark (data));
4580 }
4581 
4582 int mxSetComplexUint8s (mxArray *ptr, mxComplexUint8 *data)
4583 {
4584  return ptr->set_complex_uint8s (maybe_unmark (data));
4585 }
4586 
4587 int mxSetComplexUint16s (mxArray *ptr, mxComplexUint16 *data)
4588 {
4589  return ptr->set_complex_uint16s (maybe_unmark (data));
4590 }
4591 
4592 int mxSetComplexUint32s (mxArray *ptr, mxComplexUint32 *data)
4593 {
4594  return ptr->set_complex_uint32s (maybe_unmark (data));
4595 }
4596 
4597 int mxSetComplexUint64s (mxArray *ptr, mxComplexUint64 *data)
4598 {
4599  return ptr->set_complex_uint64s (maybe_unmark (data));
4600 }
4601 #endif
4602 
4603 void
4604 mxSetPi (mxArray *ptr, double *pi)
4605 {
4606  ptr->set_imag_data (maybe_unmark (pi));
4607 }
4608 
4609 void
4610 mxSetImagData (mxArray *ptr, void *pi)
4611 {
4612  ptr->set_imag_data (maybe_unmark (pi));
4613 }
4614 
4615 // Classes.
4616 mxClassID
4617 mxGetClassID (const mxArray *ptr)
4618 {
4619  return ptr->get_class_id ();
4620 }
4621 
4622 const char *
4624 {
4625  return ptr->get_class_name ();
4626 }
4627 
4628 void
4629 mxSetClassName (mxArray *ptr, const char *name)
4630 {
4631  ptr->set_class_name (name);
4632 }
4633 
4634 void
4635 mxSetProperty (mxArray *ptr, mwIndex idx, const char *property_name,
4636  const mxArray *property_value)
4637 {
4638  ptr->set_property (idx, property_name, property_value);
4639 }
4640 
4641 mxArray *
4642 mxGetProperty (const mxArray *ptr, mwIndex idx, const char *property_name)
4643 {
4644  return ptr->get_property (idx, property_name);
4645 }
4646 
4647 // Cell support.
4648 mxArray *
4649 mxGetCell (const mxArray *ptr, mwIndex idx)
4650 {
4651  return ptr->get_cell (idx);
4652 }
4653 
4654 void
4655 mxSetCell (mxArray *ptr, mwIndex idx, mxArray *val)
4656 {
4657  ptr->set_cell (idx, val);
4658 }
4659 
4660 // Sparse support.
4661 mwIndex *
4662 mxGetIr (const mxArray *ptr)
4663 {
4664  return ptr->get_ir ();
4665 }
4666 
4667 mwIndex *
4668 mxGetJc (const mxArray *ptr)
4669 {
4670  return ptr->get_jc ();
4671 }
4672 
4673 mwSize
4674 mxGetNzmax (const mxArray *ptr)
4675 {
4676  return ptr->get_nzmax ();
4677 }
4678 
4679 void
4680 mxSetIr (mxArray *ptr, mwIndex *ir)
4681 {
4682  ptr->set_ir (static_cast<mwIndex *> (maybe_unmark (ir)));
4683 }
4684 
4685 void
4686 mxSetJc (mxArray *ptr, mwIndex *jc)
4687 {
4688  ptr->set_jc (static_cast<mwIndex *> (maybe_unmark (jc)));
4689 }
4690 
4691 void
4692 mxSetNzmax (mxArray *ptr, mwSize nzmax)
4693 {
4694  ptr->set_nzmax (nzmax);
4695 }
4696 
4697 // Structure support.
4698 int
4699 mxAddField (mxArray *ptr, const char *key)
4700 {
4701  return ptr->add_field (key);
4702 }
4703 
4704 void
4705 mxRemoveField (mxArray *ptr, int key_num)
4706 {
4707  ptr->remove_field (key_num);
4708 }
4709 
4710 mxArray *
4711 mxGetField (const mxArray *ptr, mwIndex index, const char *key)
4712 {
4713  int key_num = mxGetFieldNumber (ptr, key);
4714  return mxGetFieldByNumber (ptr, index, key_num);
4715 }
4716 
4717 mxArray *
4718 mxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num)
4719 {
4720  return ptr->get_field_by_number (index, key_num);
4721 }
4722 
4723 void
4724 mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val)
4725 {
4726  int key_num = mxGetFieldNumber (ptr, key);
4727  mxSetFieldByNumber (ptr, index, key_num, val);
4728 }
4729 
4730 void
4731 mxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val)
4732 {
4733  ptr->set_field_by_number (index, key_num, val);
4734 }
4735 
4736 int
4738 {
4739  return ptr->get_number_of_fields ();
4740 }
4741 
4742 const char *
4743 mxGetFieldNameByNumber (const mxArray *ptr, int key_num)
4744 {
4745  return ptr->get_field_name_by_number (key_num);
4746 }
4747 
4748 int
4749 mxGetFieldNumber (const mxArray *ptr, const char *key)
4750 {
4751  return ptr->get_field_number (key);
4752 }
4753 
4754 int
4755 mxGetString (const mxArray *ptr, char *buf, mwSize buflen)
4756 {
4757  return ptr->get_string (buf, buflen);
4758 }
4759 
4760 char *
4762 {
4763  return ptr->array_to_string ();
4764 }
4765 
4766 mwIndex
4767 mxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs)
4768 {
4769  return ptr->calc_single_subscript (nsubs, subs);
4770 }
4771 
4772 std::size_t
4774 {
4775  return ptr->get_element_size ();
4776 }
4777 
4778 // ------------------------------------------------------------------
4779 
4780 typedef void (*cmex_fptr) (int nlhs, mxArray **plhs, int nrhs, mxArray **prhs);
4781 typedef F77_RET_T (*fmex_fptr) (F77_INT& nlhs, mxArray **plhs,
4782  F77_INT& nrhs, mxArray **prhs);
4783 
4785 
4788  int nargout_arg)
4789 {
4790  octave_quit ();
4791 
4792  // Use at least 1 for nargout since even for zero specified args,
4793  // still want to be able to return an ans.
4794 
4795  volatile int nargout = nargout_arg;
4796 
4797  int nargin = args.length ();
4798  OCTAVE_LOCAL_BUFFER (mxArray *, argin, nargin);
4799  for (int i = 0; i < nargin; i++)
4800  argin[i] = nullptr;
4801 
4802  int nout = (nargout == 0 ? 1 : nargout);
4803  OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout);
4804  for (int i = 0; i < nout; i++)
4805  argout[i] = nullptr;
4806 
4807  // Save old mex pointer.
4808  octave::unwind_protect_var<mex *> restore_var (mex_context);
4809 
4810  mex context (mex_fcn);
4811 
4812  for (int i = 0; i < nargin; i++)
4813  argin[i] = context.make_value (args(i));
4814 
4815  mex_context = &context;
4816 
4817  void *mex_fcn_ptr = mex_fcn.mex_fcn_ptr ();
4818 
4819  if (mex_fcn.is_fmex ())
4820  {
4821  fmex_fptr fcn = reinterpret_cast<fmex_fptr> (mex_fcn_ptr);
4822 
4823  F77_INT tmp_nargout = nargout;
4824  F77_INT tmp_nargin = nargin;
4825 
4826  fcn (tmp_nargout, argout, tmp_nargin, argin);
4827  }
4828  else
4829  {
4830  cmex_fptr fcn = reinterpret_cast<cmex_fptr> (mex_fcn_ptr);
4831 
4832  fcn (nargout, argout, nargin, argin);
4833  }
4834 
4835  // Convert returned array entries back into octave values.
4836 
4837  octave_value_list retval;
4838 
4839  if (nargout == 0 && argout[0])
4840  {
4841  // We have something for ans.
4842  nargout = 1;
4843  }
4844 
4845  retval.resize (nargout);
4846 
4847  // If using std::pmr::memory_resource object to manage memory, pass
4848  // default allocator here because we are done with these mxArray
4849  // values and want Octave to delete them.
4850 
4851  for (int i = 0; i < nargout; i++)
4852  retval(i) = mxArray::as_octave_value (argout[i], false);
4853 
4854  return retval;
4855 }
4856 
4858 
4859 // C interface to mex functions:
4860 
4861 const char *
4863 {
4864  return mex_context ? mex_context->function_name () : "unknown";
4865 }
4866 
4867 static inline octave_value_list
4868 mx_to_ov_args (int nargin, mxArray *argin[])
4869 {
4870  // Use a separate function for this job so that the
4871  // current_mx_memory_resource will be restored immediately after the
4872  // octave_value objects borrow the mxArray data. We could also use a
4873  // dummy scope in mexCallMATLAB, but this function seems less likely
4874  // to be accidentally deleted.
4875 
4876  octave_value_list args (nargin);
4877 
4878 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
4879 
4880  // Use allocator that doesn't free memory because Octave may mutate
4881  // the value (single element mxArray -> scalar octave_value object,
4882  // for example) and we need these objects to continue to exist after
4883  // mexCallMATLAB returns.
4884 
4885  octave::unwind_protect_var<std::pmr::memory_resource *>
4886  upv (current_mx_memory_resource, &the_mx_preserving_memory_resource);
4887 
4888 #endif
4889 
4890  for (int i = 0; i < nargin; i++)
4891  args(i) = mxArray::as_octave_value (argin[i]);
4892 
4893  return args;
4894 }
4895 
4896 int
4897 mexCallMATLAB (int nargout, mxArray *argout[], int nargin,
4898  mxArray *argin[], const char *fname)
4899 {
4900  octave_value_list args = mx_to_ov_args (nargin, argin);
4901 
4902  octave::interpreter& interp = octave::__get_interpreter__ ();
4903 
4904  bool execution_error = false;
4905 
4906  octave_value_list retval;
4907 
4908  try
4909  {
4910  octave::tree_evaluator& tw = interp.get_evaluator ();
4911 
4912  octave::unwind_action act
4913  ([&tw] (const std::list<octave::octave_lvalue> *lvl)
4914  {
4915  tw.set_lvalue_list (lvl);
4916  }, tw.lvalue_list ());
4917 
4918  tw.set_lvalue_list (nullptr);
4919 
4920  retval = octave::feval (fname, args, nargout);
4921  }
4922  catch (const octave::execution_exception&)
4923  {
4925  {
4926  // FIXME: is there a way to indicate what error occurred?
4927  // Should the error message be displayed here? Do we need to
4928  // save the exception info for lasterror?
4929 
4930  interp.recover_from_exception ();
4931 
4932  execution_error = true;
4933  }
4934  else
4935  {
4936  args.resize (0);
4937  retval.resize (0);
4938 
4939  throw;
4940  }
4941  }
4942 
4943  int num_to_copy = retval.length ();
4944 
4945  if (nargout < retval.length ())
4946  num_to_copy = nargout;
4947 
4948  for (int i = 0; i < num_to_copy; i++)
4949  {
4950  // FIXME: it would be nice to avoid copying the value here,
4951  // but there is no way to steal memory from a matrix, never mind
4952  // that matrix memory is allocated by new[] and mxArray memory
4953  // is allocated by malloc().
4954  argout[i] = mex_context->make_value (retval(i));
4955  }
4956 
4957  while (num_to_copy < nargout)
4958  argout[num_to_copy++] = nullptr;
4959 
4960  return execution_error ? 1 : 0;
4961 }
4962 
4963 mxArray *
4964 mexCallMATLABWithTrap (int nargout, mxArray *argout[], int nargin,
4965  mxArray *argin[], const char *fname)
4966 {
4967  mxArray *mx = nullptr;
4968 
4969  int old_flag = (mex_context ? mex_context->trap_feval_error : 0);
4970  mexSetTrapFlag (1);
4971  if (mexCallMATLAB (nargout, argout, nargin, argin, fname))
4972  {
4973  const char *field_names[] = {"identifier", "message", "case", "stack"};
4974  mx = mxCreateStructMatrix (1, 1, 4, field_names);
4975  mxSetFieldByNumber (mx, 0, 0, mxCreateString ("Octave:MEX"));
4976  std::string msg = "mexCallMATLABWithTrap: function call <"
4977  + std::string (fname) + "> failed";
4978  mxSetFieldByNumber (mx, 0, 1, mxCreateString (msg.c_str ()));
4979  mxSetFieldByNumber (mx, 0, 2, mxCreateCellMatrix (0, 0));
4980  mxSetFieldByNumber (mx, 0, 3, mxCreateStructMatrix (0, 1, 0, nullptr));
4981  }
4982  mexSetTrapFlag (old_flag);
4983 
4984  return mx;
4985 }
4986 
4987 void
4988 mexSetTrapFlag (int flag)
4989 {
4990  if (mex_context)
4991  mex_context->trap_feval_error = flag;
4992 }
4993 
4994 int
4995 mexEvalString (const char *s)
4996 {
4997  int retval = 0;
4998 
4999  octave::interpreter& interp = octave::__get_interpreter__ ();
5000 
5001  int parse_status;
5002  bool execution_error = false;
5003 
5004  octave_value_list ret;
5005 
5006  try
5007  {
5008  ret = interp.eval_string (std::string (s), false, parse_status, 0);
5009  }
5010  catch (const octave::execution_exception&)
5011  {
5012  interp.recover_from_exception ();
5013 
5014  execution_error = true;
5015  }
5016 
5017  if (parse_status || execution_error)
5018  retval = 1;
5019 
5020  return retval;
5021 }
5022 
5023 mxArray *
5024 mexEvalStringWithTrap (const char *s)
5025 {
5026  mxArray *mx = nullptr;
5027 
5028  octave::interpreter& interp = octave::__get_interpreter__ ();
5029 
5030  int parse_status;
5031  bool execution_error = false;
5032 
5033  octave_value_list ret;
5034 
5035  try
5036  {
5037  ret = interp.eval_string (std::string (s), false, parse_status, 0);
5038  }
5039  catch (const octave::execution_exception&)
5040  {
5041  interp.recover_from_exception ();
5042 
5043  execution_error = true;
5044  }
5045 
5046  if (parse_status || execution_error)
5047  {
5048  const char *field_names[] = {"identifier", "message", "case", "stack"};
5049  mx = mxCreateStructMatrix (1, 1, 4, field_names);
5050  mxSetFieldByNumber (mx, 0, 0, mxCreateString ("Octave:MEX"));
5051  std::string msg = "mexEvalStringWithTrap: eval of <"
5052  + std::string (s) + "> failed";
5053  mxSetFieldByNumber (mx, 0, 1, mxCreateString (msg.c_str ()));
5054  mxSetFieldByNumber (mx, 0, 2, mxCreateCellMatrix (0, 0));
5055  mxSetFieldByNumber (mx, 0, 3, mxCreateStructMatrix (0, 1, 0, nullptr));
5056  }
5057 
5058  return mx;
5059 }
5060 
5061 void
5062 mexErrMsgTxt (const char *s)
5063 {
5064  std::size_t len;
5065 
5066  if (s && (len = strlen (s)) > 0)
5067  {
5068  if (s[len - 1] == '\n')
5069  {
5070  std::string s_tmp (s, len - 1);
5071  error ("%s: %s\n", mexFunctionName (), s_tmp.c_str ());
5072  }
5073  else
5074  error ("%s: %s", mexFunctionName (), s);
5075  }
5076  else
5077  {
5078  // For compatibility with Matlab, print an empty message.
5079  // Octave's error routine requires a non-null input so use a SPACE.
5080  error (" ");
5081  }
5082 }
5083 
5084 void
5085 mexErrMsgIdAndTxt (const char *id, const char *fmt, ...)
5086 {
5087  if (fmt && strlen (fmt) > 0)
5088  {
5089  const char *fname = mexFunctionName ();
5090  std::size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
5091  OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
5092  sprintf (tmpfmt, "%s: %s", fname, fmt);
5093  va_list args;
5094  va_start (args, fmt);
5095  verror_with_id (id, tmpfmt, args);
5096  va_end (args);
5097  }
5098  else
5099  {
5100  // For compatibility with Matlab, print an empty message.
5101  // Octave's error routine requires a non-null input so use a SPACE.
5102  error (" ");
5103  }
5104 }
5105 
5106 void
5107 mexWarnMsgTxt (const char *s)
5108 {
5109  std::size_t len;
5110 
5111  if (s && (len = strlen (s)) > 0)
5112  {
5113  if (s[len - 1] == '\n')
5114  {
5115  std::string s_tmp (s, len - 1);
5116  warning ("%s\n", s_tmp.c_str ());
5117  }
5118  else
5119  warning ("%s", s);
5120  }
5121  else
5122  {
5123  // For compatibility with Matlab, print an empty message.
5124  // Octave's warning routine requires a non-null input so use a SPACE.
5125  warning (" ");
5126  }
5127 }
5128 
5129 void
5130 mexWarnMsgIdAndTxt (const char *id, const char *fmt, ...)
5131 {
5132  // FIXME: is this right? What does Matlab do if fmt is NULL or
5133  // an empty string?
5134 
5135  if (fmt && strlen (fmt) > 0)
5136  {
5137  const char *fname = mexFunctionName ();
5138  std::size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
5139  OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
5140  sprintf (tmpfmt, "%s: %s", fname, fmt);
5141  va_list args;
5142  va_start (args, fmt);
5143  vwarning_with_id (id, tmpfmt, args);
5144  va_end (args);
5145  }
5146 }
5147 
5148 int
5149 mexPrintf (const char *fmt, ...)
5150 {
5151  int retval;
5152  va_list args;
5153  va_start (args, fmt);
5154  retval = octave::vformat (octave_stdout, fmt, args);
5155  va_end (args);
5156  return retval;
5157 }
5158 
5159 mxArray *
5160 mexGetVariable (const char *space, const char *name)
5161 {
5162  mxArray *retval = nullptr;
5163 
5164  octave_value val;
5165 
5166  octave::interpreter& interp = octave::__get_interpreter__ ();
5167 
5168  if (! strcmp (space, "global"))
5169  val = interp.global_varval (name);
5170  else
5171  {
5172  // FIXME: should this be in variables.cc?
5173 
5174  octave::unwind_protect frame;
5175 
5176  bool caller = ! strcmp (space, "caller");
5177  bool base = ! strcmp (space, "base");
5178 
5179  if (caller || base)
5180  {
5181  // MEX files don't create a separate frame in the call stack,
5182  // so we are already in the "caller" frame.
5183 
5184  if (base)
5185  {
5186  octave::tree_evaluator& tw = interp.get_evaluator ();
5187 
5188  frame.add (&octave::tree_evaluator::restore_frame, &tw,
5189  tw.current_call_stack_frame_number ());
5190 
5191  tw.goto_base_frame ();
5192  }
5193 
5194  val = interp.varval (name);
5195  }
5196  else
5197  mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
5198  }
5199 
5200  if (val.is_defined ())
5201  {
5202  retval = mex_context->make_value (val);
5203 
5204  retval->set_name (name);
5205  }
5206 
5207  return retval;
5208 }
5209 
5210 const mxArray *
5211 mexGetVariablePtr (const char *space, const char *name)
5212 {
5213  return mexGetVariable (space, name);
5214 }
5215 
5216 int
5217 mexPutVariable (const char *space, const char *name, const mxArray *ptr)
5218 {
5219  if (! ptr)
5220  return 1;
5221 
5222  if (! name)
5223  return 1;
5224 
5225  if (name[0] == '\0')
5226  name = ptr->get_name ();
5227 
5228  if (! name || name[0] == '\0')
5229  return 1;
5230 
5231  octave::interpreter& interp = octave::__get_interpreter__ ();
5232 
5233  if (! strcmp (space, "global"))
5234  {
5235 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
5236 
5237  // Use allocator that doesn't free memory because Octave may mutate
5238  // the value (single element mxArray -> scalar octave_value object,
5239  // for example) and we need these objects to continue to exist after
5240  // mexCallMATLAB returns.
5241 
5242  octave::unwind_protect_var<std::pmr::memory_resource *>
5243  upv (current_mx_memory_resource, &the_mx_preserving_memory_resource);
5244 #endif
5245 
5246  interp.global_assign (name, mxArray::as_octave_value (ptr));
5247  }
5248  else
5249  {
5250  // FIXME: should this be in variables.cc?
5251 
5252  octave::unwind_protect frame;
5253 
5254  bool caller = ! strcmp (space, "caller");
5255  bool base = ! strcmp (space, "base");
5256 
5257  if (caller || base)
5258  {
5259  // MEX files don't create a separate frame in the call stack,
5260  // so we are already in the "caller" frame.
5261 
5262  if (base)
5263  {
5264  octave::tree_evaluator& tw = interp.get_evaluator ();
5265 
5266  frame.add (&octave::tree_evaluator::restore_frame, &tw,
5267  tw.current_call_stack_frame_number ());
5268 
5269  tw.goto_base_frame ();
5270  }
5271 
5272 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
5273 
5274  // Use allocator that doesn't free memory because Octave may
5275  // mutate the value (single element mxArray -> scalar
5276  // octave_value object, for example) and we need these objects
5277  // to continue to exist after mexCallMATLAB returns.
5278 
5279  octave::unwind_protect_var<std::pmr::memory_resource *>
5280  upv (current_mx_memory_resource,
5281  &the_mx_preserving_memory_resource);
5282 #endif
5283 
5284  interp.assign (name, mxArray::as_octave_value (ptr));
5285  }
5286  else
5287  mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
5288  }
5289 
5290  return 0;
5291 }
5292 
5293 void
5295 {
5296  maybe_unmark_array (ptr);
5297 }
5298 
5299 void
5301 {
5302  maybe_unmark (ptr);
5303 }
5304 
5305 int
5306 mexAtExit (void (*f) (void))
5307 {
5308  if (mex_context)
5309  {
5311 
5312  curr_mex_fcn.atexit (f);
5313  }
5314 
5315  return 0;
5316 }
5317 
5318 const mxArray *
5319 mexGet_interleaved (double handle, const char *property)
5320 {
5321  mxArray *m = nullptr;
5322 
5323  octave_value ret
5324  = octave::get_property_from_handle (handle, property, "mexGet");
5325 
5326  if (ret.is_defined ())
5327  m = ret.as_mxArray (true);
5328 
5329  return m;
5330 }
5331 
5332 const mxArray *
5333 mexGet (double handle, const char *property)
5334 {
5335  mxArray *m = nullptr;
5336 
5337  octave_value ret
5338  = octave::get_property_from_handle (handle, property, "mexGet");
5339 
5340  if (ret.is_defined ())
5341  m = ret.as_mxArray (false);
5342 
5343  return m;
5344 }
5345 
5346 int
5347 mexIsGlobal (const mxArray *ptr)
5348 {
5349  return mxIsFromGlobalWS (ptr);
5350 }
5351 
5352 int
5354 {
5355  int retval = 0;
5356 
5357  if (mex_context)
5358  {
5359  const char *fname = mexFunctionName ();
5360 
5361  octave::interpreter& interp = octave::__get_interpreter__ ();
5362 
5363  retval = interp.mislocked (fname);
5364  }
5365 
5366  return retval;
5367 }
5368 
5369 std::map<std::string, int> mex_lock_count;
5370 
5371 void
5372 mexLock (void)
5373 {
5374  if (mex_context)
5375  {
5376  const char *fname = mexFunctionName ();
5377 
5378  if (mex_lock_count.find (fname) == mex_lock_count.end ())
5379  mex_lock_count[fname] = 1;
5380  else
5381  mex_lock_count[fname]++;
5382 
5383  octave::interpreter& interp = octave::__get_interpreter__ ();
5384 
5385  interp.mlock ();
5386  }
5387 }
5388 
5389 int
5390 mexSet (double handle, const char *property, mxArray *val)
5391 {
5392 #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
5393 
5394  // Use allocator that doesn't free memory because Octave may mutate
5395  // the value (single element mxArray -> scalar octave_value object,
5396  // for example) and we need these objects to continue to exist after
5397  // mexCallMATLAB returns.
5398 
5399  octave::unwind_protect_var<std::pmr::memory_resource *>
5400  upv (current_mx_memory_resource, &the_mx_preserving_memory_resource);
5401 
5402 #endif
5403 
5404  bool ret = octave::set_property_in_handle (handle, property,
5406  "mexSet");
5407  return (ret ? 0 : 1);
5408 }
5409 
5410 void
5412 {
5413  if (mex_context)
5414  {
5415  const char *fname = mexFunctionName ();
5416 
5417  auto p = mex_lock_count.find (fname);
5418 
5419  if (p != mex_lock_count.end ())
5420  {
5421  int count = --mex_lock_count[fname];
5422 
5423  if (count == 0)
5424  {
5425  octave::interpreter& interp = octave::__get_interpreter__ ();
5426 
5427  interp.munlock (fname);
5428 
5429  mex_lock_count.erase (p);
5430  }
5431  }
5432  }
5433 }
OCTAVE_END_NAMESPACE(octave)
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:130
OCTARRAY_OVERRIDABLE_FUNC_API const T * data(void) const
Size of the specified dimension.
Definition: Array.h:663
OCTARRAY_API T * fortran_vec(void)
Size of the specified dimension.
Definition: Array-base.cc:1766
Definition: Cell.h:43
Definition: Sparse.h:49
T * xdata(void)
Definition: Sparse.h:576
octave_idx_type * xcidx(void)
Definition: Sparse.h:602
octave_idx_type * xridx(void)
Definition: Sparse.h:589
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
void resize(int n, int fill_value=0)
Definition: dim-vector.h:272
static const bool is_complex
Definition: mex.cc:322
Definition: mex.cc:3412
mxArray * make_value(const octave_value &ov)
Definition: mex.cc:3645
mex & operator=(const mex &)=delete
std::set< void * > m_foreign_memlist
Definition: mex.cc:3718
const char * function_name(void) const
Definition: mex.cc:3448
char * m_fname
Definition: mex.cc:3721
void * calloc(std::size_t n, std::size_t t)
Definition: mex.cc:3506
mex(octave_mex_function &f)
Definition: mex.cc:3415
void unmark_array(mxArray *ptr)
Definition: mex.cc:3610
void free(void *ptr)
Definition: mex.cc:3551
octave_mex_function & m_curr_mex_fcn
Definition: mex.cc:3708
~mex(void)
Definition: mex.cc:3424
void * calloc_unmarked(std::size_t n, std::size_t t)
Definition: mex.cc:3496
void mark(void *ptr)
Definition: mex.cc:3580
static std::set< void * > s_global_memlist
Definition: mex.cc:3724
void * malloc(std::size_t n)
Definition: mex.cc:3486
void unmark(void *ptr)
Definition: mex.cc:3592
void * realloc(void *ptr, std::size_t n)
Definition: mex.cc:3518
mex(const mex &)=delete
void * malloc_unmarked(std::size_t n)
Definition: mex.cc:3469
void global_unmark(void *ptr)
Definition: mex.cc:3693
bool free_value(mxArray *ptr)
Definition: mex.cc:3653
std::set< mxArray * > m_arraylist
Definition: mex.cc:3714
octave_mex_function & current_mex_function(void) const
Definition: mex.cc:3673
void global_mark(void *ptr)
Definition: mex.cc:3682
std::set< void * > m_memlist
Definition: mex.cc:3711
void mark_foreign(void *ptr)
Definition: mex.cc:3619
mxArray * mark_array(mxArray *ptr)
Definition: mex.cc:3604
int trap_feval_error
Definition: mex.cc:3679
void unmark_foreign(void *ptr)
Definition: mex.cc:3630
int set_complex_doubles(mxComplexDouble *d)
Definition: mex.cc:1993
mxSingle * get_singles(void) const
Definition: mex.cc:1826
mxInt16 * get_int16s(void) const
Definition: mex.cc:1836
int set_uint16s(mxUint16 *d)
Definition: mex.cc:1975
mxArray_base * dup(void) const
Definition: mex.cc:1739
mxComplexSingle * get_complex_singles(void) const
Definition: mex.cc:1876
mxArray_base_full(bool interleaved, mxClassID id, mwSize m, mwSize n, bool init=true)
Definition: mex.cc:1675
mxArray_base_full(bool interleaved, mwSize m, const char **str)
Definition: mex.cc:1710
int set_doubles(mxDouble *d)
Definition: mex.cc:1933
int set_int32s(mxInt32 *d)
Definition: mex.cc:1957
mxArray_base_full(bool interleaved, const char *str)
Definition: mex.cc:1697
mxInt64 * get_int64s(void) const
Definition: mex.cc:1846
int set_complex_singles(mxComplexSingle *d)
Definition: mex.cc:1999
void set_data(void *pr)
Definition: mex.cc:1814
~mxArray_base_full(void)
Definition: mex.cc:1744
mxComplexDouble * get_complex_doubles(void) const
Definition: mex.cc:1871
mxUint8 * get_uint8s(void) const
Definition: mex.cc:1851
int set_uint64s(mxUint64 *d)
Definition: mex.cc:1987
void * m_pr
Definition: mex.cc:2247
char * array_to_string(void) const
Definition: mex.cc:2083
mxUint16 * get_uint16s(void) const
Definition: mex.cc:1856
int set_uint32s(mxUint32 *d)
Definition: mex.cc:1981
mxInt32 * get_int32s(void) const
Definition: mex.cc:1841
int set_int16s(mxInt16 *d)
Definition: mex.cc:1951
mxArray_base_full(bool interleaved, mxClassID id, mxLogical val)
Definition: mex.cc:1689
void * get_data(void) const
Definition: mex.cc:1812
octave_value fp_to_ov(const dim_vector &dv) const
Definition: mex.cc:2169
mxArray_base_full(bool interleaved, mxClassID id, double val)
Definition: mex.cc:1681
mxArray_base_full & operator=(const mxArray_base_full &)
octave_value as_octave_value(void) const
Definition: mex.cc:2104
int set_int64s(mxInt64 *d)
Definition: mex.cc:1963
mxUint64 * get_uint64s(void) const
Definition: mex.cc:1866
int set_uint8s(mxUint8 *d)
Definition: mex.cc:1969
int set_singles(mxSingle *d)
Definition: mex.cc:1939
mxDouble * get_doubles(void) const
Definition: mex.cc:1821
mxUint32 * get_uint32s(void) const
Definition: mex.cc:1861
octave_value int_to_ov(const dim_vector &dv) const
Definition: mex.cc:2207
double get_scalar(void) const
Definition: mex.cc:1749
int set_int8s(mxInt8 *d)
Definition: mex.cc:1945
mxArray_base_full(const mxArray_base_full &val)
Definition: mex.cc:2159
mxArray_base_full(bool interleaved, mxClassID id, const dim_vector &dv)
Definition: mex.cc:1670
int get_string(char *buf, mwSize buflen) const
Definition: mex.cc:2057
mxArray_base_full(bool interleaved, mxClassID id, mwSize ndims, const mwSize *dims, bool init=true)
Definition: mex.cc:1664
mxInt8 * get_int8s(void) const
Definition: mex.cc:1831
mxArray_base_sparse & operator=(const mxArray_base_sparse &)
octave_value to_ov(const dim_vector &dv) const
Definition: mex.cc:2634
int set_complex_doubles(mxComplexDouble *d)
Definition: mex.cc:2584
mxDouble * get_doubles(void) const
Definition: mex.cc:2568
void set_ir(mwIndex *ir)
Definition: mex.cc:2596
int set_doubles(mxDouble *d)
Definition: mex.cc:2578
void set_nzmax(mwSize nzmax)
Definition: mex.cc:2600
void set_jc(mwIndex *jc)
Definition: mex.cc:2598
mwSize get_nzmax(void) const
Definition: mex.cc:2594
mxArray_base_sparse(const mxArray_base_sparse &val)
Definition: mex.cc:2527
mxComplexDouble * get_complex_doubles(void) const
Definition: mex.cc:2573
int is_sparse(void) const
Definition: mex.cc:2562
mxArray_base * dup(void) const
Definition: mex.cc:2550
mwIndex * m_ir
Definition: mex.cc:2685
~mxArray_base_sparse(void)
Definition: mex.cc:2555
mwSize m_nzmax
Definition: mex.cc:2682
void * get_data(void) const
Definition: mex.cc:2564
void set_data(void *pr)
Definition: mex.cc:2566
mxArray_base_sparse(bool interleaved, mxClassID id, mwSize m, mwSize n, mwSize nzmax)
Definition: mex.cc:2515
mwIndex * get_jc(void) const
Definition: mex.cc:2592
mwIndex * get_ir(void) const
Definition: mex.cc:2590
octave_value as_octave_value(void) const
Definition: mex.cc:2606
mwIndex * m_jc
Definition: mex.cc:2686
OCTAVE_NORETURN void err_invalid_type(const char *op) const
Definition: mxarray.h:322
OCTINTERP_API mxArray_base(bool interleaved)
Definition: mex.cc:402
virtual mxArray * mutate(void) const
Definition: mxarray.h:307
bool m_interleaved
Definition: mxarray.h:330
virtual int is_logical_scalar(void) const
Definition: mxarray.h:153
std::size_t get_numeric_element_size(std::size_t size) const
Definition: mxarray.h:315
virtual bool is_octave_value(void) const
Definition: mxarray.h:103
virtual octave_value as_octave_value(void) const =0
mxArray_cell & operator=(const mxArray_cell &)
mxArray_cell(bool interleaved, mwSize m, mwSize n)
Definition: mex.cc:3126
~mxArray_cell(void)
Definition: mex.cc:3157
mxArray_cell(const mxArray_cell &val)
Definition: mex.cc:3134
void * get_data(void) const
Definition: mex.cc:3174
void set_data(void *data)
Definition: mex.cc:3176
void set_cell(mwIndex idx, mxArray *val)
Definition: mex.cc:3803
mxArray_base * dup(void) const
Definition: mex.cc:3155
mxArray_cell(bool interleaved, mwSize ndims, const mwSize *dims)
Definition: mex.cc:3114
mxArray ** m_data
Definition: mex.cc:3196
octave_value as_octave_value(void) const
Definition: mex.cc:3178
mxArray * get_cell(mwIndex idx) const
Definition: mex.cc:3167
mxArray_cell(bool interleaved, const dim_vector &dv)
Definition: mex.cc:3120
mxArray_interleaved_full(const char *str)
Definition: mex.cc:2280
mxArray_interleaved_full(mxClassID id, mxLogical val)
Definition: mex.cc:2276
mxArray_base * dup(void) const
Definition: mex.cc:2294
mxArray_interleaved_full(mxClassID id, mwSize m, mwSize n, mxComplexity flag=mxREAL, bool init=true)
Definition: mex.cc:2266
int is_complex(void) const
Definition: mex.cc:2301
void * get_imag_data(void) const
Definition: mex.cc:2303
mxArray_interleaved_full(const mxArray_interleaved_full &val)
Definition: mex.cc:2309
mxArray_interleaved_full(mxClassID id, double val)
Definition: mex.cc:2272
mxArray_interleaved_full(mwSize m, const char **str)
Definition: mex.cc:2285
mxArray_interleaved_full(mxClassID id, mwSize ndims, const mwSize *dims, mxComplexity flag=mxREAL, bool init=true)
Definition: mex.cc:2254
~mxArray_interleaved_full(void)=default
mxArray_interleaved_full & operator=(const mxArray_interleaved_full &)
void set_imag_data(void *)
Definition: mex.cc:2305
mxArray_interleaved_full(mxClassID id, const dim_vector &dv, mxComplexity flag=mxREAL)
Definition: mex.cc:2260
void * get_imag_data(void) const
Definition: mex.cc:2726
mxArray_base * dup(void) const
Definition: mex.cc:2717
mxArray_interleaved_sparse(const mxArray_interleaved_sparse &val)
Definition: mex.cc:2706
int is_complex(void) const
Definition: mex.cc:2724
mxArray_interleaved_sparse & operator=(const mxArray_interleaved_sparse &)
mxArray_interleaved_sparse(mxClassID id, mwSize m, mwSize n, mwSize nzmax, mxComplexity flag=mxREAL)
Definition: mex.cc:2698
void set_imag_data(void *)
Definition: mex.cc:2728
~mxArray_interleaved_sparse(void)=default
void set_cell(mwIndex, mxArray *)
Definition: mex.cc:1218
mxArray * get_field_by_number(mwIndex, int) const
Definition: mex.cc:1494
void set_field_by_number(mwIndex, int, mxArray *)
Definition: mex.cc:1499
int set_complex_singles(mxComplexSingle *)
Definition: mex.cc:1401
int set_int8s(mxInt8 *)
Definition: mex.cc:1356
int set_doubles(mxDouble *)
Definition: mex.cc:1346
mxArray_matlab & operator=(const mxArray_matlab &)
int add_field(const char *)
Definition: mex.cc:1484
int set_uint16s(mxUint16 *)
Definition: mex.cc:1381
mxClassID get_class_id(void) const
Definition: mex.cc:1179
int is_char(void) const
Definition: mex.cc:1069
int is_int64(void) const
Definition: mex.cc:1081
bool is_scalar(void) const
Definition: mex.cc:1174
mxComplexDouble * get_complex_doubles(void) const
Definition: mex.cc:1283
void set_nzmax(mwSize)
Definition: mex.cc:1479
void set_m(mwSize m)
Definition: mex.cc:1132
mwSize get_n(void) const
Definition: mex.cc:1118
mxUint64 * get_uint64s(void) const
Definition: mex.cc:1278
void * get_imag_data(void) const
Definition: mex.cc:1336
int iscell(void) const
Definition: mex.cc:1067
mwIndex * get_ir(void) const
Definition: mex.cc:1454
mxSingle * get_singles(void) const
Definition: mex.cc:1238
int set_dimensions(mwSize *dims, mwSize ndims)
Definition: mex.cc:1136
int set_int64s(mxInt64 *)
Definition: mex.cc:1371
int get_number_of_fields(void) const
Definition: mex.cc:1505
mwIndex calc_single_subscript(mwSize nsubs, mwIndex *subs) const
Definition: mex.cc:1530
~mxArray_matlab(void)
Definition: mex.cc:1061
mwIndex * get_jc(void) const
Definition: mex.cc:1459
int isempty(void) const
Definition: mex.cc:1172
int is_numeric(void) const
Definition: mex.cc:1087
mxArray_matlab(const mxArray_matlab &val)
Definition: mex.cc:1622
int set_uint64s(mxUint64 *)
Definition: mex.cc:1391
void * get_data(void) const
Definition: mex.cc:1228
mxInt8 * get_int8s(void) const
Definition: mex.cc:1243
mxDouble * get_doubles(void) const
Definition: mex.cc:1233
int is_complex(void) const
Definition: mex.cc:1071
mxUint32 * get_uint32s(void) const
Definition: mex.cc:1273
mwSize * m_dims
Definition: mex.cc:1654
char * array_to_string(void) const
Definition: mex.cc:1525
mxArray_matlab(bool interleaved, mxClassID id=mxUNKNOWN_CLASS)
Definition: mex.cc:1562
int is_logical_scalar_true(void) const
Definition: mex.cc:1110
mwSize get_m(void) const
Definition: mex.cc:1116
const char * get_field_name_by_number(int) const
Definition: mex.cc:1510
int is_double(void) const
Definition: mex.cc:1073
int is_logical(void) const
Definition: mex.cc:1085
int is_struct(void) const
Definition: mex.cc:1100
mwSize * get_dimensions(void) const
Definition: mex.cc:1128
void set_n(mwSize n)
Definition: mex.cc:1134
int get_field_number(const char *) const
Definition: mex.cc:1515
char * m_class_name
Definition: mex.cc:1649
mxInt64 * get_int64s(void) const
Definition: mex.cc:1258
mxInt32 * get_int32s(void) const
Definition: mex.cc:1253
int is_function_handle(void) const
Definition: mex.cc:1075
mxArray_matlab(bool interleaved, mxClassID id, const dim_vector &dv)
Definition: mex.cc:1596
void set_jc(mwIndex *)
Definition: mex.cc:1474
int set_int16s(mxInt16 *)
Definition: mex.cc:1361
mxArray_matlab(bool interleaved, mxClassID id, mwSize ndims, const mwSize *dims)
Definition: mex.cc:1567
int is_uint32(void) const
Definition: mex.cc:1104
int is_single(void) const
Definition: mex.cc:1096
int is_int8(void) const
Definition: mex.cc:1083
void set_class_name(const char *name)
Definition: mex.cc:1206
mxArray * get_cell(mwIndex) const
Definition: mex.cc:1213
mwSize get_number_of_dimensions(void) const
Definition: mex.cc:1130
int set_uint32s(mxUint32 *)
Definition: mex.cc:1386
mwSize get_nzmax(void) const
Definition: mex.cc:1464
mxInt16 * get_int16s(void) const
Definition: mex.cc:1248
int is_int16(void) const
Definition: mex.cc:1077
double get_scalar(void) const
Definition: mex.cc:1223
int is_uint8(void) const
Definition: mex.cc:1108
int is_sparse(void) const
Definition: mex.cc:1098
mxArray_matlab(bool interleaved, mxClassID id, mwSize m, mwSize n)
Definition: mex.cc:1613
mxUint8 * get_uint8s(void) const
Definition: mex.cc:1263
int is_uint64(void) const
Definition: mex.cc:1106
void set_ir(mwIndex *)
Definition: mex.cc:1469
const char * get_class_name(void) const
Definition: mex.cc:1181
int set_singles(mxSingle *)
Definition: mex.cc:1351
mxClassID m_id
Definition: mex.cc:1651
void set_imag_data(void *)
Definition: mex.cc:1449
int get_string(char *, mwSize) const
Definition: mex.cc:1520
mxComplexSingle * get_complex_singles(void) const
Definition: mex.cc:1288
std::size_t get_element_size(void) const
Definition: mex.cc:1535
int set_complex_doubles(mxComplexDouble *)
Definition: mex.cc:1396
void remove_field(int)
Definition: mex.cc:1489
mxUint16 * get_uint16s(void) const
Definition: mex.cc:1268
int is_uint16(void) const
Definition: mex.cc:1102
int set_int32s(mxInt32 *)
Definition: mex.cc:1366
mwSize m_ndims
Definition: mex.cc:1653
dim_vector dims_to_dim_vector(void) const
Definition: mex.cc:1632
mwSize get_number_of_elements(void) const
Definition: mex.cc:1162
int set_uint8s(mxUint8 *)
Definition: mex.cc:1376
int is_int32(void) const
Definition: mex.cc:1079
void set_data(void *)
Definition: mex.cc:1341
int is_sparse(void) const
Definition: mex.cc:556
int set_uint16s(mxUint16 *)
Definition: mex.cc:849
bool mutation_needed(void) const
Definition: mex.cc:1001
int set_dimensions(mwSize *, mwSize)
Definition: mex.cc:621
mxClassID get_class_id(void) const
Definition: mex.cc:635
int is_uint16(void) const
Definition: mex.cc:560
mxUint64 * get_uint64s(void) const
Definition: mex.cc:800
const char * get_class_name(void) const
Definition: mex.cc:675
int add_field(const char *)
Definition: mex.cc:898
void * get_data(void) const
Definition: mex.cc:747
void set_nzmax(mwSize)
Definition: mex.cc:895
octave_value as_octave_value(void) const
Definition: mex.cc:1013
int isreal(void) const
Definition: mex.cc:570
mwSize get_number_of_elements(void) const
Definition: mex.cc:623
mxSingle * get_singles(void) const
Definition: mex.cc:784
int set_doubles(mxDouble *)
Definition: mex.cc:842
void set_cell(mwIndex, mxArray *)
Definition: mex.cc:725
void set_ir(mwIndex *)
Definition: mex.cc:889
void set_data(void *)
Definition: mex.cc:840
int set_singles(mxSingle *)
Definition: mex.cc:843
int set_uint32s(mxUint32 *)
Definition: mex.cc:850
int is_logical(void) const
Definition: mex.cc:550
int is_uint8(void) const
Definition: mex.cc:566
~mxArray_octave_value(void)
Definition: mex.cc:524
mxUint16 * get_uint16s(void) const
Definition: mex.cc:796
int set_int64s(mxInt64 *)
Definition: mex.cc:847
std::size_t get_element_size(void) const
Definition: mex.cc:973
void set_jc(mwIndex *)
Definition: mex.cc:892
mxArray_octave_value(const mxArray_octave_value &arg)
Definition: mex.cc:1017
const char * get_field_name_by_number(int) const
Definition: mex.cc:910
int is_uint64(void) const
Definition: mex.cc:564
int set_uint8s(mxUint8 *)
Definition: mex.cc:848
mxUint32 * get_uint32s(void) const
Definition: mex.cc:798
mxInt16 * get_int16s(void) const
Definition: mex.cc:788
mxUint8 * get_uint8s(void) const
Definition: mex.cc:794
int is_int8(void) const
Definition: mex.cc:548
mxArray_octave_value & operator=(const mxArray_octave_value &)=delete
void set_m(mwSize)
Definition: mex.cc:618
int is_int64(void) const
Definition: mex.cc:546
int set_uint64s(mxUint64 *)
Definition: mex.cc:851
int set_complex_doubles(mxComplexDouble *)
Definition: mex.cc:853
void set_class_name(const char *)
Definition: mex.cc:687
int iscell(void) const
Definition: mex.cc:532
int is_numeric(void) const
Definition: mex.cc:552
mwSize get_m(void) const
Definition: mex.cc:577
mwSize * get_dimensions(void) const
Definition: mex.cc:592
octave_value m_val
Definition: mex.cc:1034
int is_int16(void) const
Definition: mex.cc:542
int is_char(void) const
Definition: mex.cc:534
mxInt64 * get_int64s(void) const
Definition: mex.cc:792
mxArray * get_cell(mwIndex) const
Definition: mex.cc:722
void set_imag_data(void *)
Definition: mex.cc:868
int set_int8s(mxInt8 *)
Definition: mex.cc:844
int get_field_number(const char *) const
Definition: mex.cc:912
void set_property(mwIndex idx, const char *pname, const mxArray *pval)
Definition: mex.cc:709
bool is_scalar(void) const
Definition: mex.cc:627
void remove_field(int)
Definition: mex.cc:901
int get_number_of_fields(void) const
Definition: mex.cc:908
int set_int32s(mxInt32 *)
Definition: mex.cc:846
char * array_to_string(void) const
Definition: mex.cc:937
mwIndex calc_single_subscript(mwSize nsubs, mwIndex *subs) const
Definition: mex.cc:965
int is_int32(void) const
Definition: mex.cc:544
mxComplexDouble * get_complex_doubles(void) const
Definition: mex.cc:803
bool is_octave_value(void) const
Definition: mex.cc:530
void * get_imag_data(void) const
Definition: mex.cc:827
void set_n(mwSize)
Definition: mex.cc:619
mxArray_base * dup(void) const
Definition: mex.cc:485
mxArray_octave_value(bool interleaved, const octave_value &ov)
Definition: mex.cc:474
int isempty(void) const
Definition: mex.cc:625
mxComplexSingle * get_complex_singles(void) const
Definition: mex.cc:806
mwIndex * get_jc(void) const
Definition: mex.cc:878
mwIndex * get_ir(void) const
Definition: mex.cc:870
mwSize get_n(void) const
Definition: mex.cc:579
int is_range(void) const
Definition: mex.cc:568
mxInt8 * get_int8s(void) const
Definition: mex.cc:786
int is_complex(void) const
Definition: mex.cc:536
int set_int16s(mxInt16 *)
Definition: mex.cc:845
mxInt32 * get_int32s(void) const
Definition: mex.cc:790
mwSize get_nzmax(void) const
Definition: mex.cc:886
mxArray * get_property(mwIndex idx, const char *pname) const
Definition: mex.cc:689
int is_double(void) const
Definition: mex.cc:538
void request_mutation(void) const
Definition: mex.cc:1003
int is_uint32(void) const
Definition: mex.cc:562
T * get_data(mxClassID class_id, mxComplexity complexity) const
Definition: mex.cc:764
int is_single(void) const
Definition: mex.cc:554
int get_string(char *buf, mwSize buflen) const
Definition: mex.cc:914
int set_complex_singles(mxComplexSingle *)
Definition: mex.cc:854
mxArray * as_mxArray(void) const
Definition: mex.cc:487
double get_scalar(void) const
Definition: mex.cc:727
char * m_class_name
Definition: mex.cc:1043
mwSize get_number_of_dimensions(void) const
Definition: mex.cc:610
void set_field_by_number(mwIndex, int, mxArray *)
Definition: mex.cc:906
mxDouble * get_doubles(void) const
Definition: mex.cc:782
int is_logical_scalar_true(void) const
Definition: mex.cc:572
int is_function_handle(void) const
Definition: mex.cc:540
mxArray * get_field_by_number(mwIndex, int) const
Definition: mex.cc:903
mxArray * mutate(void) const
Definition: mex.cc:1011
mxClassID m_id
Definition: mex.cc:1042
int is_struct(void) const
Definition: mex.cc:558
mwSize * m_dims
Definition: mex.cc:1045
mxArray_separate_full(const mxArray_separate_full &val)
Definition: mex.cc:2470
mxArray_separate_full(const char *str)
Definition: mex.cc:2353
int set_complex_uint32s(mxComplexUint32 *)
Definition: mex.cc:2430
mxUint8 * get_uint8s(void) const
Definition: mex.cc:2389
mxArray_separate_full(mxClassID id, mwSize m, mwSize n, mxComplexity flag=mxREAL, bool init=true)
Definition: mex.cc:2337
mxInt32 * get_int32s(void) const
Definition: mex.cc:2387
int is_complex(void) const
Definition: mex.cc:2377
mxInt16 * get_int16s(void) const
Definition: mex.cc:2386
mxComplexDouble * get_complex_doubles(void) const
Definition: mex.cc:2394
void set_imag_data(void *pi)
Definition: mex.cc:2381
mxComplexUint64 * get_complex_uint64s(void) const
Definition: mex.cc:2406
mxComplexInt8 * get_complex_int8s(void) const
Definition: mex.cc:2399
mxInt64 * get_int64s(void) const
Definition: mex.cc:2388
int set_complex_int16s(mxComplexInt16 *)
Definition: mex.cc:2425
int set_uint64s(mxUint64 *)
Definition: mex.cc:2417
mxArray_separate_full & operator=(const mxArray_separate_full &)
int set_int16s(mxInt16 *)
Definition: mex.cc:2411
int set_int32s(mxInt32 *)
Definition: mex.cc:2412
mxUint16 * get_uint16s(void) const
Definition: mex.cc:2390
int set_uint8s(mxUint8 *)
Definition: mex.cc:2414
mxArray_separate_full(mxClassID id, mwSize ndims, const mwSize *dims, mxComplexity flag=mxREAL, bool init=true)
Definition: mex.cc:2321
mxArray_separate_full(mxClassID id, mxLogical val)
Definition: mex.cc:2349
int set_complex_int32s(mxComplexInt32 *)
Definition: mex.cc:2426
int set_complex_uint64s(mxComplexUint64 *)
Definition: mex.cc:2431
octave_value as_octave_value(void) const
Definition: mex.cc:2433
int set_complex_int8s(mxComplexInt8 *)
Definition: mex.cc:2424
int set_int64s(mxInt64 *)
Definition: mex.cc:2413
~mxArray_separate_full(void)
Definition: mex.cc:2372
int set_doubles(mxDouble *)
Definition: mex.cc:2408
mxUint32 * get_uint32s(void) const
Definition: mex.cc:2391
mxComplexUint32 * get_complex_uint32s(void) const
Definition: mex.cc:2405
mxArray_base * dup(void) const
Definition: mex.cc:2367
int set_singles(mxSingle *)
Definition: mex.cc:2409
octave_value to_ov(const dim_vector &dv) const
Definition: mex.cc:2484
mxComplexUint8 * get_complex_uint8s(void) const
Definition: mex.cc:2403
int set_uint32s(mxUint32 *)
Definition: mex.cc:2416
int set_complex_int64s(mxComplexInt64 *)
Definition: mex.cc:2427
int set_complex_doubles(mxComplexDouble *)
Definition: mex.cc:2419
mxComplexInt64 * get_complex_int64s(void) const
Definition: mex.cc:2402
int set_complex_singles(mxComplexSingle *)
Definition: mex.cc:2420
mxArray_separate_full(mxClassID id, const dim_vector &dv, mxComplexity flag=mxREAL)
Definition: mex.cc:2329
mxComplexInt32 * get_complex_int32s(void) const
Definition: mex.cc:2401
mxSingle * get_singles(void) const
Definition: mex.cc:2384
mxArray_separate_full(mwSize m, const char **str)
Definition: mex.cc:2358
int set_complex_uint16s(mxComplexUint16 *)
Definition: mex.cc:2429
mxArray_separate_full(mxClassID id, double val)
Definition: mex.cc:2345
int set_uint16s(mxUint16 *)
Definition: mex.cc:2415
mxInt8 * get_int8s(void) const
Definition: mex.cc:2385
mxComplexUint16 * get_complex_uint16s(void) const
Definition: mex.cc:2404
mxComplexInt16 * get_complex_int16s(void) const
Definition: mex.cc:2400
int set_complex_uint8s(mxComplexUint8 *)
Definition: mex.cc:2428
mxUint64 * get_uint64s(void) const
Definition: mex.cc:2392
mxDouble * get_doubles(void) const
Definition: mex.cc:2383
int set_int8s(mxInt8 *)
Definition: mex.cc:2410
void * get_imag_data(void) const
Definition: mex.cc:2379
mxComplexSingle * get_complex_singles(void) const
Definition: mex.cc:2395
mxComplexDouble * get_complex_doubles(void) const
Definition: mex.cc:2788
void set_imag_data(void *pi)
Definition: mex.cc:2785
int is_complex(void) const
Definition: mex.cc:2778
int set_doubles(mxDouble *)
Definition: mex.cc:2790
mxArray_separate_sparse(mxClassID id, mwSize m, mwSize n, mwSize nzmax, mxComplexity flag=mxREAL)
Definition: mex.cc:2741
mxArray_separate_sparse(const mxArray_separate_sparse &val)
Definition: mex.cc:2751
octave_value as_octave_value(void) const
Definition: mex.cc:2793
void * get_imag_data(void) const
Definition: mex.cc:2783
int set_complex_doubles(mxComplexDouble *)
Definition: mex.cc:2791
~mxArray_separate_sparse(void)
Definition: mex.cc:2773
mxArray_base * dup(void) const
Definition: mex.cc:2768
mxDouble * get_doubles(void) const
Definition: mex.cc:2787
mxArray_separate_sparse & operator=(const mxArray_separate_sparse &)
mxArray_struct(bool interleaved, mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
Definition: mex.cc:2847
~mxArray_struct(void)
Definition: mex.cc:2923
int get_number_of_fields(void) const
Definition: mex.cc:3046
mxArray ** m_data
Definition: mex.cc:3105
octave_value as_octave_value(void) const
Definition: mex.cc:3073
mxArray_struct(bool interleaved, const dim_vector &dv, int num_keys, const char **keys)
Definition: mex.cc:2860
void remove_field(int key_num)
Definition: mex.cc:2987
mxArray_struct(const mxArray_struct &val)
Definition: mex.cc:2888
mxArray_struct & operator=(const mxArray_struct &val)
int get_field_number(const char *key) const
Definition: mex.cc:3053
mxArray * get_field_by_number(mwIndex index, int key_num) const
Definition: mex.cc:3038
mxArray_struct(bool interleaved, mwSize m, mwSize n, int num_keys, const char **keys)
Definition: mex.cc:2873
const char * get_field_name_by_number(int key_num) const
Definition: mex.cc:3048
void set_data(void *data)
Definition: mex.cc:3071
int m_nfields
Definition: mex.cc:3101
int add_field(const char *key)
Definition: mex.cc:2938
void init(const char **keys)
Definition: mex.cc:2915
mxArray_base * dup(void) const
Definition: mex.cc:2921
void * get_data(void) const
Definition: mex.cc:3069
char ** m_fields
Definition: mex.cc:3103
void set_field_by_number(mwIndex index, int key_num, mxArray *val)
Definition: mex.cc:3796
mxInt64 * get_int64s(void) const
Definition: mxarray.h:514
int set_uint8s(mxUint8 *data)
Definition: mxarray.h:585
mxClassID get_class_id(void) const
Definition: mxarray.h:476
int is_int64(void) const
Definition: mxarray.h:422
int is_single(void) const
Definition: mxarray.h:430
int set_complex_singles(mxComplexSingle *data)
Definition: mxarray.h:600
OCTINTERP_API void maybe_mutate(void) const
Definition: mex.cc:3386
int set_uint32s(mxUint32 *data)
Definition: mxarray.h:591
void * get_imag_data(void) const
Definition: mxarray.h:562
OCTINTERP_API void set_name(const char *name)
Definition: mex.cc:3281
const char * get_class_name(void) const
Definition: mxarray.h:478
mxInt8 * get_int8s(void) const
Definition: mxarray.h:505
void set_n(mwSize n)
Definition: mxarray.h:460
char * m_name
Definition: mxarray.h:749
int is_logical_scalar_true(void) const
Definition: mxarray.h:446
int is_uint32(void) const
Definition: mxarray.h:438
int is_char(void) const
Definition: mxarray.h:408
OCTINTERP_API ~mxArray(void)
Definition: mex.cc:3273
void set_property(mwIndex idx, const char *pname, const mxArray *pval)
Definition: mxarray.h:483
int set_singles(mxSingle *data)
Definition: mxarray.h:570
int set_uint16s(mxUint16 *data)
Definition: mxarray.h:588
void set_m(mwSize m)
Definition: mxarray.h:458
static OCTINTERP_API void * alloc(bool init, std::size_t n, std::size_t t)
Definition: mex.cc:3747
mxArray * get_property(mwIndex idx, const char *pname) const
Definition: mxarray.h:480
int set_uint64s(mxUint64 *data)
Definition: mxarray.h:594
mxArray * dup(void) const
Definition: mxarray.h:380
void * get_data(void) const
Definition: mxarray.h:497
mwIndex * get_jc(void) const
Definition: mxarray.h:634
mwIndex calc_single_subscript(mwSize nsubs, mwIndex *subs) const
Definition: mxarray.h:669
int is_function_handle(void) const
Definition: mxarray.h:416
int set_dimensions(mwSize *dims_arg, mwSize ndims_arg)
Definition: mxarray.h:462
static char * strsave(const char *str)
Definition: mxarray.h:685
int isempty(void) const
Definition: mxarray.h:468
mwSize get_m(void) const
Definition: mxarray.h:449
void set_data(void *pr)
Definition: mxarray.h:565
int is_uint64(void) const
Definition: mxarray.h:440
int is_struct(void) const
Definition: mxarray.h:434
static OCTINTERP_API void * calloc(std::size_t n, std::size_t t)
Definition: mex.cc:3741
OCTINTERP_API mxArray(bool interleaved, const octave_value &ov)
Definition: mex.cc:3201
int set_complex_doubles(mxComplexDouble *data)
Definition: mxarray.h:597
int get_field_number(const char *key) const
Definition: mxarray.h:661
std::size_t get_element_size(void) const
Definition: mxarray.h:672
mxInt32 * get_int32s(void) const
Definition: mxarray.h:511
int iscell(void) const
Definition: mxarray.h:406
mxArray * get_field_by_number(mwIndex index, int key_num) const
Definition: mxarray.h:649
int add_field(const char *key)
Definition: mxarray.h:644
int is_int8(void) const
Definition: mxarray.h:424
int get_number_of_fields(void) const
Definition: mxarray.h:655
int is_sparse(void) const
Definition: mxarray.h:432
mxDouble * get_doubles(void) const
Definition: mxarray.h:499
mxComplexDouble * get_complex_doubles(void) const
Definition: mxarray.h:529
mxUint16 * get_uint16s(void) const
Definition: mxarray.h:520
mxUint8 * get_uint8s(void) const
Definition: mxarray.h:517
int is_double(void) const
Definition: mxarray.h:414
mwSize get_nzmax(void) const
Definition: mxarray.h:636
mxArray_base * m_rep
Definition: mxarray.h:747
int is_uint8(void) const
Definition: mxarray.h:442
mwIndex * get_ir(void) const
Definition: mxarray.h:632
static OCTINTERP_API octave_value as_octave_value(const mxArray *ptr, bool null_is_empty=true)
Definition: mex.cc:3288
int set_int32s(mxInt32 *data)
Definition: mxarray.h:579
bool is_scalar(void) const
Definition: mxarray.h:470
int set_int64s(mxInt64 *data)
Definition: mxarray.h:582
int set_doubles(mxDouble *data)
Definition: mxarray.h:567
void set_nzmax(mwSize nzmax)
Definition: mxarray.h:642
int is_logical(void) const
Definition: mxarray.h:426
int is_int16(void) const
Definition: mxarray.h:418
double get_scalar(void) const
Definition: mxarray.h:495
void set_jc(mwIndex *jc)
Definition: mxarray.h:640
mwSize get_number_of_dimensions(void) const
Definition: mxarray.h:455
int set_int16s(mxInt16 *data)
Definition: mxarray.h:576
const char * get_name(void) const
Definition: mxarray.h:472
int is_numeric(void) const
Definition: mxarray.h:428
mwSize get_number_of_elements(void) const
Definition: mxarray.h:465
const char * get_field_name_by_number(int key_num) const
Definition: mxarray.h:658
int get_string(char *buf, mwSize buflen) const
Definition: mxarray.h:664
mxUint64 * get_uint64s(void) const
Definition: mxarray.h:526
int is_class(const char *name_arg) const
Definition: mxarray.h:410
int set_int8s(mxInt8 *data)
Definition: mxarray.h:573
mwSize get_n(void) const
Definition: mxarray.h:451
void set_class_name(const char *name_arg)
Definition: mxarray.h:486
int is_complex(void) const
Definition: mxarray.h:412
mxUint32 * get_uint32s(void) const
Definition: mxarray.h:523
int is_uint16(void) const
Definition: mxarray.h:436
void set_field_by_number(mwIndex index, int key_num, mxArray *val)
Definition: mxarray.h:652
void set_cell(mwIndex idx, mxArray *val)
Definition: mxarray.h:492
mxArray * get_cell(mwIndex idx) const
Definition: mxarray.h:489
static OCTINTERP_API mxArray_base * create_rep(bool interleaved, const octave_value &ov)
Definition: mex.cc:3304
void set_ir(mwIndex *ir)
Definition: mxarray.h:638
char * array_to_string(void) const
Definition: mxarray.h:667
int is_logical_scalar(void) const
Definition: mxarray.h:444
static OCTINTERP_API void * malloc(std::size_t n)
Definition: mex.cc:3735
OCTINTERP_API octave_value as_octave_value(void) const
Definition: mex.cc:3298
mwSize * get_dimensions(void) const
Definition: mxarray.h:453
void set_imag_data(void *pi)
Definition: mxarray.h:630
mxSingle * get_singles(void) const
Definition: mxarray.h:502
mxInt16 * get_int16s(void) const
Definition: mxarray.h:508
void remove_field(int key_num)
Definition: mxarray.h:646
int is_int32(void) const
Definition: mxarray.h:420
mxComplexSingle * get_complex_singles(void) const
Definition: mxarray.h:532
octave_value get_property(octave_idx_type idx, const std::string &name) const
Definition: ov-classdef.h:140
void set_property(octave_idx_type idx, const std::string &name, const octave_value &pval)
Definition: ov-classdef.h:133
std::string name(void) const
Definition: ov-fcn.h:208
bool is_fmex(void) const
Definition: ov-mex-fcn.h:106
void * mex_fcn_ptr(void) const
Definition: ov-mex-fcn.h:104
void atexit(void(*fcn)(void))
Definition: ov-mex-fcn.h:100
bool use_interleaved_complex(void) const
Definition: ov-mex-fcn.h:94
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
octave_idx_type length(void) const
Definition: ovl.h:113
bool is_classdef_object(void) const
Definition: ov.h:700
bool iscell(void) const
Definition: ov.h:649
bool isreal(void) const
Definition: ov.h:783
bool issparse(void) const
Definition: ov.h:798
bool is_uint16_type(void) const
Definition: ov.h:766
const octave_idx_type * mex_get_ir(void) const
Definition: ov.h:1520
const octave_idx_type * mex_get_jc(void) const
Definition: ov.h:1526
bool is_true(void) const
Definition: ov.h:803
bool is_int8_type(void) const
Definition: ov.h:751
octave_idx_type rows(void) const
Definition: ov.h:590
bool isnumeric(void) const
Definition: ov.h:795
octave_idx_type numel(void) const
Definition: ov.h:604
bool is_string(void) const
Definition: ov.h:682
bool is_defined(void) const
Definition: ov.h:637
charNDArray char_array_value(bool frc_str_conv=false) const
Definition: ov.h:942
bool is_double_type(void) const
Definition: ov.h:740
bool is_function_handle(void) const
Definition: ov.h:813
std::string class_name(void) const
Definition: ov.h:1454
bool is_uint32_type(void) const
Definition: ov.h:769
int ndims(void) const
Definition: ov.h:596
bool is_int64_type(void) const
Definition: ov.h:760
bool isstruct(void) const
Definition: ov.h:694
double scalar_value(bool frc_str_conv=false) const
Definition: ov.h:892
octave_idx_type nfields(void) const
Definition: ov.h:614
bool is_int32_type(void) const
Definition: ov.h:757
bool is_uint64_type(void) const
Definition: ov.h:772
octave_idx_type nzmax(void) const
Definition: ov.h:612
bool is_int16_type(void) const
Definition: ov.h:754
bool is_range(void) const
Definition: ov.h:691
bool isempty(void) const
Definition: ov.h:646
bool is_single_type(void) const
Definition: ov.h:743
OCTINTERP_API const void * mex_get_data(mxClassID class_id=mxUNKNOWN_CLASS, mxComplexity complexity=mxREAL) const
mxArray * as_mxArray(bool interleaved=false) const
Definition: ov.h:1531
bool is_uint8_type(void) const
Definition: ov.h:763
bool iscomplex(void) const
Definition: ov.h:786
bool islogical(void) const
Definition: ov.h:780
dim_vector dims(void) const
Definition: ov.h:586
OCTINTERP_API octave_classdef * classdef_object_value(bool silent=false) const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void warning(const char *fmt,...)
Definition: error.cc:1054
void vwarning_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:1063
void verror_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:1018
void error(const char *fmt,...)
Definition: error.cc:979
#define panic_impossible()
Definition: error.h:508
octave_f77_int_type F77_INT
Definition: f77-fcn.h:306
bool set_property_in_handle(double handle, const std::string &property, const octave_value &arg, const std::string &fcn)
Definition: graphics.cc:14305
octave_value get_property_from_handle(double handle, const std::string &property, const std::string &fcn)
Definition: graphics.cc:14289
interpreter & __get_interpreter__(void)
tree_evaluator & __get_evaluator__(void)
double lo_ieee_inf_value(void)
Definition: lo-ieee.cc:68
double lo_ieee_nan_value(void)
Definition: lo-ieee.cc:84
#define lo_ieee_isnan(x)
Definition: lo-ieee.h:100
#define lo_ieee_isinf(x)
Definition: lo-ieee.h:108
#define lo_ieee_isfinite(x)
Definition: lo-ieee.h:104
F77_RET_T(F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, F77_CONST_CHAR_ARG_DECL, const F77_INT &, const F77_INT &, const F77_INT &, F77_INT &, F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, F77_DBLE *, F77_DBLE *, const F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, const F77_INT &, F77_DBLE *, F77_INT *, F77_INT &F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE const F77_DBLE * f
static const double pi
Definition: lo-specfun.cc:1944
static char * strsave(const char *s)
Definition: main.in.cc:214
void mxSetIr(mxArray *ptr, mwIndex *ir)
Definition: mex.cc:4680
OCTINTERP_API mxUint16 * mxGetUint16s(const mxArray *p)
Definition: mex.cc:4419
void mxSetCell(mxArray *ptr, mwIndex idx, mxArray *val)
Definition: mex.cc:4655
bool mxIsUint16(const mxArray *ptr)
Definition: mex.cc:4226
std::size_t mxGetM(const mxArray *ptr)
Definition: mex.cc:4288
OCTINTERP_API int mxSetDoubles(mxArray *p, mxDouble *d)
Definition: mex.cc:4500
OCTINTERP_API mxDouble * mxGetDoubles(const mxArray *p)
Definition: mex.cc:4384
void mexWarnMsgIdAndTxt(const char *id, const char *fmt,...)
Definition: mex.cc:5130
OCTINTERP_API int mxSetUint8s(mxArray *p, mxUint8 *d)
Definition: mex.cc:4530
#define CONST_MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL)
Definition: mex.cc:464
void * mxGetData(const mxArray *ptr)
Definition: mex.cc:4367
void * mxMalloc(std::size_t n)
Definition: mex.cc:3859
mwIndex mxCalcSingleSubscript(const mxArray *ptr, mwSize nsubs, mwIndex *subs)
Definition: mex.cc:4767
OCTINTERP_API int mxSetInt16s(mxArray *p, mxInt16 *d)
Definition: mex.cc:4515
OCTINTERP_API mxInt64 * mxGetInt64s(const mxArray *p)
Definition: mex.cc:4409
bool mxIsFunctionHandle(const mxArray *ptr)
Definition: mex.cc:4166
bool mxIsStruct(const mxArray *ptr)
Definition: mex.cc:4220
int mxGetFieldNumber(const mxArray *ptr, const char *key)
Definition: mex.cc:4749
void mexErrMsgTxt(const char *s)
Definition: mex.cc:5062
mex * mex_context
Definition: mex.cc:3732
void mxSetField(mxArray *ptr, mwIndex index, const char *key, mxArray *val)
Definition: mex.cc:4724
OCTINTERP_API mxArray * mxCreateCellMatrix_interleaved(mwSize m, mwSize n)
Definition: mex.cc:3900
void(* cmex_fptr)(int nlhs, mxArray **plhs, int nrhs, mxArray **prhs)
Definition: mex.cc:4780
bool mxIsUint32(const mxArray *ptr)
Definition: mex.cc:4232
void mxSetProperty(mxArray *ptr, mwIndex idx, const char *property_name, const mxArray *property_value)
Definition: mex.cc:4635
OCTINTERP_API int mxSetComplexDoubles(mxArray *p, mxComplexDouble *d)
Definition: mex.cc:4550
OCTINTERP_API mxUint64 * mxGetUint64s(const mxArray *p)
Definition: mex.cc:4429
bool mxIsComplex(const mxArray *ptr)
Definition: mex.cc:4154
OCTINTERP_API mxArray * mxCreateCharArray_interleaved(mwSize ndims, const mwSize *dims)
Definition: mex.cc:3912
OCTINTERP_API mxComplexDouble * mxGetComplexDoubles(const mxArray *p)
Definition: mex.cc:4434
OCTINTERP_API mxArray * mxCreateString(const char *str)
Definition: mex.cc:4086
OCTINTERP_API mxArray * mxCreateSparseLogicalMatrix_interleaved(mwSize m, mwSize n, mwSize nzmax)
Definition: mex.cc:4068
OCTINTERP_API mxArray * mxCreateCellArray(mwSize ndims, const mwSize *dims)
Definition: mex.cc:3894
OCTINTERP_API int mxSetUint32s(mxArray *p, mxUint32 *d)
Definition: mex.cc:4540
OCTINTERP_API int mxSetInt8s(mxArray *p, mxInt8 *d)
Definition: mex.cc:4510
OCTINTERP_API mxArray * mxCreateNumericMatrix(mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:4017
int mexAtExit(void(*f)(void))
Definition: mex.cc:5306
OCTINTERP_API int mxSetUint16s(mxArray *p, mxUint16 *d)
Definition: mex.cc:4535
bool mxIsFinite(const double v)
Definition: mex.cc:3816
OCTINTERP_API mxSingle * mxGetSingles(const mxArray *p)
Definition: mex.cc:4389
bool mxIsScalar(const mxArray *ptr)
Definition: mex.cc:4271
bool mxIsFromGlobalWS(const mxArray *)
Definition: mex.cc:4279
void mxSetFieldByNumber(mxArray *ptr, mwIndex index, int key_num, mxArray *val)
Definition: mex.cc:4731
const char * mxGetClassName(const mxArray *ptr)
Definition: mex.cc:4623
bool mxIsLogicalScalarTrue(const mxArray *ptr)
Definition: mex.cc:4258
OCTINTERP_API int mxSetInt32s(mxArray *p, mxInt32 *d)
Definition: mex.cc:4520
OCTINTERP_API mxArray * mxCreateSparse(mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
Definition: mex.cc:4061
static octave_value_list mx_to_ov_args(int nargin, mxArray *argin[])
Definition: mex.cc:4868
OCTINTERP_API mxArray * mxCreateStructArray(mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
Definition: mex.cc:4099
OCTINTERP_API void * mxGetImagData(const mxArray *ptr)
Definition: mex.cc:4379
mxClassID mxGetClassID(const mxArray *ptr)
Definition: mex.cc:4617
bool mxIsLogical(const mxArray *ptr)
Definition: mex.cc:4196
mxArray * mxGetProperty(const mxArray *ptr, mwIndex idx, const char *property_name)
Definition: mex.cc:4642
std::map< std::string, int > mex_lock_count
Definition: mex.cc:5369
void mexWarnMsgTxt(const char *s)
Definition: mex.cc:5107
OCTINTERP_API mxInt16 * mxGetInt16s(const mxArray *p)
Definition: mex.cc:4399
void mxSetData(mxArray *ptr, void *pr)
Definition: mex.cc:4495
const char * mexFunctionName(void)
Definition: mex.cc:4862
mwIndex * mxGetIr(const mxArray *ptr)
Definition: mex.cc:4662
OCTINTERP_API int mxSetUint64s(mxArray *p, mxUint64 *d)
Definition: mex.cc:4545
OCTINTERP_API mxInt8 * mxGetInt8s(const mxArray *p)
Definition: mex.cc:4394
bool mxIsInt64(const mxArray *ptr)
Definition: mex.cc:4184
mxArray * mxGetFieldByNumber(const mxArray *ptr, mwIndex index, int key_num)
Definition: mex.cc:4718
mxArray * mexCallMATLABWithTrap(int nargout, mxArray *argout[], int nargin, mxArray *argin[], const char *fname)
Definition: mex.cc:4964
int mxSetDimensions(mxArray *ptr, const mwSize *dims, mwSize ndims)
Definition: mex.cc:4331
std::size_t mxGetNumberOfElements(const mxArray *ptr)
Definition: mex.cc:4312
octave_value_list call_mex(octave_mex_function &mex_fcn, const octave_value_list &args, int nargout_arg)
Definition: mex.cc:4787
int mexPrintf(const char *fmt,...)
Definition: mex.cc:5149
bool mxIsChar(const mxArray *ptr)
Definition: mex.cc:4142
bool mxIsInf(const double v)
Definition: mex.cc:3822
bool mxIsUint8(const mxArray *ptr)
Definition: mex.cc:4244
void mxDestroyArray(mxArray *ptr)
Definition: mex.cc:4128
void mxSetNzmax(mxArray *ptr, mwSize nzmax)
Definition: mex.cc:4692
bool mxIsSingle(const mxArray *ptr)
Definition: mex.cc:4208
void mexErrMsgIdAndTxt(const char *id, const char *fmt,...)
Definition: mex.cc:5085
F77_RET_T(* fmex_fptr)(F77_INT &nlhs, mxArray **plhs, F77_INT &nrhs, mxArray **prhs)
Definition: mex.cc:4781
int mxAddField(mxArray *ptr, const char *key)
Definition: mex.cc:4699
void mexMakeMemoryPersistent(void *ptr)
Definition: mex.cc:5300
bool mxIsInt8(const mxArray *ptr)
Definition: mex.cc:4190
OCTINTERP_API mxComplexSingle * mxGetComplexSingles(const mxArray *p)
Definition: mex.cc:4439
std::size_t mxGetElementSize(const mxArray *ptr)
Definition: mex.cc:4773
OCTINTERP_API void mxSetImagData(mxArray *ptr, void *pi)
Definition: mex.cc:4610
OCTINTERP_API mxArray * mxCreateLogicalArray(mwSize ndims, const mwSize *dims)
Definition: mex.cc:3966
int mexCallMATLAB(int nargout, mxArray *argout[], int nargin, mxArray *argin[], const char *fname)
Definition: mex.cc:4897
bool mxIsNaN(const double v)
Definition: mex.cc:3828
OCTINTERP_API mxArray * mxCreateCharArray(mwSize ndims, const mwSize *dims)
Definition: mex.cc:3918
OCTINTERP_API mxUint8 * mxGetUint8s(const mxArray *p)
Definition: mex.cc:4414
void mxSetPr(mxArray *ptr, double *pr)
Definition: mex.cc:4489
mxArray * mexEvalStringWithTrap(const char *s)
Definition: mex.cc:5024
mxArray * mexGetVariable(const char *space, const char *name)
Definition: mex.cc:5160
bool mxIsClass(const mxArray *ptr, const char *name)
Definition: mex.cc:4148
OCTINTERP_API mxArray * mxCreateString_interleaved(const char *str)
Definition: mex.cc:4080
OCTINTERP_API mxInt32 * mxGetInt32s(const mxArray *p)
Definition: mex.cc:4404
OCTINTERP_API mxArray * mxCreateUninitNumericMatrix_interleaved(mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:4040
static mwSize max_str_len(mwSize m, const char **str)
Definition: mex.cc:301
int mxGetNumberOfFields(const mxArray *ptr)
Definition: mex.cc:4737
#define GET_DATA_METHOD(RT, FCN_NAME, ID, COMPLEXITY)
Definition: mex.cc:467
OCTINTERP_API mxArray * mxCreateCellArray_interleaved(mwSize ndims, const mwSize *dims)
Definition: mex.cc:3888
void * mxCalloc(std::size_t n, std::size_t size)
Definition: mex.cc:3853
OCTINTERP_API mxArray * mxCreateNumericArray_interleaved(mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:3996
mwIndex * mxGetJc(const mxArray *ptr)
Definition: mex.cc:4668
int mexPutVariable(const char *space, const char *name, const mxArray *ptr)
Definition: mex.cc:5217
void mxSetN(mxArray *ptr, mwSize n)
Definition: mex.cc:4325
OCTINTERP_API mxArray * mxCreateNumericArray(mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:4003
OCTINTERP_API int mxSetInt64s(mxArray *p, mxInt64 *d)
Definition: mex.cc:4525
static mxArray * maybe_mark_array(mxArray *ptr)
Definition: mex.cc:3881
OCTINTERP_API mxArray * mxCreateSparseLogicalMatrix(mwSize m, mwSize n, mwSize nzmax)
Definition: mex.cc:4074
bool mxIsInt32(const mxArray *ptr)
Definition: mex.cc:4178
OCTINTERP_API double * mxGetPi(const mxArray *ptr)
Definition: mex.cc:4373
OCTINTERP_API mxArray * mxCreateCharMatrixFromStrings_interleaved(mwSize m, const char **str)
Definition: mex.cc:3924
void * mxRealloc(void *ptr, std::size_t size)
Definition: mex.cc:3865
void mexUnlock(void)
Definition: mex.cc:5411
int mexIsGlobal(const mxArray *ptr)
Definition: mex.cc:5347
void mxSetJc(mxArray *ptr, mwIndex *jc)
Definition: mex.cc:4686
bool mxIsInt16(const mxArray *ptr)
Definition: mex.cc:4172
const mwSize * mxGetDimensions(const mxArray *ptr)
Definition: mex.cc:4300
OCTINTERP_API int mxSetComplexSingles(mxArray *p, mxComplexSingle *d)
Definition: mex.cc:4555
OCTINTERP_API mxArray * mxCreateCellMatrix(mwSize m, mwSize n)
Definition: mex.cc:3906
int mexEvalString(const char *s)
Definition: mex.cc:4995
void mexSetTrapFlag(int flag)
Definition: mex.cc:4988
mwSize mxGetNzmax(const mxArray *ptr)
Definition: mex.cc:4674
OCTINTERP_API mxArray * mxCreateLogicalScalar(mxLogical val)
Definition: mex.cc:3990
void mxSetClassName(mxArray *ptr, const char *name)
Definition: mex.cc:4629
const mxArray * mexGetVariablePtr(const char *space, const char *name)
Definition: mex.cc:5211
OCTINTERP_API mxUint32 * mxGetUint32s(const mxArray *p)
Definition: mex.cc:4424
bool mxIsNumeric(const mxArray *ptr)
Definition: mex.cc:4202
static void * xmalloc(size_t n)
Definition: mex.cc:266
static void * xrealloc(void *ptr, size_t n)
Definition: mex.cc:278
OCTINTERP_API mxArray * mxCreateSparse_interleaved(mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
Definition: mex.cc:4054
int mexIsLocked(void)
Definition: mex.cc:5353
OCTINTERP_API mxArray * mxCreateDoubleMatrix(mwSize nr, mwSize nc, mxComplexity flag)
Definition: mex.cc:3942
bool mxIsCell(const mxArray *ptr)
Definition: mex.cc:4136
static mxArray * maybe_unmark_array(mxArray *ptr)
Definition: mex.cc:3777
void mexMakeArrayPersistent(mxArray *ptr)
Definition: mex.cc:5294
OCTINTERP_API mxArray * mxCreateCharMatrixFromStrings(mwSize m, const char **str)
Definition: mex.cc:3930
double mxGetScalar(const mxArray *ptr)
Definition: mex.cc:4346
#define VOID_MUTATION_METHOD(FCN_NAME, ARG_LIST)
Definition: mex.cc:455
void mxRemoveField(mxArray *ptr, int key_num)
Definition: mex.cc:4705
int mxGetString(const mxArray *ptr, char *buf, mwSize buflen)
Definition: mex.cc:4755
const char * mxGetFieldNameByNumber(const mxArray *ptr, int key_num)
Definition: mex.cc:4743
OCTINTERP_API mxArray * mxCreateStructMatrix(mwSize rows, mwSize cols, int num_keys, const char **keys)
Definition: mex.cc:4113
bool mxIsLogicalScalar(const mxArray *ptr)
Definition: mex.cc:4251
OCTINTERP_API mxArray * mxCreateDoubleScalar(double val)
Definition: mex.cc:3954
double mxGetInf(void)
Definition: mex.cc:3840
double mxGetNaN(void)
Definition: mex.cc:3846
OCTINTERP_API mxArray * mxCreateUninitNumericArray(mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:4032
static void xfree(void *ptr)
Definition: mex.cc:291
std::size_t mxGetN(const mxArray *ptr)
Definition: mex.cc:4294
OCTINTERP_API mxArray * mxCreateNumericMatrix_interleaved(mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:4010
mwSize mxGetNumberOfDimensions(const mxArray *ptr)
Definition: mex.cc:4306
mxLogical * mxGetLogicals(const mxArray *ptr)
Definition: mex.cc:4361
OCTINTERP_API mxArray * mxCreateUninitNumericMatrix(mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:4047
OCTINTERP_API int mxMakeArrayComplex(mxArray *ptr)
double mxGetEps(void)
Definition: mex.cc:3834
double * mxGetPr(const mxArray *ptr)
Definition: mex.cc:4340
int mexSet(double handle, const char *property, mxArray *val)
Definition: mex.cc:5390
void mexLock(void)
Definition: mex.cc:5372
#define MUTATION_METHOD(RET_TYPE, FCN_NAME, ARG_LIST, RET_VAL)
Definition: mex.cc:461
const mxArray * mexGet(double handle, const char *property)
Definition: mex.cc:5333
OCTINTERP_API mxArray * mxCreateStructMatrix_interleaved(mwSize rows, mwSize cols, int num_keys, const char **keys)
Definition: mex.cc:4106
bool mxIsEmpty(const mxArray *ptr)
Definition: mex.cc:4265
OCTINTERP_API mxArray * mxCreateLogicalArray_interleaved(mwSize ndims, const mwSize *dims)
Definition: mex.cc:3960
mxArray * mxGetField(const mxArray *ptr, mwIndex index, const char *key)
Definition: mex.cc:4711
char * mxArrayToString(const mxArray *ptr)
Definition: mex.cc:4761
OCTINTERP_API mxArray * mxCreateLogicalMatrix_interleaved(mwSize m, mwSize n)
Definition: mex.cc:3972
void mxFree(void *ptr)
Definition: mex.cc:3872
OCTINTERP_API int mxMakeArrayReal(mxArray *ptr)
mxChar * mxGetChars(const mxArray *ptr)
Definition: mex.cc:4352
OCTINTERP_API const mxArray * mexGet_interleaved(double handle, const char *property)
Definition: mex.cc:5319
static T * maybe_unmark(T *ptr)
Definition: mex.cc:3787
bool mxIsSparse(const mxArray *ptr)
Definition: mex.cc:4214
bool mxIsUint64(const mxArray *ptr)
Definition: mex.cc:4238
OCTINTERP_API mxArray * mxCreateDoubleScalar_interleaved(double val)
Definition: mex.cc:3948
bool mxIsDouble(const mxArray *ptr)
Definition: mex.cc:4160
mxArray * mxGetCell(const mxArray *ptr, mwIndex idx)
Definition: mex.cc:4649
OCTINTERP_API mxArray * mxCreateStructArray_interleaved(mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
Definition: mex.cc:4092
OCTINTERP_API mxArray * mxCreateLogicalScalar_interleaved(mxLogical val)
Definition: mex.cc:3984
OCTINTERP_API void mxSetPi(mxArray *ptr, double *pi)
Definition: mex.cc:4604
OCTINTERP_API mxArray * mxCreateUninitNumericArray_interleaved(mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag)
Definition: mex.cc:4024
OCTINTERP_API int mxSetSingles(mxArray *p, mxSingle *d)
Definition: mex.cc:4505
void mxSetM(mxArray *ptr, mwSize m)
Definition: mex.cc:4319
OCTINTERP_API mxArray * mxCreateLogicalMatrix(mwSize m, mwSize n)
Definition: mex.cc:3978
static mwIndex calc_single_subscript_internal(mwSize ndims, const mwSize *dims, mwSize nsubs, const mwIndex *subs)
Definition: mex.cc:407
OCTINTERP_API mxArray * mxCreateDoubleMatrix_interleaved(mwSize nr, mwSize nc, mxComplexity flag)
Definition: mex.cc:3936
static void * maybe_mark_foreign(void *ptr)
Definition: mex.cc:3753
mxArray * mxDuplicateArray(const mxArray *ptr)
Definition: mex.cc:4121
void mxArray
Definition: mex.h:58
class OCTAVE_API Matrix
Definition: mx-fwd.h:31
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:10370
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:85
OCTAVE_API bool strcmp(const T &str_a, const T &str_b)
Octave string utility functions.
void * malloc(unsigned)
void free(void *)
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
#define octave_stdout
Definition: pager.h:314
std::size_t vformat(std::ostream &os, const char *fmt, va_list args)
Definition: utils.cc:1487
F77_RET_T len
Definition: xerbla.cc:61