00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include <cfloat>
00026 #include <csetjmp>
00027 #include <cstdarg>
00028 #include <cstdlib>
00029 #include <cstring>
00030 #include <cctype>
00031
00032 #include <set>
00033
00034 #include "f77-fcn.h"
00035 #include "lo-ieee.h"
00036 #include "oct-locbuf.h"
00037
00038
00039 class mxArray;
00040 #include "Cell.h"
00041 #include "mexproto.h"
00042 #include "oct-map.h"
00043 #include "oct-obj.h"
00044 #include "ov.h"
00045 #include "ov-mex-fcn.h"
00046 #include "ov-usr-fcn.h"
00047 #include "pager.h"
00048 #include "parse.h"
00049 #include "toplev.h"
00050 #include "unwind-prot.h"
00051 #include "utils.h"
00052 #include "variables.h"
00053 #include "graphics.h"
00054
00055
00056
00057 static void
00058 xfree (void *ptr)
00059 {
00060 ::free (ptr);
00061 }
00062
00063 static mwSize
00064 max_str_len (mwSize m, const char **str)
00065 {
00066 int max_len = 0;
00067
00068 for (mwSize i = 0; i < m; i++)
00069 {
00070 mwSize tmp = strlen (str[i]);
00071
00072 if (tmp > max_len)
00073 max_len = tmp;
00074 }
00075
00076 return max_len;
00077 }
00078
00079 static int
00080 valid_key (const char *key)
00081 {
00082 int retval = 0;
00083
00084 int nel = strlen (key);
00085
00086 if (nel > 0)
00087 {
00088 if (isalpha (key[0]))
00089 {
00090 for (int i = 1; i < nel; i++)
00091 {
00092 if (! (isalnum (key[i]) || key[i] == '_'))
00093 goto done;
00094 }
00095
00096 retval = 1;
00097 }
00098 }
00099
00100 done:
00101
00102 return retval;
00103 }
00104
00105
00106
00107
00108
00109
00110 class mxArray_base : public mxArray
00111 {
00112 protected:
00113
00114 mxArray_base (void) : mxArray (xmxArray ()) { }
00115
00116 public:
00117
00118 mxArray *dup (void) const = 0;
00119
00120 ~mxArray_base (void) { }
00121
00122 bool is_octave_value (void) const { return false; }
00123
00124 int is_cell (void) const = 0;
00125
00126 int is_char (void) const = 0;
00127
00128 int is_class (const char *name_arg) const
00129 {
00130 int retval = 0;
00131
00132 const char *cname = get_class_name ();
00133
00134 if (cname && name_arg)
00135 retval = ! strcmp (cname, name_arg);
00136
00137 return retval;
00138 }
00139
00140 int is_complex (void) const = 0;
00141
00142 int is_double (void) const = 0;
00143
00144 int is_function_handle (void) const = 0;
00145
00146 int is_int16 (void) const = 0;
00147
00148 int is_int32 (void) const = 0;
00149
00150 int is_int64 (void) const = 0;
00151
00152 int is_int8 (void) const = 0;
00153
00154 int is_logical (void) const = 0;
00155
00156 int is_numeric (void) const = 0;
00157
00158 int is_single (void) const = 0;
00159
00160 int is_sparse (void) const = 0;
00161
00162 int is_struct (void) const = 0;
00163
00164 int is_uint16 (void) const = 0;
00165
00166 int is_uint32 (void) const = 0;
00167
00168 int is_uint64 (void) const = 0;
00169
00170 int is_uint8 (void) const = 0;
00171
00172 int is_logical_scalar (void) const
00173 {
00174 return is_logical () && get_number_of_elements () == 1;
00175 }
00176
00177 int is_logical_scalar_true (void) const = 0;
00178
00179 mwSize get_m (void) const = 0;
00180
00181 mwSize get_n (void) const = 0;
00182
00183 mwSize *get_dimensions (void) const = 0;
00184
00185 mwSize get_number_of_dimensions (void) const = 0;
00186
00187 void set_m (mwSize m) = 0;
00188
00189 void set_n (mwSize n) = 0;
00190
00191 void set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0;
00192
00193 mwSize get_number_of_elements (void) const = 0;
00194
00195 int is_empty (void) const = 0;
00196
00197 mxClassID get_class_id (void) const = 0;
00198
00199 const char *get_class_name (void) const = 0;
00200
00201 void set_class_name (const char *name_arg) = 0;
00202
00203 mxArray *get_cell (mwIndex ) const
00204 {
00205 invalid_type_error ();
00206 return 0;
00207 }
00208
00209 void set_cell (mwIndex idx, mxArray *val) = 0;
00210
00211 double get_scalar (void) const = 0;
00212
00213 void *get_data (void) const = 0;
00214
00215 void *get_imag_data (void) const = 0;
00216
00217 void set_data (void *pr) = 0;
00218
00219 void set_imag_data (void *pi) = 0;
00220
00221 mwIndex *get_ir (void) const = 0;
00222
00223 mwIndex *get_jc (void) const = 0;
00224
00225 mwSize get_nzmax (void) const = 0;
00226
00227 void set_ir (mwIndex *ir) = 0;
00228
00229 void set_jc (mwIndex *jc) = 0;
00230
00231 void set_nzmax (mwSize nzmax) = 0;
00232
00233 int add_field (const char *key) = 0;
00234
00235 void remove_field (int key_num) = 0;
00236
00237 mxArray *get_field_by_number (mwIndex index, int key_num) const = 0;
00238
00239 void set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0;
00240
00241 int get_number_of_fields (void) const = 0;
00242
00243 const char *get_field_name_by_number (int key_num) const = 0;
00244
00245 int get_field_number (const char *key) const = 0;
00246
00247 int get_string (char *buf, mwSize buflen) const = 0;
00248
00249 char *array_to_string (void) const = 0;
00250
00251 mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0;
00252
00253 size_t get_element_size (void) const = 0;
00254
00255 bool mutation_needed (void) const { return false; }
00256
00257 mxArray *mutate (void) const { return 0; }
00258
00259 protected:
00260
00261 octave_value as_octave_value (void) const = 0;
00262
00263 mxArray_base (const mxArray_base&) : mxArray (xmxArray ()) { }
00264
00265 void invalid_type_error (void) const
00266 {
00267 error ("invalid type for operation");
00268 }
00269
00270 void error (const char *msg) const
00271 {
00272
00273 ::error ("%s", msg);
00274 }
00275 };
00276
00277 static mwIndex
00278 calc_single_subscript_internal (mwSize ndims, const mwSize *dims,
00279 mwSize nsubs, const mwIndex *subs)
00280 {
00281 mwIndex retval = 0;
00282
00283 switch (nsubs)
00284 {
00285 case 0:
00286 break;
00287
00288 case 1:
00289 retval = subs[0];
00290 break;
00291
00292 default:
00293 {
00294
00295
00296 mwSize n = nsubs <= ndims ? nsubs : ndims;
00297
00298 retval = subs[--n];
00299
00300 while (--n >= 0)
00301 retval = dims[n] * retval + subs[n];
00302 }
00303 break;
00304 }
00305
00306 return retval;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 static inline void *maybe_mark_foreign (void *ptr);
00321
00322 class mxArray_octave_value : public mxArray_base
00323 {
00324 public:
00325
00326 mxArray_octave_value (const octave_value& ov)
00327 : mxArray_base (), val (ov), mutate_flag (false),
00328 id (mxUNKNOWN_CLASS), class_name (0), ndims (-1), dims (0) { }
00329
00330 mxArray *dup (void) const
00331 {
00332 mxArray *retval = val.as_mxArray ();
00333
00334 if (! retval)
00335 retval = new mxArray_octave_value (*this);
00336
00337 return retval;
00338 }
00339
00340 ~mxArray_octave_value (void)
00341 {
00342 mxFree (class_name);
00343 mxFree (dims);
00344 }
00345
00346 bool is_octave_value (void) const { return true; }
00347
00348 int is_cell (void) const { return val.is_cell (); }
00349
00350 int is_char (void) const { return val.is_string (); }
00351
00352 int is_complex (void) const { return val.is_complex_type (); }
00353
00354 int is_double (void) const { return val.is_double_type (); }
00355
00356 int is_function_handle (void) const { return val.is_function_handle (); }
00357
00358 int is_int16 (void) const { return val.is_int16_type (); }
00359
00360 int is_int32 (void) const { return val.is_int32_type (); }
00361
00362 int is_int64 (void) const { return val.is_int64_type (); }
00363
00364 int is_int8 (void) const { return val.is_int8_type (); }
00365
00366 int is_logical (void) const { return val.is_bool_type (); }
00367
00368 int is_numeric (void) const { return val.is_numeric_type (); }
00369
00370 int is_single (void) const { return val.is_single_type (); }
00371
00372 int is_sparse (void) const { return val.is_sparse_type (); }
00373
00374 int is_struct (void) const { return val.is_map (); }
00375
00376 int is_uint16 (void) const { return val.is_uint16_type (); }
00377
00378 int is_uint32 (void) const { return val.is_uint32_type (); }
00379
00380 int is_uint64 (void) const { return val.is_uint64_type (); }
00381
00382 int is_uint8 (void) const { return val.is_uint8_type (); }
00383
00384 int is_range (void) const { return val.is_range (); }
00385
00386 int is_real_type (void) const { return val.is_real_type (); }
00387
00388 int is_logical_scalar_true (void) const
00389 {
00390 return (is_logical_scalar () && val.is_true ());
00391 }
00392
00393 mwSize get_m (void) const { return val.rows (); }
00394
00395 mwSize get_n (void) const
00396 {
00397 mwSize n = 1;
00398
00399
00400 get_dimensions();
00401
00402 for (mwIndex i = ndims - 1; i > 0; i--)
00403 n *= dims[i];
00404
00405 return n;
00406 }
00407
00408 mwSize *get_dimensions (void) const
00409 {
00410 if (! dims)
00411 {
00412 ndims = val.ndims ();
00413
00414 dims = static_cast<mwSize *> (malloc (ndims * sizeof (mwSize)));
00415
00416 dim_vector dv = val.dims ();
00417
00418 for (mwIndex i = 0; i < ndims; i++)
00419 dims[i] = dv(i);
00420 }
00421
00422 return dims;
00423 }
00424
00425 mwSize get_number_of_dimensions (void) const
00426 {
00427
00428 get_dimensions ();
00429
00430 return ndims;
00431 }
00432
00433 void set_m (mwSize ) { request_mutation (); }
00434
00435 void set_n (mwSize ) { request_mutation (); }
00436
00437 void set_dimensions (mwSize *, mwSize )
00438 {
00439 request_mutation ();
00440 }
00441
00442 mwSize get_number_of_elements (void) const { return val.numel (); }
00443
00444 int is_empty (void) const { return val.is_empty (); }
00445
00446 mxClassID get_class_id (void) const
00447 {
00448 id = mxUNKNOWN_CLASS;
00449
00450 std::string cn = val.class_name ();
00451
00452 if (cn == "cell")
00453 id = mxCELL_CLASS;
00454 else if (cn == "struct")
00455 id = mxSTRUCT_CLASS;
00456 else if (cn == "logical")
00457 id = mxLOGICAL_CLASS;
00458 else if (cn == "char")
00459 id = mxCHAR_CLASS;
00460 else if (cn == "double")
00461 id = mxDOUBLE_CLASS;
00462 else if (cn == "single")
00463 id = mxSINGLE_CLASS;
00464 else if (cn == "int8")
00465 id = mxINT8_CLASS;
00466 else if (cn == "uint8")
00467 id = mxUINT8_CLASS;
00468 else if (cn == "int16")
00469 id = mxINT16_CLASS;
00470 else if (cn == "uint16")
00471 id = mxUINT16_CLASS;
00472 else if (cn == "int32")
00473 id = mxINT32_CLASS;
00474 else if (cn == "uint32")
00475 id = mxUINT32_CLASS;
00476 else if (cn == "int64")
00477 id = mxINT64_CLASS;
00478 else if (cn == "uint64")
00479 id = mxUINT64_CLASS;
00480 else if (cn == "function_handle")
00481 id = mxFUNCTION_CLASS;
00482
00483 return id;
00484 }
00485
00486 const char *get_class_name (void) const
00487 {
00488 if (! class_name)
00489 {
00490 std::string s = val.class_name ();
00491 class_name = strsave (s.c_str ());
00492 }
00493
00494 return class_name;
00495 }
00496
00497
00498 void set_class_name (const char *) { request_mutation (); }
00499
00500 mxArray *get_cell (mwIndex ) const
00501 {
00502 request_mutation ();
00503 return 0;
00504 }
00505
00506
00507 void set_cell (mwIndex , mxArray *) { request_mutation (); }
00508
00509 double get_scalar (void) const { return val.scalar_value (true); }
00510
00511 void *get_data (void) const
00512 {
00513 void *retval = val.mex_get_data ();
00514
00515 if (retval)
00516 maybe_mark_foreign (retval);
00517 else
00518 request_mutation ();
00519
00520 return retval;
00521 }
00522
00523 void *get_imag_data (void) const
00524 {
00525 void *retval = 0;
00526
00527 if (is_numeric () && is_real_type ())
00528 retval = 0;
00529 else
00530 request_mutation ();
00531
00532 return retval;
00533 }
00534
00535
00536 void set_data (void *) { request_mutation (); }
00537
00538
00539 void set_imag_data (void *) { request_mutation (); }
00540
00541 mwIndex *get_ir (void) const
00542 {
00543 return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_ir ()));
00544 }
00545
00546 mwIndex *get_jc (void) const
00547 {
00548 return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_jc ()));
00549 }
00550
00551 mwSize get_nzmax (void) const { return val.nzmax (); }
00552
00553
00554 void set_ir (mwIndex *) { request_mutation (); }
00555
00556
00557 void set_jc (mwIndex *) { request_mutation (); }
00558
00559
00560 void set_nzmax (mwSize ) { request_mutation (); }
00561
00562
00563 int add_field (const char *)
00564 {
00565 request_mutation ();
00566 return 0;
00567 }
00568
00569
00570 void remove_field (int ) { request_mutation (); }
00571
00572 mxArray *get_field_by_number (mwIndex , int ) const
00573 {
00574 request_mutation ();
00575 return 0;
00576 }
00577
00578
00579 void set_field_by_number (mwIndex , int , mxArray *)
00580 {
00581 request_mutation ();
00582 }
00583
00584 int get_number_of_fields (void) const { return val.nfields (); }
00585
00586 const char *get_field_name_by_number (int ) const
00587 {
00588 request_mutation ();
00589 return 0;
00590 }
00591
00592 int get_field_number (const char *) const
00593 {
00594 request_mutation ();
00595 return 0;
00596 }
00597
00598 int get_string (char *buf, mwSize buflen) const
00599 {
00600 int retval = 1;
00601
00602 mwSize nel = get_number_of_elements ();
00603
00604 if (val.is_string () && nel < buflen)
00605 {
00606 charNDArray tmp = val.char_array_value ();
00607
00608 const char *p = tmp.data ();
00609
00610 for (mwIndex i = 0; i < nel; i++)
00611 buf[i] = p[i];
00612
00613 buf[nel] = 0;
00614
00615 retval = 0;
00616 }
00617
00618 return retval;
00619 }
00620
00621 char *array_to_string (void) const
00622 {
00623
00624
00625
00626 char *buf = 0;
00627
00628 if (val.is_string ())
00629 {
00630 mwSize nel = get_number_of_elements ();
00631
00632 buf = static_cast<char *> (malloc (nel + 1));
00633
00634 if (buf)
00635 {
00636 charNDArray tmp = val.char_array_value ();
00637
00638 const char *p = tmp.data ();
00639
00640 for (mwIndex i = 0; i < nel; i++)
00641 buf[i] = p[i];
00642
00643 buf[nel] = '\0';
00644 }
00645 }
00646
00647 return buf;
00648 }
00649
00650 mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
00651 {
00652
00653 get_dimensions ();
00654
00655 return calc_single_subscript_internal (ndims, dims, nsubs, subs);
00656 }
00657
00658 size_t get_element_size (void) const
00659 {
00660
00661 get_class_id ();
00662
00663 switch (id)
00664 {
00665 case mxCELL_CLASS: return sizeof (mxArray *);
00666 case mxSTRUCT_CLASS: return sizeof (mxArray *);
00667 case mxLOGICAL_CLASS: return sizeof (mxLogical);
00668 case mxCHAR_CLASS: return sizeof (mxChar);
00669 case mxDOUBLE_CLASS: return sizeof (double);
00670 case mxSINGLE_CLASS: return sizeof (float);
00671 case mxINT8_CLASS: return 1;
00672 case mxUINT8_CLASS: return 1;
00673 case mxINT16_CLASS: return 2;
00674 case mxUINT16_CLASS: return 2;
00675 case mxINT32_CLASS: return 4;
00676 case mxUINT32_CLASS: return 4;
00677 case mxINT64_CLASS: return 8;
00678 case mxUINT64_CLASS: return 8;
00679 case mxFUNCTION_CLASS: return 0;
00680 default: return 0;
00681 }
00682 }
00683
00684 bool mutation_needed (void) const { return mutate_flag; }
00685
00686 void request_mutation (void) const
00687 {
00688 if (mutate_flag)
00689 panic_impossible ();
00690
00691 mutate_flag = true;
00692 }
00693
00694 mxArray *mutate (void) const { return val.as_mxArray (); }
00695
00696 protected:
00697
00698 octave_value as_octave_value (void) const { return val; }
00699
00700 mxArray_octave_value (const mxArray_octave_value& arg)
00701 : mxArray_base (arg), val (arg.val), mutate_flag (arg.mutate_flag),
00702 id (arg.id), class_name (strsave (arg.class_name)), ndims (arg.ndims),
00703 dims (ndims > 0 ? static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))) : 0)
00704 {
00705 if (dims)
00706 {
00707 for (mwIndex i = 0; i < ndims; i++)
00708 dims[i] = arg.dims[i];
00709 }
00710 }
00711
00712 private:
00713
00714 octave_value val;
00715
00716 mutable bool mutate_flag;
00717
00718
00719
00720
00721
00722 mutable mxClassID id;
00723 mutable char *class_name;
00724 mutable mwSize ndims;
00725 mutable mwSize *dims;
00726
00727
00728
00729
00730 mxArray_octave_value& operator = (const mxArray_octave_value&);
00731 };
00732
00733
00734
00735
00736 class mxArray_matlab : public mxArray_base
00737 {
00738 protected:
00739
00740 mxArray_matlab (mxClassID id_arg = mxUNKNOWN_CLASS)
00741 : mxArray_base (), class_name (0), id (id_arg), ndims (0), dims (0) { }
00742
00743 mxArray_matlab (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg)
00744 : mxArray_base (), class_name (0), id (id_arg),
00745 ndims (ndims_arg < 2 ? 2 : ndims_arg),
00746 dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
00747 {
00748 if (ndims_arg < 2)
00749 {
00750 dims[0] = 1;
00751 dims[1] = 1;
00752 }
00753
00754 for (mwIndex i = 0; i < ndims_arg; i++)
00755 dims[i] = dims_arg[i];
00756
00757 for (mwIndex i = ndims - 1; i > 1; i--)
00758 {
00759 if (dims[i] == 1)
00760 ndims--;
00761 else
00762 break;
00763 }
00764 }
00765
00766 mxArray_matlab (mxClassID id_arg, const dim_vector& dv)
00767 : mxArray_base (), class_name (0), id (id_arg),
00768 ndims (dv.length ()),
00769 dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
00770 {
00771 for (mwIndex i = 0; i < ndims; i++)
00772 dims[i] = dv(i);
00773
00774 for (mwIndex i = ndims - 1; i > 1; i--)
00775 {
00776 if (dims[i] == 1)
00777 ndims--;
00778 else
00779 break;
00780 }
00781 }
00782
00783 mxArray_matlab (mxClassID id_arg, mwSize m, mwSize n)
00784 : mxArray_base (), class_name (0), id (id_arg), ndims (2),
00785 dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
00786 {
00787 dims[0] = m;
00788 dims[1] = n;
00789 }
00790
00791 public:
00792
00793 ~mxArray_matlab (void)
00794 {
00795 mxFree (class_name);
00796 mxFree (dims);
00797 }
00798
00799 int is_cell (void) const { return id == mxCELL_CLASS; }
00800
00801 int is_char (void) const { return id == mxCHAR_CLASS; }
00802
00803 int is_complex (void) const { return 0; }
00804
00805 int is_double (void) const { return id == mxDOUBLE_CLASS; }
00806
00807 int is_function_handle (void) const { return id == mxFUNCTION_CLASS; }
00808
00809 int is_int16 (void) const { return id == mxINT16_CLASS; }
00810
00811 int is_int32 (void) const { return id == mxINT32_CLASS; }
00812
00813 int is_int64 (void) const { return id == mxINT64_CLASS; }
00814
00815 int is_int8 (void) const { return id == mxINT8_CLASS; }
00816
00817 int is_logical (void) const { return id == mxLOGICAL_CLASS; }
00818
00819 int is_numeric (void) const
00820 {
00821 return (id == mxDOUBLE_CLASS || id == mxSINGLE_CLASS
00822 || id == mxINT8_CLASS || id == mxUINT8_CLASS
00823 || id == mxINT16_CLASS || id == mxUINT16_CLASS
00824 || id == mxINT32_CLASS || id == mxUINT32_CLASS
00825 || id == mxINT64_CLASS || id == mxUINT64_CLASS);
00826 }
00827
00828 int is_single (void) const { return id == mxSINGLE_CLASS; }
00829
00830 int is_sparse (void) const { return 0; }
00831
00832 int is_struct (void) const { return id == mxSTRUCT_CLASS; }
00833
00834 int is_uint16 (void) const { return id == mxUINT16_CLASS; }
00835
00836 int is_uint32 (void) const { return id == mxUINT32_CLASS; }
00837
00838 int is_uint64 (void) const { return id == mxUINT64_CLASS; }
00839
00840 int is_uint8 (void) const { return id == mxUINT8_CLASS; }
00841
00842 int is_logical_scalar_true (void) const
00843 {
00844 return (is_logical_scalar ()
00845 && static_cast<mxLogical *> (get_data ())[0] != 0);
00846 }
00847
00848 mwSize get_m (void) const { return dims[0]; }
00849
00850 mwSize get_n (void) const
00851 {
00852 mwSize n = 1;
00853
00854 for (mwSize i = ndims - 1 ; i > 0 ; i--)
00855 n *= dims[i];
00856
00857 return n;
00858 }
00859
00860 mwSize *get_dimensions (void) const { return dims; }
00861
00862 mwSize get_number_of_dimensions (void) const { return ndims; }
00863
00864 void set_m (mwSize m) { dims[0] = m; }
00865
00866 void set_n (mwSize n) { dims[1] = n; }
00867
00868 void set_dimensions (mwSize *dims_arg, mwSize ndims_arg)
00869 {
00870 dims = dims_arg;
00871 ndims = ndims_arg;
00872 }
00873
00874 mwSize get_number_of_elements (void) const
00875 {
00876 mwSize retval = dims[0];
00877
00878 for (mwIndex i = 1; i < ndims; i++)
00879 retval *= dims[i];
00880
00881 return retval;
00882 }
00883
00884 int is_empty (void) const { return get_number_of_elements () == 0; }
00885
00886 mxClassID get_class_id (void) const { return id; }
00887
00888 const char *get_class_name (void) const
00889 {
00890 switch (id)
00891 {
00892 case mxCELL_CLASS: return "cell";
00893 case mxSTRUCT_CLASS: return "struct";
00894 case mxLOGICAL_CLASS: return "logical";
00895 case mxCHAR_CLASS: return "char";
00896 case mxDOUBLE_CLASS: return "double";
00897 case mxSINGLE_CLASS: return "single";
00898 case mxINT8_CLASS: return "int8";
00899 case mxUINT8_CLASS: return "uint8";
00900 case mxINT16_CLASS: return "int16";
00901 case mxUINT16_CLASS: return "uint16";
00902 case mxINT32_CLASS: return "int32";
00903 case mxUINT32_CLASS: return "uint32";
00904 case mxINT64_CLASS: return "int64";
00905 case mxUINT64_CLASS: return "uint64";
00906 case mxFUNCTION_CLASS: return "function_handle";
00907 default: return "unknown";
00908 }
00909 }
00910
00911 void set_class_name (const char *name_arg)
00912 {
00913 mxFree (class_name);
00914 class_name = static_cast<char *> (malloc (strlen (name_arg) + 1));
00915 strcpy (class_name, name_arg);
00916 }
00917
00918 mxArray *get_cell (mwIndex ) const
00919 {
00920 invalid_type_error ();
00921 return 0;
00922 }
00923
00924 void set_cell (mwIndex , mxArray *)
00925 {
00926 invalid_type_error ();
00927 }
00928
00929 double get_scalar (void) const
00930 {
00931 invalid_type_error ();
00932 return 0;
00933 }
00934
00935 void *get_data (void) const
00936 {
00937 invalid_type_error ();
00938 return 0;
00939 }
00940
00941 void *get_imag_data (void) const
00942 {
00943 invalid_type_error ();
00944 return 0;
00945 }
00946
00947 void set_data (void *)
00948 {
00949 invalid_type_error ();
00950 }
00951
00952 void set_imag_data (void *)
00953 {
00954 invalid_type_error ();
00955 }
00956
00957 mwIndex *get_ir (void) const
00958 {
00959 invalid_type_error ();
00960 return 0;
00961 }
00962
00963 mwIndex *get_jc (void) const
00964 {
00965 invalid_type_error ();
00966 return 0;
00967 }
00968
00969 mwSize get_nzmax (void) const
00970 {
00971 invalid_type_error ();
00972 return 0;
00973 }
00974
00975 void set_ir (mwIndex *)
00976 {
00977 invalid_type_error ();
00978 }
00979
00980 void set_jc (mwIndex *)
00981 {
00982 invalid_type_error ();
00983 }
00984
00985 void set_nzmax (mwSize )
00986 {
00987 invalid_type_error ();
00988 }
00989
00990 int add_field (const char *)
00991 {
00992 invalid_type_error ();
00993 return -1;
00994 }
00995
00996 void remove_field (int )
00997 {
00998 invalid_type_error ();
00999 }
01000
01001 mxArray *get_field_by_number (mwIndex , int ) const
01002 {
01003 invalid_type_error ();
01004 return 0;
01005 }
01006
01007 void set_field_by_number (mwIndex , int , mxArray *)
01008 {
01009 invalid_type_error ();
01010 }
01011
01012 int get_number_of_fields (void) const
01013 {
01014 invalid_type_error ();
01015 return 0;
01016 }
01017
01018 const char *get_field_name_by_number (int ) const
01019 {
01020 invalid_type_error ();
01021 return 0;
01022 }
01023
01024 int get_field_number (const char *) const
01025 {
01026 return -1;
01027 }
01028
01029 int get_string (char *, mwSize ) const
01030 {
01031 invalid_type_error ();
01032 return 0;
01033 }
01034
01035 char *array_to_string (void) const
01036 {
01037 invalid_type_error ();
01038 return 0;
01039 }
01040
01041 mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
01042 {
01043 return calc_single_subscript_internal (ndims, dims, nsubs, subs);
01044 }
01045
01046 size_t get_element_size (void) const
01047 {
01048 switch (id)
01049 {
01050 case mxCELL_CLASS: return sizeof (mxArray *);
01051 case mxSTRUCT_CLASS: return sizeof (mxArray *);
01052 case mxLOGICAL_CLASS: return sizeof (mxLogical);
01053 case mxCHAR_CLASS: return sizeof (mxChar);
01054 case mxDOUBLE_CLASS: return sizeof (double);
01055 case mxSINGLE_CLASS: return sizeof (float);
01056 case mxINT8_CLASS: return 1;
01057 case mxUINT8_CLASS: return 1;
01058 case mxINT16_CLASS: return 2;
01059 case mxUINT16_CLASS: return 2;
01060 case mxINT32_CLASS: return 4;
01061 case mxUINT32_CLASS: return 4;
01062 case mxINT64_CLASS: return 8;
01063 case mxUINT64_CLASS: return 8;
01064 case mxFUNCTION_CLASS: return 0;
01065 default: return 0;
01066 }
01067 }
01068
01069 protected:
01070
01071 mxArray_matlab (const mxArray_matlab& val)
01072 : mxArray_base (val), class_name (strsave (val.class_name)),
01073 id (val.id), ndims (val.ndims),
01074 dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
01075 {
01076 for (mwIndex i = 0; i < ndims; i++)
01077 dims[i] = val.dims[i];
01078 }
01079
01080 dim_vector
01081 dims_to_dim_vector (void) const
01082 {
01083 mwSize nd = get_number_of_dimensions ();
01084
01085 mwSize *d = get_dimensions ();
01086
01087 dim_vector dv;
01088 dv.resize (nd);
01089
01090 for (mwIndex i = 0; i < nd; i++)
01091 dv(i) = d[i];
01092
01093 return dv;
01094 }
01095
01096 private:
01097
01098 char *class_name;
01099
01100 mxClassID id;
01101
01102 mwSize ndims;
01103 mwSize *dims;
01104
01105 void invalid_type_error (void) const
01106 {
01107 error ("invalid type for operation");
01108 }
01109
01110
01111
01112
01113 mxArray_matlab& operator = (const mxArray_matlab&);
01114 };
01115
01116
01117
01118 class mxArray_number : public mxArray_matlab
01119 {
01120 public:
01121
01122 mxArray_number (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg,
01123 mxComplexity flag = mxREAL)
01124 : mxArray_matlab (id_arg, ndims_arg, dims_arg),
01125 pr (calloc (get_number_of_elements (), get_element_size ())),
01126 pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
01127
01128 mxArray_number (mxClassID id_arg, const dim_vector& dv,
01129 mxComplexity flag = mxREAL)
01130 : mxArray_matlab (id_arg, dv),
01131 pr (calloc (get_number_of_elements (), get_element_size ())),
01132 pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
01133
01134 mxArray_number (mxClassID id_arg, mwSize m, mwSize n, mxComplexity flag = mxREAL)
01135 : mxArray_matlab (id_arg, m, n),
01136 pr (calloc (get_number_of_elements (), get_element_size ())),
01137 pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
01138
01139 mxArray_number (mxClassID id_arg, double val)
01140 : mxArray_matlab (id_arg, 1, 1),
01141 pr (calloc (get_number_of_elements (), get_element_size ())),
01142 pi (0)
01143 {
01144 double *dpr = static_cast<double *> (pr);
01145 dpr[0] = val;
01146 }
01147
01148 mxArray_number (mxClassID id_arg, mxLogical val)
01149 : mxArray_matlab (id_arg, 1, 1),
01150 pr (calloc (get_number_of_elements (), get_element_size ())),
01151 pi (0)
01152 {
01153 mxLogical *lpr = static_cast<mxLogical *> (pr);
01154 lpr[0] = val;
01155 }
01156
01157 mxArray_number (const char *str)
01158 : mxArray_matlab (mxCHAR_CLASS,
01159 str ? (strlen (str) ? 1 : 0) : 0,
01160 str ? strlen (str) : 0),
01161 pr (calloc (get_number_of_elements (), get_element_size ())),
01162 pi (0)
01163 {
01164 mxChar *cpr = static_cast<mxChar *> (pr);
01165 mwSize nel = get_number_of_elements ();
01166 for (mwIndex i = 0; i < nel; i++)
01167 cpr[i] = str[i];
01168 }
01169
01170
01171 mxArray_number (mwSize m, const char **str)
01172 : mxArray_matlab (mxCHAR_CLASS, m, max_str_len (m, str)),
01173 pr (calloc (get_number_of_elements (), get_element_size ())),
01174 pi (0)
01175 {
01176 mxChar *cpr = static_cast<mxChar *> (pr);
01177
01178 mwSize *dv = get_dimensions ();
01179
01180 mwSize nc = dv[1];
01181
01182 for (mwIndex j = 0; j < m; j++)
01183 {
01184 const char *ptr = str[j];
01185
01186 size_t tmp_len = strlen (ptr);
01187
01188 for (size_t i = 0; i < tmp_len; i++)
01189 cpr[m*i+j] = static_cast<mxChar> (ptr[i]);
01190
01191 for (size_t i = tmp_len; i < nc; i++)
01192 cpr[m*i+j] = static_cast<mxChar> (' ');
01193 }
01194 }
01195
01196 mxArray_number *dup (void) const { return new mxArray_number (*this); }
01197
01198 ~mxArray_number (void)
01199 {
01200 mxFree (pr);
01201 mxFree (pi);
01202 }
01203
01204 int is_complex (void) const { return pi != 0; }
01205
01206 double get_scalar (void) const
01207 {
01208 double retval = 0;
01209
01210 switch (get_class_id ())
01211 {
01212 case mxLOGICAL_CLASS:
01213 retval = *(static_cast<bool *> (pr));
01214 break;
01215
01216 case mxCHAR_CLASS:
01217 retval = *(static_cast<mxChar *> (pr));
01218 break;
01219
01220 case mxSINGLE_CLASS:
01221 retval = *(static_cast<float *> (pr));
01222 break;
01223
01224 case mxDOUBLE_CLASS:
01225 retval = *(static_cast<double *> (pr));
01226 break;
01227
01228 case mxINT8_CLASS:
01229 retval = *(static_cast<int8_t *> (pr));
01230 break;
01231
01232 case mxUINT8_CLASS:
01233 retval = *(static_cast<uint8_t *> (pr));
01234 break;
01235
01236 case mxINT16_CLASS:
01237 retval = *(static_cast<int16_t *> (pr));
01238 break;
01239
01240 case mxUINT16_CLASS:
01241 retval = *(static_cast<uint16_t *> (pr));
01242 break;
01243
01244 case mxINT32_CLASS:
01245 retval = *(static_cast<int32_t *> (pr));
01246 break;
01247
01248 case mxUINT32_CLASS:
01249 retval = *(static_cast<uint32_t *> (pr));
01250 break;
01251
01252 case mxINT64_CLASS:
01253 retval = *(static_cast<int64_t *> (pr));
01254 break;
01255
01256 case mxUINT64_CLASS:
01257 retval = *(static_cast<uint64_t *> (pr));
01258 break;
01259
01260 default:
01261 panic_impossible ();
01262 }
01263
01264 return retval;
01265 }
01266
01267 void *get_data (void) const { return pr; }
01268
01269 void *get_imag_data (void) const { return pi; }
01270
01271 void set_data (void *pr_arg) { pr = pr_arg; }
01272
01273 void set_imag_data (void *pi_arg) { pi = pi_arg; }
01274
01275 int get_string (char *buf, mwSize buflen) const
01276 {
01277 int retval = 0;
01278
01279 mwSize nel = get_number_of_elements ();
01280
01281 if (! (nel < buflen))
01282 {
01283 retval = 1;
01284 if (buflen > 0)
01285 nel = buflen-1;
01286 }
01287
01288 if (nel < buflen)
01289 {
01290 mxChar *ptr = static_cast<mxChar *> (pr);
01291
01292 for (mwIndex i = 0; i < nel; i++)
01293 buf[i] = static_cast<char> (ptr[i]);
01294
01295 buf[nel] = 0;
01296 }
01297
01298 return retval;
01299 }
01300
01301 char *array_to_string (void) const
01302 {
01303
01304
01305
01306 mwSize nel = get_number_of_elements ();
01307
01308 char *buf = static_cast<char *> (malloc (nel + 1));
01309
01310 if (buf)
01311 {
01312 mxChar *ptr = static_cast<mxChar *> (pr);
01313
01314 for (mwIndex i = 0; i < nel; i++)
01315 buf[i] = static_cast<char> (ptr[i]);
01316
01317 buf[nel] = '\0';
01318 }
01319
01320 return buf;
01321 }
01322
01323 protected:
01324
01325 template <typename ELT_T, typename ARRAY_T, typename ARRAY_ELT_T>
01326 octave_value
01327 int_to_ov (const dim_vector& dv) const
01328 {
01329 octave_value retval;
01330
01331 mwSize nel = get_number_of_elements ();
01332
01333 ELT_T *ppr = static_cast<ELT_T *> (pr);
01334
01335 if (pi)
01336 error ("complex integer types are not supported");
01337 else
01338 {
01339 ARRAY_T val (dv);
01340
01341 ARRAY_ELT_T *ptr = val.fortran_vec ();
01342
01343 for (mwIndex i = 0; i < nel; i++)
01344 ptr[i] = ppr[i];
01345
01346 retval = val;
01347 }
01348
01349 return retval;
01350 }
01351
01352 octave_value as_octave_value (void) const
01353 {
01354 octave_value retval;
01355
01356 dim_vector dv = dims_to_dim_vector ();
01357
01358 switch (get_class_id ())
01359 {
01360 case mxLOGICAL_CLASS:
01361 retval = int_to_ov<bool, boolNDArray, bool> (dv);
01362 break;
01363
01364 case mxCHAR_CLASS:
01365 {
01366 mwSize nel = get_number_of_elements ();
01367
01368 mxChar *ppr = static_cast<mxChar *> (pr);
01369
01370 charNDArray val (dv);
01371
01372 char *ptr = val.fortran_vec ();
01373
01374 for (mwIndex i = 0; i < nel; i++)
01375 ptr[i] = static_cast<char> (ppr[i]);
01376
01377 retval = val;
01378 }
01379 break;
01380
01381 case mxSINGLE_CLASS:
01382 {
01383 mwSize nel = get_number_of_elements ();
01384
01385 float *ppr = static_cast<float *> (pr);
01386
01387 if (pi)
01388 {
01389 FloatComplexNDArray val (dv);
01390
01391 FloatComplex *ptr = val.fortran_vec ();
01392
01393 float *ppi = static_cast<float *> (pi);
01394
01395 for (mwIndex i = 0; i < nel; i++)
01396 ptr[i] = FloatComplex (ppr[i], ppi[i]);
01397
01398 retval = val;
01399 }
01400 else
01401 {
01402 FloatNDArray val (dv);
01403
01404 float *ptr = val.fortran_vec ();
01405
01406 for (mwIndex i = 0; i < nel; i++)
01407 ptr[i] = ppr[i];
01408
01409 retval = val;
01410 }
01411 }
01412 break;
01413
01414 case mxDOUBLE_CLASS:
01415 {
01416 mwSize nel = get_number_of_elements ();
01417
01418 double *ppr = static_cast<double *> (pr);
01419
01420 if (pi)
01421 {
01422 ComplexNDArray val (dv);
01423
01424 Complex *ptr = val.fortran_vec ();
01425
01426 double *ppi = static_cast<double *> (pi);
01427
01428 for (mwIndex i = 0; i < nel; i++)
01429 ptr[i] = Complex (ppr[i], ppi[i]);
01430
01431 retval = val;
01432 }
01433 else
01434 {
01435 NDArray val (dv);
01436
01437 double *ptr = val.fortran_vec ();
01438
01439 for (mwIndex i = 0; i < nel; i++)
01440 ptr[i] = ppr[i];
01441
01442 retval = val;
01443 }
01444 }
01445 break;
01446
01447 case mxINT8_CLASS:
01448 retval = int_to_ov<int8_t, int8NDArray, octave_int8> (dv);
01449 break;
01450
01451 case mxUINT8_CLASS:
01452 retval = int_to_ov<uint8_t, uint8NDArray, octave_uint8> (dv);
01453 break;
01454
01455 case mxINT16_CLASS:
01456 retval = int_to_ov<int16_t, int16NDArray, octave_int16> (dv);
01457 break;
01458
01459 case mxUINT16_CLASS:
01460 retval = int_to_ov<uint16_t, uint16NDArray, octave_uint16> (dv);
01461 break;
01462
01463 case mxINT32_CLASS:
01464 retval = int_to_ov<int32_t, int32NDArray, octave_int32> (dv);
01465 break;
01466
01467 case mxUINT32_CLASS:
01468 retval = int_to_ov<uint32_t, uint32NDArray, octave_uint32> (dv);
01469 break;
01470
01471 case mxINT64_CLASS:
01472 retval = int_to_ov<int64_t, int64NDArray, octave_int64> (dv);
01473 break;
01474
01475 case mxUINT64_CLASS:
01476 retval = int_to_ov<uint64_t, uint64NDArray, octave_uint64> (dv);
01477 break;
01478
01479 default:
01480 panic_impossible ();
01481 }
01482
01483 return retval;
01484 }
01485
01486 mxArray_number (const mxArray_number& val)
01487 : mxArray_matlab (val),
01488 pr (malloc (get_number_of_elements () * get_element_size ())),
01489 pi (val.pi ? malloc (get_number_of_elements () * get_element_size ()) : 0)
01490 {
01491 size_t nbytes = get_number_of_elements () * get_element_size ();
01492
01493 if (pr)
01494 memcpy (pr, val.pr, nbytes);
01495
01496 if (pi)
01497 memcpy (pi, val.pi, nbytes);
01498 }
01499
01500 private:
01501
01502 void *pr;
01503 void *pi;
01504
01505
01506
01507
01508 mxArray_number& operator = (const mxArray_number&);
01509 };
01510
01511
01512
01513 class mxArray_sparse : public mxArray_matlab
01514 {
01515 public:
01516
01517 mxArray_sparse (mxClassID id_arg, mwSize m, mwSize n, mwSize nzmax_arg,
01518 mxComplexity flag = mxREAL)
01519 : mxArray_matlab (id_arg, m, n), nzmax (nzmax_arg),
01520 pr (calloc (nzmax, get_element_size ())),
01521 pi (flag == mxCOMPLEX ? calloc (nzmax, get_element_size ()) : 0),
01522 ir (static_cast<mwIndex *> (calloc (nzmax, sizeof (mwIndex)))),
01523 jc (static_cast<mwIndex *> (calloc (n + 1, sizeof (mwIndex))))
01524 { }
01525
01526 mxArray_sparse *dup (void) const { return new mxArray_sparse (*this); }
01527
01528 ~mxArray_sparse (void)
01529 {
01530 mxFree (pr);
01531 mxFree (pi);
01532 mxFree (ir);
01533 mxFree (jc);
01534 }
01535
01536 int is_complex (void) const { return pi != 0; }
01537
01538 int is_sparse (void) const { return 1; }
01539
01540 void *get_data (void) const { return pr; }
01541
01542 void *get_imag_data (void) const { return pi; }
01543
01544 void set_data (void *pr_arg) { pr = pr_arg; }
01545
01546 void set_imag_data (void *pi_arg) { pi = pi_arg; }
01547
01548 mwIndex *get_ir (void) const { return ir; }
01549
01550 mwIndex *get_jc (void) const { return jc; }
01551
01552 mwSize get_nzmax (void) const { return nzmax; }
01553
01554 void set_ir (mwIndex *ir_arg) { ir = ir_arg; }
01555
01556 void set_jc (mwIndex *jc_arg) { jc = jc_arg; }
01557
01558 void set_nzmax (mwSize nzmax_arg) { nzmax = nzmax_arg; }
01559
01560 protected:
01561
01562 octave_value as_octave_value (void) const
01563 {
01564 octave_value retval;
01565
01566 dim_vector dv = dims_to_dim_vector ();
01567
01568 switch (get_class_id ())
01569 {
01570 case mxLOGICAL_CLASS:
01571 {
01572 bool *ppr = static_cast<bool *> (pr);
01573
01574 SparseBoolMatrix val (get_m (), get_n (),
01575 static_cast<octave_idx_type> (nzmax));
01576
01577 for (mwIndex i = 0; i < nzmax; i++)
01578 {
01579 val.xdata(i) = ppr[i];
01580 val.xridx(i) = ir[i];
01581 }
01582
01583 for (mwIndex i = 0; i < get_n () + 1; i++)
01584 val.xcidx(i) = jc[i];
01585
01586 retval = val;
01587 }
01588 break;
01589
01590 case mxSINGLE_CLASS:
01591 error ("single precision sparse data type not supported");
01592 break;
01593
01594 case mxDOUBLE_CLASS:
01595 {
01596 if (pi)
01597 {
01598 double *ppr = static_cast<double *> (pr);
01599 double *ppi = static_cast<double *> (pi);
01600
01601 SparseComplexMatrix val (get_m (), get_n (),
01602 static_cast<octave_idx_type> (nzmax));
01603
01604 for (mwIndex i = 0; i < nzmax; i++)
01605 {
01606 val.xdata(i) = Complex (ppr[i], ppi[i]);
01607 val.xridx(i) = ir[i];
01608 }
01609
01610 for (mwIndex i = 0; i < get_n () + 1; i++)
01611 val.xcidx(i) = jc[i];
01612
01613 retval = val;
01614 }
01615 else
01616 {
01617 double *ppr = static_cast<double *> (pr);
01618
01619 SparseMatrix val (get_m (), get_n (),
01620 static_cast<octave_idx_type> (nzmax));
01621
01622 for (mwIndex i = 0; i < nzmax; i++)
01623 {
01624 val.xdata(i) = ppr[i];
01625 val.xridx(i) = ir[i];
01626 }
01627
01628 for (mwIndex i = 0; i < get_n () + 1; i++)
01629 val.xcidx(i) = jc[i];
01630
01631 retval = val;
01632 }
01633 }
01634 break;
01635
01636 default:
01637 panic_impossible ();
01638 }
01639
01640 return retval;
01641 }
01642
01643 private:
01644
01645 mwSize nzmax;
01646
01647 void *pr;
01648 void *pi;
01649 mwIndex *ir;
01650 mwIndex *jc;
01651
01652 mxArray_sparse (const mxArray_sparse& val)
01653 : mxArray_matlab (val), nzmax (val.nzmax),
01654 pr (malloc (nzmax * get_element_size ())),
01655 pi (val.pi ? malloc (nzmax * get_element_size ()) : 0),
01656 ir (static_cast<mwIndex *> (malloc (nzmax * sizeof (mwIndex)))),
01657 jc (static_cast<mwIndex *> (malloc (nzmax * sizeof (mwIndex))))
01658 {
01659 size_t nbytes = nzmax * get_element_size ();
01660
01661 if (pr)
01662 memcpy (pr, val.pr, nbytes);
01663
01664 if (pi)
01665 memcpy (pi, val.pi, nbytes);
01666
01667 if (ir)
01668 memcpy (ir, val.ir, nzmax * sizeof (mwIndex));
01669
01670 if (jc)
01671 memcpy (jc, val.jc, (val.get_n () + 1) * sizeof (mwIndex));
01672 }
01673
01674
01675
01676
01677 mxArray_sparse& operator = (const mxArray_sparse&);
01678 };
01679
01680
01681
01682 class mxArray_struct : public mxArray_matlab
01683 {
01684 public:
01685
01686 mxArray_struct (mwSize ndims_arg, const mwSize *dims_arg, int num_keys_arg,
01687 const char **keys)
01688 : mxArray_matlab (mxSTRUCT_CLASS, ndims_arg, dims_arg), nfields (num_keys_arg),
01689 fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
01690 data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
01691 {
01692 init (keys);
01693 }
01694
01695 mxArray_struct (const dim_vector& dv, int num_keys_arg, const char **keys)
01696 : mxArray_matlab (mxSTRUCT_CLASS, dv), nfields (num_keys_arg),
01697 fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
01698 data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
01699 {
01700 init (keys);
01701 }
01702
01703 mxArray_struct (mwSize m, mwSize n, int num_keys_arg, const char **keys)
01704 : mxArray_matlab (mxSTRUCT_CLASS, m, n), nfields (num_keys_arg),
01705 fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
01706 data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
01707 {
01708 init (keys);
01709 }
01710
01711 void init (const char **keys)
01712 {
01713 for (int i = 0; i < nfields; i++)
01714 fields[i] = strsave (keys[i]);
01715 }
01716
01717 mxArray_struct *dup (void) const { return new mxArray_struct (*this); }
01718
01719 ~mxArray_struct (void)
01720 {
01721 for (int i = 0; i < nfields; i++)
01722 mxFree (fields[i]);
01723
01724 mxFree (fields);
01725
01726 mwSize ntot = nfields * get_number_of_elements ();
01727
01728 for (mwIndex i = 0; i < ntot; i++)
01729 delete data[i];
01730
01731 mxFree (data);
01732 }
01733
01734 int add_field (const char *key)
01735 {
01736 int retval = -1;
01737
01738 if (valid_key (key))
01739 {
01740 nfields++;
01741
01742 fields = static_cast<char **> (mxRealloc (fields, nfields * sizeof (char *)));
01743
01744 if (fields)
01745 {
01746 fields[nfields-1] = strsave (key);
01747
01748 mwSize nel = get_number_of_elements ();
01749
01750 mwSize ntot = nfields * nel;
01751
01752 mxArray **new_data = static_cast<mxArray **> (malloc (ntot * sizeof (mxArray *)));
01753
01754 if (new_data)
01755 {
01756 mwIndex j = 0;
01757 mwIndex k = 0;
01758 mwIndex n = 0;
01759
01760 for (mwIndex i = 0; i < ntot; i++)
01761 {
01762 if (++n == nfields)
01763 {
01764 new_data[j++] = 0;
01765 n = 0;
01766 }
01767 else
01768 new_data[j++] = data[k++];
01769 }
01770
01771 mxFree (data);
01772
01773 data = new_data;
01774
01775 retval = nfields - 1;
01776 }
01777 }
01778 }
01779
01780 return retval;
01781 }
01782
01783 void remove_field (int key_num)
01784 {
01785 if (key_num >= 0 && key_num < nfields)
01786 {
01787 mwSize nel = get_number_of_elements ();
01788
01789 mwSize ntot = nfields * nel;
01790
01791 int new_nfields = nfields - 1;
01792
01793 char **new_fields = static_cast<char **> (malloc (new_nfields * sizeof (char *)));
01794
01795 mxArray **new_data = static_cast<mxArray **> (malloc (new_nfields * nel * sizeof (mxArray *)));
01796
01797 for (int i = 0; i < key_num; i++)
01798 new_fields[i] = fields[i];
01799
01800 for (int i = key_num + 1; i < nfields; i++)
01801 new_fields[i-1] = fields[i];
01802
01803 if (new_nfields > 0)
01804 {
01805 mwIndex j = 0;
01806 mwIndex k = 0;
01807 mwIndex n = 0;
01808
01809 for (mwIndex i = 0; i < ntot; i++)
01810 {
01811 if (n == key_num)
01812 k++;
01813 else
01814 new_data[j++] = data[k++];
01815
01816 if (++n == nfields)
01817 n = 0;
01818 }
01819 }
01820
01821 nfields = new_nfields;
01822
01823 mxFree (fields);
01824 mxFree (data);
01825
01826 fields = new_fields;
01827 data = new_data;
01828 }
01829 }
01830
01831 mxArray *get_field_by_number (mwIndex index, int key_num) const
01832 {
01833 return key_num >= 0 && key_num < nfields
01834 ? data[nfields * index + key_num] : 0;
01835 }
01836
01837 void set_field_by_number (mwIndex index, int key_num, mxArray *val);
01838
01839 int get_number_of_fields (void) const { return nfields; }
01840
01841 const char *get_field_name_by_number (int key_num) const
01842 {
01843 return key_num >= 0 && key_num < nfields ? fields[key_num] : 0;
01844 }
01845
01846 int get_field_number (const char *key) const
01847 {
01848 int retval = -1;
01849
01850 for (int i = 0; i < nfields; i++)
01851 {
01852 if (! strcmp (key, fields[i]))
01853 {
01854 retval = i;
01855 break;
01856 }
01857 }
01858
01859 return retval;
01860 }
01861
01862 void *get_data (void) const { return data; }
01863
01864 void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
01865
01866 protected:
01867
01868 octave_value as_octave_value (void) const
01869 {
01870 dim_vector dv = dims_to_dim_vector ();
01871
01872 string_vector keys (fields, nfields);
01873
01874 octave_map m;
01875
01876 mwSize ntot = nfields * get_number_of_elements ();
01877
01878 for (int i = 0; i < nfields; i++)
01879 {
01880 Cell c (dv);
01881
01882 octave_value *p = c.fortran_vec ();
01883
01884 mwIndex k = 0;
01885 for (mwIndex j = i; j < ntot; j += nfields)
01886 p[k++] = mxArray::as_octave_value (data[j]);
01887
01888 m.assign (keys[i], c);
01889 }
01890
01891 return m;
01892 }
01893
01894 private:
01895
01896 int nfields;
01897
01898 char **fields;
01899
01900 mxArray **data;
01901
01902 mxArray_struct (const mxArray_struct& val)
01903 : mxArray_matlab (val), nfields (val.nfields),
01904 fields (static_cast<char **> (malloc (nfields * sizeof (char *)))),
01905 data (static_cast<mxArray **> (malloc (nfields * get_number_of_elements () * sizeof (mxArray *))))
01906 {
01907 for (int i = 0; i < nfields; i++)
01908 fields[i] = strsave (val.fields[i]);
01909
01910 mwSize nel = get_number_of_elements ();
01911
01912 for (mwIndex i = 0; i < nel * nfields; i++)
01913 {
01914 mxArray *ptr = val.data[i];
01915 data[i] = ptr ? ptr->dup () : 0;
01916 }
01917 }
01918
01919
01920
01921
01922 mxArray_struct& operator = (const mxArray_struct& val);
01923 };
01924
01925
01926
01927 class mxArray_cell : public mxArray_matlab
01928 {
01929 public:
01930
01931 mxArray_cell (mwSize ndims_arg, const mwSize *dims_arg)
01932 : mxArray_matlab (mxCELL_CLASS, ndims_arg, dims_arg),
01933 data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
01934
01935 mxArray_cell (const dim_vector& dv)
01936 : mxArray_matlab (mxCELL_CLASS, dv),
01937 data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
01938
01939 mxArray_cell (mwSize m, mwSize n)
01940 : mxArray_matlab (mxCELL_CLASS, m, n),
01941 data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
01942
01943 mxArray_cell *dup (void) const { return new mxArray_cell (*this); }
01944
01945 ~mxArray_cell (void)
01946 {
01947 mwSize nel = get_number_of_elements ();
01948
01949 for (mwIndex i = 0; i < nel; i++)
01950 delete data[i];
01951
01952 mxFree (data);
01953 }
01954
01955 mxArray *get_cell (mwIndex idx) const
01956 {
01957 return idx >= 0 && idx < get_number_of_elements () ? data[idx] : 0;
01958 }
01959
01960 void set_cell (mwIndex idx, mxArray *val);
01961
01962 void *get_data (void) const { return data; }
01963
01964 void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
01965
01966 protected:
01967
01968 octave_value as_octave_value (void) const
01969 {
01970 dim_vector dv = dims_to_dim_vector ();
01971
01972 Cell c (dv);
01973
01974 mwSize nel = get_number_of_elements ();
01975
01976 octave_value *p = c.fortran_vec ();
01977
01978 for (mwIndex i = 0; i < nel; i++)
01979 p[i] = mxArray::as_octave_value (data[i]);
01980
01981 return c;
01982 }
01983
01984 private:
01985
01986 mxArray **data;
01987
01988 mxArray_cell (const mxArray_cell& val)
01989 : mxArray_matlab (val),
01990 data (static_cast<mxArray **> (malloc (get_number_of_elements () * sizeof (mxArray *))))
01991 {
01992 mwSize nel = get_number_of_elements ();
01993
01994 for (mwIndex i = 0; i < nel; i++)
01995 {
01996 mxArray *ptr = val.data[i];
01997 data[i] = ptr ? ptr->dup () : 0;
01998 }
01999 }
02000
02001
02002
02003
02004 mxArray_cell& operator = (const mxArray_cell&);
02005 };
02006
02007
02008
02009 mxArray::mxArray (const octave_value& ov)
02010 : rep (new mxArray_octave_value (ov)), name (0) { }
02011
02012 mxArray::mxArray (mxClassID id, mwSize ndims, const mwSize *dims, mxComplexity flag)
02013 : rep (new mxArray_number (id, ndims, dims, flag)), name (0) { }
02014
02015 mxArray::mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag)
02016 : rep (new mxArray_number (id, dv, flag)), name (0) { }
02017
02018 mxArray::mxArray (mxClassID id, mwSize m, mwSize n, mxComplexity flag)
02019 : rep (new mxArray_number (id, m, n, flag)), name (0) { }
02020
02021 mxArray::mxArray (mxClassID id, double val)
02022 : rep (new mxArray_number (id, val)), name (0) { }
02023
02024 mxArray::mxArray (mxClassID id, mxLogical val)
02025 : rep (new mxArray_number (id, val)), name (0) { }
02026
02027 mxArray::mxArray (const char *str)
02028 : rep (new mxArray_number (str)), name (0) { }
02029
02030 mxArray::mxArray (mwSize m, const char **str)
02031 : rep (new mxArray_number (m, str)), name (0) { }
02032
02033 mxArray::mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
02034 : rep (new mxArray_sparse (id, m, n, nzmax, flag)), name (0) { }
02035
02036 mxArray::mxArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
02037 : rep (new mxArray_struct (ndims, dims, num_keys, keys)), name (0) { }
02038
02039 mxArray::mxArray (const dim_vector& dv, int num_keys, const char **keys)
02040 : rep (new mxArray_struct (dv, num_keys, keys)), name (0) { }
02041
02042 mxArray::mxArray (mwSize m, mwSize n, int num_keys, const char **keys)
02043 : rep (new mxArray_struct (m, n, num_keys, keys)), name (0) { }
02044
02045 mxArray::mxArray (mwSize ndims, const mwSize *dims)
02046 : rep (new mxArray_cell (ndims, dims)), name (0) { }
02047
02048 mxArray::mxArray (const dim_vector& dv)
02049 : rep (new mxArray_cell (dv)), name (0) { }
02050
02051 mxArray::mxArray (mwSize m, mwSize n)
02052 : rep (new mxArray_cell (m, n)), name (0) { }
02053
02054 mxArray::~mxArray (void)
02055 {
02056 mxFree (name);
02057
02058 delete rep;
02059 }
02060
02061 void
02062 mxArray::set_name (const char *name_arg)
02063 {
02064 mxFree (name);
02065 name = strsave (name_arg);
02066 }
02067
02068 octave_value
02069 mxArray::as_octave_value (mxArray *ptr)
02070 {
02071 return ptr ? ptr->as_octave_value () : octave_value (Matrix ());
02072 }
02073
02074 octave_value
02075 mxArray::as_octave_value (void) const
02076 {
02077 return rep->as_octave_value ();
02078 }
02079
02080 void
02081 mxArray::maybe_mutate (void) const
02082 {
02083 if (rep->is_octave_value ())
02084 {
02085
02086
02087
02088
02089 mxArray *new_val = rep->mutate ();
02090
02091 if (new_val)
02092 {
02093 delete rep;
02094 rep = new_val->rep;
02095 new_val->rep = 0;
02096 delete new_val;
02097 }
02098 }
02099 }
02100
02101
02102
02103
02104
02105
02106 class mex
02107 {
02108 public:
02109
02110 mex (octave_mex_function *f)
02111 : curr_mex_fcn (f), memlist (), arraylist (), fname (0) { }
02112
02113 ~mex (void)
02114 {
02115 if (! memlist.empty ())
02116 error ("mex: %s: cleanup failed", function_name ());
02117
02118 mxFree (fname);
02119 }
02120
02121 const char *function_name (void) const
02122 {
02123 if (! fname)
02124 {
02125 octave_function *fcn = octave_call_stack::current ();
02126
02127 if (fcn)
02128 {
02129 std::string nm = fcn->name ();
02130 fname = mxArray::strsave (nm.c_str ());
02131 }
02132 else
02133 fname = mxArray::strsave ("unknown");
02134 }
02135
02136 return fname;
02137 }
02138
02139
02140 static void cleanup (void *ptr)
02141 {
02142 mex *context = static_cast<mex *> (ptr);
02143
02144
02145 for (std::set<void *>::iterator p = context->memlist.begin ();
02146 p != context->memlist.end (); p++)
02147 xfree (*p);
02148
02149 context->memlist.clear ();
02150
02151
02152 for (std::set<mxArray *>::iterator p = context->arraylist.begin ();
02153 p != context->arraylist.end (); p++)
02154 delete *p;
02155
02156 context->arraylist.clear ();
02157 }
02158
02159
02160 void *malloc_unmarked (size_t n)
02161 {
02162 void *ptr = gnulib::malloc (n);
02163
02164 if (! ptr)
02165 {
02166
02167
02168 error ("%s: failed to allocate %d bytes of memory",
02169 function_name (), n);
02170
02171 abort ();
02172 }
02173
02174 global_mark (ptr);
02175
02176 return ptr;
02177 }
02178
02179
02180 void *malloc (size_t n)
02181 {
02182 void *ptr = malloc_unmarked (n);
02183
02184 mark (ptr);
02185
02186 return ptr;
02187 }
02188
02189
02190 void *calloc_unmarked (size_t n, size_t t)
02191 {
02192 void *ptr = malloc_unmarked (n*t);
02193
02194 memset (ptr, 0, n*t);
02195
02196 return ptr;
02197 }
02198
02199
02200 void *calloc (size_t n, size_t t)
02201 {
02202 void *ptr = calloc_unmarked (n, t);
02203
02204 mark (ptr);
02205
02206 return ptr;
02207 }
02208
02209
02210
02211
02212 void *realloc (void *ptr, size_t n)
02213 {
02214 void *v;
02215
02216 if (ptr)
02217 {
02218 v = gnulib::realloc (ptr, n);
02219
02220 std::set<void *>::iterator p = memlist.find (ptr);
02221
02222 if (v && p != memlist.end ())
02223 {
02224 memlist.erase (p);
02225 memlist.insert (v);
02226 }
02227
02228 p = global_memlist.find (ptr);
02229
02230 if (v && p != global_memlist.end ())
02231 {
02232 global_memlist.erase (p);
02233 global_memlist.insert (v);
02234 }
02235 }
02236 else
02237 v = malloc (n);
02238
02239 return v;
02240 }
02241
02242
02243 void free (void *ptr)
02244 {
02245 if (ptr)
02246 {
02247 unmark (ptr);
02248
02249 std::set<void *>::iterator p = global_memlist.find (ptr);
02250
02251 if (p != global_memlist.end ())
02252 {
02253 global_memlist.erase (p);
02254
02255 xfree (ptr);
02256 }
02257 else
02258 {
02259 p = foreign_memlist.find (ptr);
02260
02261 if (p != foreign_memlist.end ())
02262 foreign_memlist.erase (p);
02263 #ifdef DEBUG
02264 else
02265 warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc");
02266 #endif
02267 }
02268 }
02269 }
02270
02271
02272 void mark (void *ptr)
02273 {
02274 #ifdef DEBUG
02275 if (memlist.find (ptr) != memlist.end ())
02276 warning ("%s: double registration ignored", function_name ());
02277 #endif
02278
02279 memlist.insert (ptr);
02280 }
02281
02282
02283
02284 void unmark (void *ptr)
02285 {
02286 std::set<void *>::iterator p = memlist.find (ptr);
02287
02288 if (p != memlist.end ())
02289 memlist.erase (p);
02290 #ifdef DEBUG
02291 else
02292 warning ("%s: value not marked", function_name ());
02293 #endif
02294 }
02295
02296 mxArray *mark_array (mxArray *ptr)
02297 {
02298 arraylist.insert (ptr);
02299 return ptr;
02300 }
02301
02302 void unmark_array (mxArray *ptr)
02303 {
02304 std::set<mxArray *>::iterator p = arraylist.find (ptr);
02305
02306 if (p != arraylist.end ())
02307 arraylist.erase (p);
02308 }
02309
02310
02311 void mark_foreign (void *ptr)
02312 {
02313 #ifdef DEBUG
02314 if (foreign_memlist.find (ptr) != foreign_memlist.end ())
02315 warning ("%s: double registration ignored", function_name ());
02316 #endif
02317
02318 foreign_memlist.insert (ptr);
02319 }
02320
02321
02322 void unmark_foreign (void *ptr)
02323 {
02324 std::set<void *>::iterator p = foreign_memlist.find (ptr);
02325
02326 if (p != foreign_memlist.end ())
02327 foreign_memlist.erase (p);
02328 #ifdef DEBUG
02329 else
02330 warning ("%s: value not marked", function_name ());
02331 #endif
02332
02333 }
02334
02335
02336
02337 mxArray *make_value (const octave_value& ov)
02338 {
02339 return mark_array (new mxArray (ov));
02340 }
02341
02342
02343 bool free_value (mxArray *ptr)
02344 {
02345 bool inlist = false;
02346
02347 std::set<mxArray *>::iterator p = arraylist.find (ptr);
02348
02349 if (p != arraylist.end ())
02350 {
02351 inlist = true;
02352 arraylist.erase (p);
02353 delete ptr;
02354 }
02355 #ifdef DEBUG
02356 else
02357 warning ("mex::free_value: skipping memory not allocated by mex::make_value");
02358 #endif
02359
02360 return inlist;
02361 }
02362
02363 octave_mex_function *current_mex_function (void) const
02364 {
02365 return curr_mex_fcn;
02366 }
02367
02368
02369 int trap_feval_error;
02370
02371
02372 jmp_buf jump;
02373
02374
02375 void abort (void) { longjmp (jump, 1); }
02376
02377 private:
02378
02379
02380 octave_mex_function *curr_mex_fcn;
02381
02382
02383 std::set<void *> memlist;
02384
02385
02386 std::set<mxArray *> arraylist;
02387
02388
02389
02390 std::set<void *> foreign_memlist;
02391
02392
02393 mutable char *fname;
02394
02395
02396 static std::set<void *> global_memlist;
02397
02398
02399 void global_mark (void *ptr)
02400 {
02401 #ifdef DEBUG
02402 if (global_memlist.find (ptr) != global_memlist.end ())
02403 warning ("%s: double registration ignored", function_name ());
02404 #endif
02405
02406 global_memlist.insert (ptr);
02407 }
02408
02409
02410 void global_unmark (void *ptr)
02411 {
02412 std::set<void *>::iterator p = global_memlist.find (ptr);
02413
02414 if (p != global_memlist.end ())
02415 global_memlist.erase (p);
02416 #ifdef DEBUG
02417 else
02418 warning ("%s: value not marked", function_name ());
02419 #endif
02420
02421 }
02422
02423
02424
02425 mex (const mex&);
02426
02427 mex& operator = (const mex&);
02428 };
02429
02430
02431 std::set<void *> mex::global_memlist;
02432
02433
02434 mex *mex_context = 0;
02435
02436 void *
02437 mxArray::malloc (size_t n)
02438 {
02439 return mex_context ? mex_context->malloc_unmarked (n) : gnulib::malloc (n);
02440 }
02441
02442 void *
02443 mxArray::calloc (size_t n, size_t t)
02444 {
02445 return mex_context ? mex_context->calloc_unmarked (n, t) : ::calloc (n, t);
02446 }
02447
02448 static inline void *
02449 maybe_mark_foreign (void *ptr)
02450 {
02451 if (mex_context)
02452 mex_context->mark_foreign (ptr);
02453
02454 return ptr;
02455 }
02456
02457 static inline mxArray *
02458 maybe_unmark_array (mxArray *ptr)
02459 {
02460 if (mex_context)
02461 mex_context->unmark_array (ptr);
02462
02463 return ptr;
02464 }
02465
02466 static inline void *
02467 maybe_unmark (void *ptr)
02468 {
02469 if (mex_context)
02470 mex_context->unmark (ptr);
02471
02472 return ptr;
02473 }
02474
02475 void
02476 mxArray_struct::set_field_by_number (mwIndex index, int key_num, mxArray *val)
02477 {
02478 if (key_num >= 0 && key_num < nfields)
02479 data[nfields * index + key_num] = maybe_unmark_array (val);
02480 }
02481
02482 void
02483 mxArray_cell::set_cell (mwIndex idx, mxArray *val)
02484 {
02485 if (idx >= 0 && idx < get_number_of_elements ())
02486 data[idx] = maybe_unmark_array (val);
02487 }
02488
02489
02490
02491
02492
02493
02494
02495 int
02496 mxIsFinite (const double v)
02497 {
02498 return lo_ieee_finite (v) != 0;
02499 }
02500
02501 int
02502 mxIsInf (const double v)
02503 {
02504 return lo_ieee_isinf (v) != 0;
02505 }
02506
02507 int
02508 mxIsNaN (const double v)
02509 {
02510 return lo_ieee_isnan (v) != 0;
02511 }
02512
02513 double
02514 mxGetEps (void)
02515 {
02516 return DBL_EPSILON;
02517 }
02518
02519 double
02520 mxGetInf (void)
02521 {
02522 return lo_ieee_inf_value ();
02523 }
02524
02525 double
02526 mxGetNaN (void)
02527 {
02528 return lo_ieee_nan_value ();
02529 }
02530
02531
02532 void *
02533 mxCalloc (size_t n, size_t size)
02534 {
02535 return mex_context ? mex_context->calloc (n, size) : calloc (n, size);
02536 }
02537
02538 void *
02539 mxMalloc (size_t n)
02540 {
02541 return mex_context ? mex_context->malloc (n) : gnulib::malloc (n);
02542 }
02543
02544 void *
02545 mxRealloc (void *ptr, size_t size)
02546 {
02547 return mex_context ? mex_context->realloc (ptr, size) : gnulib::realloc (ptr, size);
02548 }
02549
02550 void
02551 mxFree (void *ptr)
02552 {
02553 if (mex_context)
02554 mex_context->free (ptr);
02555 else
02556 xfree (ptr);
02557 }
02558
02559 static inline mxArray *
02560 maybe_mark_array (mxArray *ptr)
02561 {
02562 return mex_context ? mex_context->mark_array (ptr) : ptr;
02563 }
02564
02565
02566 mxArray *
02567 mxCreateCellArray (mwSize ndims, const mwSize *dims)
02568 {
02569 return maybe_mark_array (new mxArray (ndims, dims));
02570 }
02571
02572 mxArray *
02573 mxCreateCellMatrix (mwSize m, mwSize n)
02574 {
02575 return maybe_mark_array (new mxArray (m, n));
02576 }
02577
02578 mxArray *
02579 mxCreateCharArray (mwSize ndims, const mwSize *dims)
02580 {
02581 return maybe_mark_array (new mxArray (mxCHAR_CLASS, ndims, dims));
02582 }
02583
02584 mxArray *
02585 mxCreateCharMatrixFromStrings (mwSize m, const char **str)
02586 {
02587 return maybe_mark_array (new mxArray (m, str));
02588 }
02589
02590 mxArray *
02591 mxCreateDoubleMatrix (mwSize m, mwSize n, mxComplexity flag)
02592 {
02593 return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, flag));
02594 }
02595
02596 mxArray *
02597 mxCreateDoubleScalar (double val)
02598 {
02599 return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, val));
02600 }
02601
02602 mxArray *
02603 mxCreateLogicalArray (mwSize ndims, const mwSize *dims)
02604 {
02605 return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, ndims, dims));
02606 }
02607
02608 mxArray *
02609 mxCreateLogicalMatrix (mwSize m, mwSize n)
02610 {
02611 return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n));
02612 }
02613
02614 mxArray *
02615 mxCreateLogicalScalar (mxLogical val)
02616 {
02617 return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, val));
02618 }
02619
02620 mxArray *
02621 mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,
02622 mxComplexity flag)
02623 {
02624 return maybe_mark_array (new mxArray (class_id, ndims, dims, flag));
02625 }
02626
02627 mxArray *
02628 mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
02629 {
02630 return maybe_mark_array (new mxArray (class_id, m, n, flag));
02631 }
02632
02633 mxArray *
02634 mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
02635 {
02636 return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, nzmax, flag));
02637 }
02638
02639 mxArray *
02640 mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax)
02641 {
02642 return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n, nzmax));
02643 }
02644
02645 mxArray *
02646 mxCreateString (const char *str)
02647 {
02648 return maybe_mark_array (new mxArray (str));
02649 }
02650
02651 mxArray *
02652 mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
02653 {
02654 return maybe_mark_array (new mxArray (ndims, dims, num_keys, keys));
02655 }
02656
02657 mxArray *
02658 mxCreateStructMatrix (mwSize m, mwSize n, int num_keys, const char **keys)
02659 {
02660 return maybe_mark_array (new mxArray (m, n, num_keys, keys));
02661 }
02662
02663
02664 mxArray *
02665 mxDuplicateArray (const mxArray *ptr)
02666 {
02667 return maybe_mark_array (ptr->dup ());
02668 }
02669
02670
02671 void
02672 mxDestroyArray (mxArray *ptr)
02673 {
02674 if (! (mex_context && mex_context->free_value (ptr)))
02675 delete ptr;
02676 }
02677
02678
02679 int
02680 mxIsCell (const mxArray *ptr)
02681 {
02682 return ptr->is_cell ();
02683 }
02684
02685 int
02686 mxIsChar (const mxArray *ptr)
02687 {
02688 return ptr->is_char ();
02689 }
02690
02691 int
02692 mxIsClass (const mxArray *ptr, const char *name)
02693 {
02694 return ptr->is_class (name);
02695 }
02696
02697 int
02698 mxIsComplex (const mxArray *ptr)
02699 {
02700 return ptr->is_complex ();
02701 }
02702
02703 int
02704 mxIsDouble (const mxArray *ptr)
02705 {
02706 return ptr->is_double ();
02707 }
02708
02709 int
02710 mxIsFunctionHandle (const mxArray *ptr)
02711 {
02712 return ptr->is_function_handle ();
02713 }
02714
02715 int
02716 mxIsInt16 (const mxArray *ptr)
02717 {
02718 return ptr->is_int16 ();
02719 }
02720
02721 int
02722 mxIsInt32 (const mxArray *ptr)
02723 {
02724 return ptr->is_int32 ();
02725 }
02726
02727 int
02728 mxIsInt64 (const mxArray *ptr)
02729 {
02730 return ptr->is_int64 ();
02731 }
02732
02733 int
02734 mxIsInt8 (const mxArray *ptr)
02735 {
02736 return ptr->is_int8 ();
02737 }
02738
02739 int
02740 mxIsLogical (const mxArray *ptr)
02741 {
02742 return ptr->is_logical ();
02743 }
02744
02745 int
02746 mxIsNumeric (const mxArray *ptr)
02747 {
02748 return ptr->is_numeric ();
02749 }
02750
02751 int
02752 mxIsSingle (const mxArray *ptr)
02753 {
02754 return ptr->is_single ();
02755 }
02756
02757 int
02758 mxIsSparse (const mxArray *ptr)
02759 {
02760 return ptr->is_sparse ();
02761 }
02762
02763 int
02764 mxIsStruct (const mxArray *ptr)
02765 {
02766 return ptr->is_struct ();
02767 }
02768
02769 int
02770 mxIsUint16 (const mxArray *ptr)
02771 {
02772 return ptr->is_uint16 ();
02773 }
02774
02775 int
02776 mxIsUint32 (const mxArray *ptr)
02777 {
02778 return ptr->is_uint32 ();
02779 }
02780
02781 int
02782 mxIsUint64 (const mxArray *ptr)
02783 {
02784 return ptr->is_uint64 ();
02785 }
02786
02787 int
02788 mxIsUint8 (const mxArray *ptr)
02789 {
02790 return ptr->is_uint8 ();
02791 }
02792
02793
02794 int
02795 mxIsLogicalScalar (const mxArray *ptr)
02796 {
02797 return ptr->is_logical_scalar ();
02798 }
02799
02800
02801 int
02802 mxIsLogicalScalarTrue (const mxArray *ptr)
02803 {
02804 return ptr->is_logical_scalar_true ();
02805 }
02806
02807
02808 int
02809 mxIsEmpty (const mxArray *ptr)
02810 {
02811 return ptr->is_empty ();
02812 }
02813
02814
02815 int
02816 mxIsFromGlobalWS (const mxArray *)
02817 {
02818
02819 abort ();
02820 return 0;
02821 }
02822
02823
02824 size_t
02825 mxGetM (const mxArray *ptr)
02826 {
02827 return ptr->get_m ();
02828 }
02829
02830 size_t
02831 mxGetN (const mxArray *ptr)
02832 {
02833 return ptr->get_n ();
02834 }
02835
02836 mwSize *
02837 mxGetDimensions (const mxArray *ptr)
02838 {
02839 return ptr->get_dimensions ();
02840 }
02841
02842 mwSize
02843 mxGetNumberOfDimensions (const mxArray *ptr)
02844 {
02845 return ptr->get_number_of_dimensions ();
02846 }
02847
02848 size_t
02849 mxGetNumberOfElements (const mxArray *ptr)
02850 {
02851 return ptr->get_number_of_elements ();
02852 }
02853
02854
02855 void
02856 mxSetM (mxArray *ptr, mwSize m)
02857 {
02858 ptr->set_m (m);
02859 }
02860
02861 void
02862 mxSetN (mxArray *ptr, mwSize n)
02863 {
02864 ptr->set_n (n);
02865 }
02866
02867 void
02868 mxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims)
02869 {
02870 ptr->set_dimensions (static_cast<mwSize *> (
02871 maybe_unmark (const_cast<mwSize *> (dims))),
02872 ndims);
02873 }
02874
02875
02876 double *
02877 mxGetPr (const mxArray *ptr)
02878 {
02879 return static_cast<double *> (ptr->get_data ());
02880 }
02881
02882 double *
02883 mxGetPi (const mxArray *ptr)
02884 {
02885 return static_cast<double *> (ptr->get_imag_data ());
02886 }
02887
02888 double
02889 mxGetScalar (const mxArray *ptr)
02890 {
02891 return ptr->get_scalar ();
02892 }
02893
02894 mxChar *
02895 mxGetChars (const mxArray *ptr)
02896 {
02897 return static_cast<mxChar *> (ptr->get_data ());
02898 }
02899
02900 mxLogical *
02901 mxGetLogicals (const mxArray *ptr)
02902 {
02903 return static_cast<mxLogical *> (ptr->get_data ());
02904 }
02905
02906 void *
02907 mxGetData (const mxArray *ptr)
02908 {
02909 return ptr->get_data ();
02910 }
02911
02912 void *
02913 mxGetImagData (const mxArray *ptr)
02914 {
02915 return ptr->get_imag_data ();
02916 }
02917
02918
02919 void
02920 mxSetPr (mxArray *ptr, double *pr)
02921 {
02922 ptr->set_data (maybe_unmark (pr));
02923 }
02924
02925 void
02926 mxSetPi (mxArray *ptr, double *pi)
02927 {
02928 ptr->set_imag_data (maybe_unmark (pi));
02929 }
02930
02931 void
02932 mxSetData (mxArray *ptr, void *pr)
02933 {
02934 ptr->set_data (maybe_unmark (pr));
02935 }
02936
02937 void
02938 mxSetImagData (mxArray *ptr, void *pi)
02939 {
02940 ptr->set_imag_data (maybe_unmark (pi));
02941 }
02942
02943
02944 mxClassID
02945 mxGetClassID (const mxArray *ptr)
02946 {
02947 return ptr->get_class_id ();
02948 }
02949
02950 const char *
02951 mxGetClassName (const mxArray *ptr)
02952 {
02953 return ptr->get_class_name ();
02954 }
02955
02956 void
02957 mxSetClassName (mxArray *ptr, const char *name)
02958 {
02959 ptr->set_class_name (name);
02960 }
02961
02962
02963 mxArray *
02964 mxGetCell (const mxArray *ptr, mwIndex idx)
02965 {
02966 return ptr->get_cell (idx);
02967 }
02968
02969 void
02970 mxSetCell (mxArray *ptr, mwIndex idx, mxArray *val)
02971 {
02972 ptr->set_cell (idx, val);
02973 }
02974
02975
02976 mwIndex *
02977 mxGetIr (const mxArray *ptr)
02978 {
02979 return ptr->get_ir ();
02980 }
02981
02982 mwIndex *
02983 mxGetJc (const mxArray *ptr)
02984 {
02985 return ptr->get_jc ();
02986 }
02987
02988 mwSize
02989 mxGetNzmax (const mxArray *ptr)
02990 {
02991 return ptr->get_nzmax ();
02992 }
02993
02994 void
02995 mxSetIr (mxArray *ptr, mwIndex *ir)
02996 {
02997 ptr->set_ir (static_cast <mwIndex *> (maybe_unmark (ir)));
02998 }
02999
03000 void
03001 mxSetJc (mxArray *ptr, mwIndex *jc)
03002 {
03003 ptr->set_jc (static_cast<mwIndex *> (maybe_unmark (jc)));
03004 }
03005
03006 void
03007 mxSetNzmax (mxArray *ptr, mwSize nzmax)
03008 {
03009 ptr->set_nzmax (nzmax);
03010 }
03011
03012
03013 int
03014 mxAddField (mxArray *ptr, const char *key)
03015 {
03016 return ptr->add_field (key);
03017 }
03018
03019 void
03020 mxRemoveField (mxArray *ptr, int key_num)
03021 {
03022 ptr->remove_field (key_num);
03023 }
03024
03025 mxArray *
03026 mxGetField (const mxArray *ptr, mwIndex index, const char *key)
03027 {
03028 int key_num = mxGetFieldNumber (ptr, key);
03029 return mxGetFieldByNumber (ptr, index, key_num);
03030 }
03031
03032 mxArray *
03033 mxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num)
03034 {
03035 return ptr->get_field_by_number (index, key_num);
03036 }
03037
03038 void
03039 mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val)
03040 {
03041 int key_num = mxGetFieldNumber (ptr, key);
03042 mxSetFieldByNumber (ptr, index, key_num, val);
03043 }
03044
03045 void
03046 mxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val)
03047 {
03048 ptr->set_field_by_number (index, key_num, val);
03049 }
03050
03051 int
03052 mxGetNumberOfFields (const mxArray *ptr)
03053 {
03054 return ptr->get_number_of_fields ();
03055 }
03056
03057 const char *
03058 mxGetFieldNameByNumber (const mxArray *ptr, int key_num)
03059 {
03060 return ptr->get_field_name_by_number (key_num);
03061 }
03062
03063 int
03064 mxGetFieldNumber (const mxArray *ptr, const char *key)
03065 {
03066 return ptr->get_field_number (key);
03067 }
03068
03069 int
03070 mxGetString (const mxArray *ptr, char *buf, mwSize buflen)
03071 {
03072 return ptr->get_string (buf, buflen);
03073 }
03074
03075 char *
03076 mxArrayToString (const mxArray *ptr)
03077 {
03078 return ptr->array_to_string ();
03079 }
03080
03081 mwIndex
03082 mxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs)
03083 {
03084 return ptr->calc_single_subscript (nsubs, subs);
03085 }
03086
03087 size_t
03088 mxGetElementSize (const mxArray *ptr)
03089 {
03090 return ptr->get_element_size ();
03091 }
03092
03093
03094
03095 typedef void (*cmex_fptr) (int nlhs, mxArray **plhs, int nrhs, mxArray **prhs);
03096 typedef F77_RET_T (*fmex_fptr) (int& nlhs, mxArray **plhs, int& nrhs, mxArray **prhs);
03097
03098 octave_value_list
03099 call_mex (bool have_fmex, void *f, const octave_value_list& args,
03100 int nargout_arg, octave_mex_function *curr_mex_fcn)
03101 {
03102
03103
03104
03105 volatile int nargout = nargout_arg;
03106
03107 int nargin = args.length ();
03108 OCTAVE_LOCAL_BUFFER (mxArray *, argin, nargin);
03109 for (int i = 0; i < nargin; i++)
03110 argin[i] = 0;
03111
03112 int nout = nargout == 0 ? 1 : nargout;
03113 OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout);
03114 for (int i = 0; i < nout; i++)
03115 argout[i] = 0;
03116
03117 unwind_protect_safe frame;
03118
03119
03120 frame.protect_var (mex_context);
03121
03122 mex context (curr_mex_fcn);
03123
03124 frame.add (mex::cleanup, static_cast<void *> (&context));
03125
03126 for (int i = 0; i < nargin; i++)
03127 argin[i] = context.make_value (args(i));
03128
03129 if (setjmp (context.jump) == 0)
03130 {
03131 mex_context = &context;
03132
03133 if (have_fmex)
03134 {
03135 fmex_fptr fcn = FCN_PTR_CAST (fmex_fptr, f);
03136
03137 int tmp_nargout = nargout;
03138 int tmp_nargin = nargin;
03139
03140 fcn (tmp_nargout, argout, tmp_nargin, argin);
03141 }
03142 else
03143 {
03144 cmex_fptr fcn = FCN_PTR_CAST (cmex_fptr, f);
03145
03146 fcn (nargout, argout, nargin, argin);
03147 }
03148 }
03149
03150
03151
03152 octave_value_list retval;
03153
03154 if (! error_state)
03155 {
03156 if (nargout == 0 && argout[0])
03157 {
03158
03159 nargout = 1;
03160 }
03161
03162 retval.resize (nargout);
03163
03164 for (int i = 0; i < nargout; i++)
03165 retval(i) = mxArray::as_octave_value (argout[i]);
03166 }
03167
03168
03169 frame.run ();
03170
03171 return retval;
03172 }
03173
03174
03175
03176 const char *
03177 mexFunctionName (void)
03178 {
03179 return mex_context ? mex_context->function_name () : "unknown";
03180 }
03181
03182 int
03183 mexCallMATLAB (int nargout, mxArray *argout[], int nargin, mxArray *argin[],
03184 const char *fname)
03185 {
03186 octave_value_list args;
03187
03188
03189
03190
03191
03192
03193
03194 args.resize (nargin);
03195
03196 for (int i = 0; i < nargin; i++)
03197 args(i) = mxArray::as_octave_value (argin[i]);
03198
03199 octave_value_list retval = feval (fname, args, nargout);
03200
03201 if (error_state && mex_context->trap_feval_error == 0)
03202 {
03203
03204
03205
03206
03207
03208
03209
03210 args.resize (0);
03211 retval.resize (0);
03212 mex_context->abort ();
03213 }
03214
03215 int num_to_copy = retval.length ();
03216
03217 if (nargout < retval.length ())
03218 num_to_copy = nargout;
03219
03220 for (int i = 0; i < num_to_copy; i++)
03221 {
03222
03223
03224
03225
03226 argout[i] = mex_context->make_value (retval (i));
03227 }
03228
03229 while (num_to_copy < nargout)
03230 argout[num_to_copy++] = 0;
03231
03232 if (error_state)
03233 {
03234 error_state = 0;
03235 return 1;
03236 }
03237 else
03238 return 0;
03239 }
03240
03241 void
03242 mexSetTrapFlag (int flag)
03243 {
03244 if (mex_context)
03245 mex_context->trap_feval_error = flag;
03246 }
03247
03248 int
03249 mexEvalString (const char *s)
03250 {
03251 int retval = 0;
03252
03253 int parse_status;
03254
03255 octave_value_list ret;
03256
03257 ret = eval_string (s, false, parse_status, 0);
03258
03259 if (parse_status || error_state)
03260 {
03261 error_state = 0;
03262
03263 retval = 1;
03264 }
03265
03266 return retval;
03267 }
03268
03269 void
03270 mexErrMsgTxt (const char *s)
03271 {
03272 if (s && strlen (s) > 0)
03273 error ("%s: %s", mexFunctionName (), s);
03274 else
03275
03276 error ("");
03277
03278 mex_context->abort ();
03279 }
03280
03281 void
03282 mexErrMsgIdAndTxt (const char *id, const char *fmt, ...)
03283 {
03284 if (fmt && strlen (fmt) > 0)
03285 {
03286 const char *fname = mexFunctionName ();
03287 size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
03288 OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
03289 sprintf (tmpfmt, "%s: %s", fname, fmt);
03290 va_list args;
03291 va_start (args, fmt);
03292 verror_with_id (id, tmpfmt, args);
03293 va_end (args);
03294 }
03295 else
03296
03297 error ("");
03298
03299 mex_context->abort ();
03300 }
03301
03302 void
03303 mexWarnMsgTxt (const char *s)
03304 {
03305 warning ("%s", s);
03306 }
03307
03308 void
03309 mexWarnMsgIdAndTxt (const char *id, const char *fmt, ...)
03310 {
03311
03312
03313
03314 if (fmt && strlen (fmt) > 0)
03315 {
03316 const char *fname = mexFunctionName ();
03317 size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
03318 OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
03319 sprintf (tmpfmt, "%s: %s", fname, fmt);
03320 va_list args;
03321 va_start (args, fmt);
03322 vwarning_with_id (id, tmpfmt, args);
03323 va_end (args);
03324 }
03325 }
03326
03327 int
03328 mexPrintf (const char *fmt, ...)
03329 {
03330 int retval;
03331 va_list args;
03332 va_start (args, fmt);
03333 retval = octave_vformat (octave_stdout, fmt, args);
03334 va_end (args);
03335 return retval;
03336 }
03337
03338 mxArray *
03339 mexGetVariable (const char *space, const char *name)
03340 {
03341 mxArray *retval = 0;
03342
03343 octave_value val;
03344
03345 if (! strcmp (space, "global"))
03346 val = get_global_value (name);
03347 else
03348 {
03349
03350
03351 unwind_protect frame;
03352
03353 bool caller = ! strcmp (space, "caller");
03354 bool base = ! strcmp (space, "base");
03355
03356 if (caller || base)
03357 {
03358 if (caller)
03359 octave_call_stack::goto_caller_frame ();
03360 else
03361 octave_call_stack::goto_base_frame ();
03362
03363 if (! error_state)
03364 frame.add_fcn (octave_call_stack::pop);
03365
03366 val = symbol_table::varval (name);
03367 }
03368 else
03369 mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
03370 }
03371
03372 if (val.is_defined ())
03373 {
03374 retval = mex_context->make_value (val);
03375
03376 retval->set_name (name);
03377 }
03378
03379 return retval;
03380 }
03381
03382 const mxArray *
03383 mexGetVariablePtr (const char *space, const char *name)
03384 {
03385 return mexGetVariable (space, name);
03386 }
03387
03388 int
03389 mexPutVariable (const char *space, const char *name, mxArray *ptr)
03390 {
03391 if (! ptr)
03392 return 1;
03393
03394 if (! name)
03395 return 1;
03396
03397 if (name[0] == '\0')
03398 name = ptr->get_name ();
03399
03400 if (! name || name[0] == '\0')
03401 return 1;
03402
03403 if (! strcmp (space, "global"))
03404 set_global_value (name, mxArray::as_octave_value (ptr));
03405 else
03406 {
03407
03408
03409 unwind_protect frame;
03410
03411 bool caller = ! strcmp (space, "caller");
03412 bool base = ! strcmp (space, "base");
03413
03414 if (caller || base)
03415 {
03416 if (caller)
03417 octave_call_stack::goto_caller_frame ();
03418 else
03419 octave_call_stack::goto_base_frame ();
03420
03421 if (! error_state)
03422 frame.add_fcn (octave_call_stack::pop);
03423
03424 symbol_table::varref (name) = mxArray::as_octave_value (ptr);
03425 }
03426 else
03427 mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
03428 }
03429
03430 return 0;
03431 }
03432
03433 void
03434 mexMakeArrayPersistent (mxArray *ptr)
03435 {
03436 maybe_unmark_array (ptr);
03437 }
03438
03439 void
03440 mexMakeMemoryPersistent (void *ptr)
03441 {
03442 maybe_unmark (ptr);
03443 }
03444
03445 int
03446 mexAtExit (void (*f) (void))
03447 {
03448 if (mex_context)
03449 {
03450 octave_mex_function *curr_mex_fcn = mex_context->current_mex_function ();
03451
03452 assert (curr_mex_fcn);
03453
03454 curr_mex_fcn->atexit (f);
03455 }
03456
03457 return 0;
03458 }
03459
03460 const mxArray *
03461 mexGet (double handle, const char *property)
03462 {
03463 mxArray *m = 0;
03464 octave_value ret = get_property_from_handle (handle, property, "mexGet");
03465
03466 if (!error_state && ret.is_defined())
03467 m = ret.as_mxArray ();
03468 return m;
03469 }
03470
03471 int
03472 mexIsGlobal (const mxArray *ptr)
03473 {
03474 return mxIsFromGlobalWS (ptr);
03475 }
03476
03477 int
03478 mexIsLocked (void)
03479 {
03480 int retval = 0;
03481
03482 if (mex_context)
03483 {
03484 const char *fname = mexFunctionName ();
03485
03486 retval = mislocked (fname);
03487 }
03488
03489 return retval;
03490 }
03491
03492 std::map<std::string,int> mex_lock_count;
03493
03494 void
03495 mexLock (void)
03496 {
03497 if (mex_context)
03498 {
03499 const char *fname = mexFunctionName ();
03500
03501 if (mex_lock_count.find (fname) == mex_lock_count.end ())
03502 mex_lock_count[fname] = 1;
03503 else
03504 mex_lock_count[fname]++;
03505
03506 mlock ();
03507 }
03508 }
03509
03510 int
03511 mexSet (double handle, const char *property, mxArray *val)
03512 {
03513 bool ret =
03514 set_property_in_handle (handle, property, mxArray::as_octave_value (val),
03515 "mexSet");
03516 return (ret ? 0 : 1);
03517 }
03518
03519 void
03520 mexUnlock (void)
03521 {
03522 if (mex_context)
03523 {
03524 const char *fname = mexFunctionName ();
03525
03526 std::map<std::string,int>::iterator p = mex_lock_count.find (fname);
03527
03528 if (p != mex_lock_count.end ())
03529 {
03530 int count = --mex_lock_count[fname];
03531
03532 if (count == 0)
03533 {
03534 munlock (fname);
03535
03536 mex_lock_count.erase (p);
03537 }
03538 }
03539 }
03540 }