comparison src/mex.cc @ 5900:c20eb7330d13

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