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