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