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