00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030
00031 #include <istream>
00032 #include <iostream>
00033 #include <sstream>
00034 #include <vector>
00035
00036 #include "oct-locbuf.h"
00037
00038 #include "defun.h"
00039 #include "error.h"
00040 #include "gripes.h"
00041 #include "oct-map.h"
00042 #include "ov-base.h"
00043 #include "ov-fcn-inline.h"
00044 #include "ov-usr-fcn.h"
00045 #include "pr-output.h"
00046 #include "variables.h"
00047 #include "parse.h"
00048 #include "toplev.h"
00049
00050 #include "byte-swap.h"
00051 #include "ls-ascii-helper.h"
00052 #include "ls-oct-ascii.h"
00053 #include "ls-hdf5.h"
00054 #include "ls-utils.h"
00055
00056 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_inline);
00057
00058 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_inline,
00059 "inline function",
00060 "function_handle");
00061
00062 octave_fcn_inline::octave_fcn_inline (const std::string& f,
00063 const string_vector& a,
00064 const std::string& n)
00065 : octave_fcn_handle (n), iftext (f), ifargs (a)
00066 {
00067
00068
00069 std::ostringstream buf;
00070
00071 buf << "@(";
00072
00073 for (int i = 0; i < ifargs.length (); i++)
00074 {
00075 if (i > 0)
00076 buf << ", ";
00077
00078 buf << ifargs(i);
00079 }
00080
00081 buf << ") " << iftext;
00082
00083 int parse_status;
00084 octave_value anon_fcn_handle = eval_string (buf.str (), true, parse_status);
00085
00086 if (parse_status == 0)
00087 {
00088 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
00089
00090 if (fh)
00091 {
00092 fcn = fh->fcn_val ();
00093
00094 octave_user_function *uf = fcn.user_function_value ();
00095
00096 if (uf)
00097 {
00098 octave_function *curr_fcn = octave_call_stack::current ();
00099
00100 if (curr_fcn)
00101 {
00102 symbol_table::scope_id parent_scope
00103 = curr_fcn->parent_fcn_scope ();
00104
00105 if (parent_scope < 0)
00106 parent_scope = curr_fcn->scope ();
00107
00108 uf->stash_parent_fcn_scope (parent_scope);
00109 }
00110 }
00111 }
00112 }
00113
00114 if (fcn.is_undefined ())
00115 error ("inline: unable to define function");
00116 }
00117
00118
00119
00120 octave_map
00121 octave_fcn_inline::map_value (void) const
00122 {
00123 octave_scalar_map m;
00124
00125 m.assign ("version", 1.0);
00126 m.assign ("isEmpty", 0.0);
00127 m.assign ("expr", fcn_text ());
00128
00129 string_vector args = fcn_arg_names ();
00130
00131 m.assign ("numArgs", args.length ());
00132 m.assign ("args", args);
00133
00134 std::ostringstream buf;
00135
00136 for (int i = 0; i < args.length (); i++)
00137 buf << args(i) << " = INLINE_INPUTS_{" << i + 1 << "}; ";
00138
00139 m.assign ("inputExpr", buf.str ());
00140
00141 return m;
00142 }
00143
00144 bool
00145 octave_fcn_inline::save_ascii (std::ostream& os)
00146 {
00147 os << "# nargs: " << ifargs.length () << "\n";
00148 for (int i = 0; i < ifargs.length (); i++)
00149 os << ifargs(i) << "\n";
00150 if (nm.length () < 1)
00151
00152 os << "0\n";
00153 else
00154 os << nm << "\n";
00155 os << iftext << "\n";
00156 return true;
00157 }
00158
00159 bool
00160 octave_fcn_inline::load_ascii (std::istream& is)
00161 {
00162 int nargs;
00163 if (extract_keyword (is, "nargs", nargs, true))
00164 {
00165 ifargs.resize (nargs);
00166 for (int i = 0; i < nargs; i++)
00167 is >> ifargs(i);
00168 is >> nm;
00169 if (nm == "0")
00170 nm = "";
00171
00172 skip_preceeding_newline (is);
00173
00174 std::string buf;
00175
00176 if (is)
00177 {
00178
00179
00180
00181 buf = read_until_newline (is, true);
00182 }
00183
00184 iftext = buf;
00185
00186 octave_fcn_inline tmp (iftext, ifargs, nm);
00187 fcn = tmp.fcn;
00188
00189 return true;
00190 }
00191 else
00192 return false;
00193 }
00194
00195 bool
00196 octave_fcn_inline::save_binary (std::ostream& os, bool&)
00197 {
00198 int32_t tmp = ifargs.length ();
00199 os.write (reinterpret_cast<char *> (&tmp), 4);
00200 for (int i = 0; i < ifargs.length (); i++)
00201 {
00202 tmp = ifargs(i).length ();
00203 os.write (reinterpret_cast<char *> (&tmp), 4);
00204 os.write (ifargs(i).c_str (), ifargs(i).length ());
00205 }
00206 tmp = nm.length ();
00207 os.write (reinterpret_cast<char *> (&tmp), 4);
00208 os.write (nm.c_str (), nm.length ());
00209 tmp = iftext.length ();
00210 os.write (reinterpret_cast<char *> (&tmp), 4);
00211 os.write (iftext.c_str (), iftext.length ());
00212 return true;
00213 }
00214
00215 bool
00216 octave_fcn_inline::load_binary (std::istream& is, bool swap,
00217 oct_mach_info::float_format)
00218 {
00219 int32_t nargs;
00220 if (! is.read (reinterpret_cast<char *> (&nargs), 4))
00221 return false;
00222 if (swap)
00223 swap_bytes<4> (&nargs);
00224
00225 if (nargs < 1)
00226 return false;
00227 else
00228 {
00229 int32_t tmp;
00230 ifargs.resize (nargs);
00231 for (int i = 0; i < nargs; i++)
00232 {
00233 if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00234 return false;
00235 if (swap)
00236 swap_bytes<4> (&tmp);
00237
00238 OCTAVE_LOCAL_BUFFER (char, ctmp, tmp+1);
00239 is.read (ctmp, tmp);
00240 ifargs(i) = std::string (ctmp);
00241
00242 if (! is)
00243 return false;
00244 }
00245
00246 if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00247 return false;
00248 if (swap)
00249 swap_bytes<4> (&tmp);
00250
00251 OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1);
00252 is.read (ctmp1, tmp);
00253 nm = std::string (ctmp1);
00254
00255 if (! is)
00256 return false;
00257
00258 if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00259 return false;
00260 if (swap)
00261 swap_bytes<4> (&tmp);
00262
00263 OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
00264 is.read (ctmp2, tmp);
00265 iftext = std::string (ctmp2);
00266
00267 if (! is)
00268 return false;
00269
00270 octave_fcn_inline ftmp (iftext, ifargs, nm);
00271 fcn = ftmp.fcn;
00272 }
00273 return true;
00274 }
00275
00276 #if defined (HAVE_HDF5)
00277 bool
00278 octave_fcn_inline::save_hdf5 (hid_t loc_id, const char *name,
00279 bool )
00280 {
00281 hid_t group_hid = -1;
00282 #if HAVE_HDF5_18
00283 group_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00284 #else
00285 group_hid = H5Gcreate (loc_id, name, 0);
00286 #endif
00287 if (group_hid < 0 ) return false;
00288
00289 size_t len = 0;
00290 for (int i = 0; i < ifargs.length (); i++)
00291 if (len < ifargs(i).length ())
00292 len = ifargs(i).length ();
00293
00294 hid_t space_hid = -1, data_hid = -1, type_hid = -1;;
00295 bool retval = true;
00296
00297
00298
00299
00300 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2);
00301
00302
00303 hdims[1] = ifargs.length ();
00304 hdims[0] = len + 1;
00305
00306 space_hid = H5Screate_simple (2, hdims, 0);
00307 if (space_hid < 0)
00308 {
00309 H5Gclose (group_hid);
00310 return false;
00311 }
00312 #if HAVE_HDF5_18
00313 data_hid = H5Dcreate (group_hid, "args", H5T_NATIVE_CHAR, space_hid,
00314 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00315 #else
00316 data_hid = H5Dcreate (group_hid, "args", H5T_NATIVE_CHAR, space_hid,
00317 H5P_DEFAULT);
00318 #endif
00319 if (data_hid < 0)
00320 {
00321 H5Sclose (space_hid);
00322 H5Gclose (group_hid);
00323 return false;
00324 }
00325
00326 OCTAVE_LOCAL_BUFFER (char, s, ifargs.length () * (len + 1));
00327
00328
00329 for (int i = 0; i < ifargs.length (); i++)
00330 {
00331 const char * cptr = ifargs(i).c_str ();
00332 for (size_t j = 0; j < ifargs(i).length (); j++)
00333 s[i*(len+1)+j] = *cptr++;
00334 s[ifargs(i).length ()] = '\0';
00335 }
00336
00337 retval = H5Dwrite (data_hid, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL,
00338 H5P_DEFAULT, s) >= 0;
00339
00340 H5Dclose (data_hid);
00341 H5Sclose (space_hid);
00342
00343 if (!retval)
00344 {
00345 H5Gclose (group_hid);
00346 return false;
00347 }
00348
00349
00350 type_hid = H5Tcopy (H5T_C_S1);
00351 H5Tset_size (type_hid, nm.length () + 1);
00352 if (type_hid < 0)
00353 {
00354 H5Gclose (group_hid);
00355 return false;
00356 }
00357
00358 hdims[0] = 0;
00359 space_hid = H5Screate_simple (0 , hdims, 0);
00360 if (space_hid < 0)
00361 {
00362 H5Tclose (type_hid);
00363 H5Gclose (group_hid);
00364 return false;
00365 }
00366 #if HAVE_HDF5_18
00367 data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid,
00368 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00369 #else
00370 data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, H5P_DEFAULT);
00371 #endif
00372 if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL,
00373 H5P_DEFAULT, nm.c_str ()) < 0)
00374 {
00375 H5Sclose (space_hid);
00376 H5Tclose (type_hid);
00377 H5Gclose (group_hid);
00378 return false;
00379 }
00380 H5Dclose (data_hid);
00381
00382
00383 H5Tset_size (type_hid, iftext.length () + 1);
00384 if (type_hid < 0)
00385 {
00386 H5Gclose (group_hid);
00387 return false;
00388 }
00389
00390 #if HAVE_HDF5_18
00391 data_hid = H5Dcreate (group_hid, "iftext", type_hid, space_hid,
00392 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00393 #else
00394 data_hid = H5Dcreate (group_hid, "iftext", type_hid, space_hid,
00395 H5P_DEFAULT);
00396 #endif
00397 if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL,
00398 H5P_DEFAULT, iftext.c_str ()) < 0)
00399 {
00400 H5Sclose (space_hid);
00401 H5Tclose (type_hid);
00402 H5Gclose (group_hid);
00403 return false;
00404 }
00405
00406 H5Dclose (data_hid);
00407 H5Sclose (space_hid);
00408 H5Tclose (type_hid);
00409 H5Gclose (group_hid);
00410
00411 return retval;
00412 }
00413
00414 bool
00415 octave_fcn_inline::load_hdf5 (hid_t loc_id, const char *name)
00416 {
00417 hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
00418 hsize_t rank;
00419 int slen;
00420
00421 #if HAVE_HDF5_18
00422 group_hid = H5Gopen (loc_id, name, H5P_DEFAULT);
00423 #else
00424 group_hid = H5Gopen (loc_id, name);
00425 #endif
00426 if (group_hid < 0 ) return false;
00427
00428 #if HAVE_HDF5_18
00429 data_hid = H5Dopen (group_hid, "args", H5P_DEFAULT);
00430 #else
00431 data_hid = H5Dopen (group_hid, "args");
00432 #endif
00433 space_hid = H5Dget_space (data_hid);
00434 rank = H5Sget_simple_extent_ndims (space_hid);
00435
00436 if (rank != 2)
00437 {
00438 H5Dclose (data_hid);
00439 H5Sclose (space_hid);
00440 H5Gclose (group_hid);
00441 return false;
00442 }
00443
00444 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00445 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
00446
00447 H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
00448
00449 ifargs.resize (hdims[1]);
00450
00451 OCTAVE_LOCAL_BUFFER (char, s1, hdims[0] * hdims[1]);
00452
00453 if (H5Dread (data_hid, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL,
00454 H5P_DEFAULT, s1) < 0)
00455 {
00456 H5Dclose (data_hid);
00457 H5Sclose (space_hid);
00458 H5Gclose (group_hid);
00459 return false;
00460 }
00461
00462 H5Dclose (data_hid);
00463 H5Sclose (space_hid);
00464
00465 for (size_t i = 0; i < hdims[1]; i++)
00466 ifargs(i) = std::string (s1 + i*hdims[0]);
00467
00468 #if HAVE_HDF5_18
00469 data_hid = H5Dopen (group_hid, "nm", H5P_DEFAULT);
00470 #else
00471 data_hid = H5Dopen (group_hid, "nm");
00472 #endif
00473
00474 if (data_hid < 0)
00475 {
00476 H5Gclose (group_hid);
00477 return false;
00478 }
00479
00480 type_hid = H5Dget_type (data_hid);
00481 type_class_hid = H5Tget_class (type_hid);
00482
00483 if (type_class_hid != H5T_STRING)
00484 {
00485 H5Tclose (type_hid);
00486 H5Dclose (data_hid);
00487 H5Gclose (group_hid);
00488 return false;
00489 }
00490
00491 space_hid = H5Dget_space (data_hid);
00492 rank = H5Sget_simple_extent_ndims (space_hid);
00493
00494 if (rank != 0)
00495 {
00496 H5Sclose (space_hid);
00497 H5Tclose (type_hid);
00498 H5Dclose (data_hid);
00499 H5Gclose (group_hid);
00500 return false;
00501 }
00502
00503 slen = H5Tget_size (type_hid);
00504 if (slen < 0)
00505 {
00506 H5Sclose (space_hid);
00507 H5Tclose (type_hid);
00508 H5Dclose (data_hid);
00509 H5Gclose (group_hid);
00510 return false;
00511 }
00512
00513 OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen);
00514
00515
00516 st_id = H5Tcopy (H5T_C_S1);
00517 H5Tset_size (st_id, slen);
00518
00519 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, nm_tmp) < 0)
00520 {
00521 H5Sclose (space_hid);
00522 H5Tclose (type_hid);
00523 H5Gclose (group_hid);
00524 return false;
00525 }
00526 H5Tclose (st_id);
00527 H5Dclose (data_hid);
00528 nm = nm_tmp;
00529
00530 #if HAVE_HDF5_18
00531 data_hid = H5Dopen (group_hid, "iftext", H5P_DEFAULT);
00532 #else
00533 data_hid = H5Dopen (group_hid, "iftext");
00534 #endif
00535
00536 if (data_hid < 0)
00537 {
00538 H5Gclose (group_hid);
00539 return false;
00540 }
00541
00542 type_hid = H5Dget_type (data_hid);
00543 type_class_hid = H5Tget_class (type_hid);
00544
00545 if (type_class_hid != H5T_STRING)
00546 {
00547 H5Tclose (type_hid);
00548 H5Dclose (data_hid);
00549 H5Gclose (group_hid);
00550 return false;
00551 }
00552
00553 space_hid = H5Dget_space (data_hid);
00554 rank = H5Sget_simple_extent_ndims (space_hid);
00555
00556 if (rank != 0)
00557 {
00558 H5Sclose (space_hid);
00559 H5Tclose (type_hid);
00560 H5Dclose (data_hid);
00561 H5Gclose (group_hid);
00562 return false;
00563 }
00564
00565 slen = H5Tget_size (type_hid);
00566 if (slen < 0)
00567 {
00568 H5Sclose (space_hid);
00569 H5Tclose (type_hid);
00570 H5Dclose (data_hid);
00571 H5Gclose (group_hid);
00572 return false;
00573 }
00574
00575 OCTAVE_LOCAL_BUFFER (char, iftext_tmp, slen);
00576
00577
00578 st_id = H5Tcopy (H5T_C_S1);
00579 H5Tset_size (st_id, slen);
00580
00581 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, iftext_tmp) < 0)
00582 {
00583 H5Sclose (space_hid);
00584 H5Tclose (type_hid);
00585 H5Gclose (group_hid);
00586 return false;
00587 }
00588 H5Tclose (st_id);
00589 H5Dclose (data_hid);
00590 iftext = iftext_tmp;
00591
00592 octave_fcn_inline ftmp (iftext, ifargs, nm);
00593 fcn = ftmp.fcn;
00594
00595 return true;
00596 }
00597 #endif
00598
00599 void
00600 octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax) const
00601 {
00602 print_raw (os, pr_as_read_syntax);
00603 newline (os);
00604 }
00605
00606 void
00607 octave_fcn_inline::print_raw (std::ostream& os, bool pr_as_read_syntax) const
00608 {
00609 std::ostringstream buf;
00610
00611 if (nm.empty ())
00612 buf << "f(";
00613 else
00614 buf << nm << "(";
00615
00616 for (int i = 0; i < ifargs.length (); i++)
00617 {
00618 if (i)
00619 buf << ", ";
00620
00621 buf << ifargs(i);
00622 }
00623
00624 buf << ") = " << iftext;
00625
00626 octave_print_internal (os, buf.str (), pr_as_read_syntax,
00627 current_print_indent_level ());
00628 }
00629
00630 octave_value
00631 octave_fcn_inline::convert_to_str_internal (bool, bool, char type) const
00632 {
00633 return octave_value (fcn_text (), type);
00634 }
00635
00636 DEFUNX ("inline", Finline, args, ,
00637 "-*- texinfo -*-\n\
00638 @deftypefn {Built-in Function} {} inline (@var{str})\n\
00639 @deftypefnx {Built-in Function} {} inline (@var{str}, @var{arg1}, @dots{})\n\
00640 @deftypefnx {Built-in Function} {} inline (@var{str}, @var{n})\n\
00641 Create an inline function from the character string @var{str}.\n\
00642 If called with a single argument, the arguments of the generated\n\
00643 function are extracted from the function itself. The generated\n\
00644 function arguments will then be in alphabetical order. It should\n\
00645 be noted that i, and j are ignored as arguments due to the\n\
00646 ambiguity between their use as a variable or their use as an inbuilt\n\
00647 constant. All arguments followed by a parenthesis are considered\n\
00648 to be functions.\n\
00649 \n\
00650 If the second and subsequent arguments are character strings,\n\
00651 they are the names of the arguments of the function.\n\
00652 \n\
00653 If the second argument is an integer @var{n}, the arguments are\n\
00654 @code{\"x\"}, @code{\"P1\"}, @dots{}, @code{\"P@var{N}\"}.\n\
00655 @seealso{argnames, formula, vectorize}\n\
00656 @end deftypefn")
00657 {
00658 octave_value retval;
00659
00660 int nargin = args.length ();
00661
00662 if (nargin > 0)
00663 {
00664 if (args(0).is_string ())
00665 {
00666 std::string fun = args(0).string_value ();
00667 string_vector fargs;
00668
00669 if (nargin == 1)
00670 {
00671 bool is_arg = false;
00672 bool in_string = false;
00673 std::string tmp_arg;
00674 size_t i = 0;
00675 size_t fun_length = fun.length ();
00676
00677 while (i < fun_length)
00678 {
00679 bool terminate_arg = false;
00680 char c = fun[i++];
00681
00682 if (in_string)
00683 {
00684 if (c == '\'' || c == '\"')
00685 in_string = false;
00686 }
00687 else if (c == '\'' || c == '\"')
00688 {
00689 in_string = true;
00690 if (is_arg)
00691 terminate_arg = true;
00692 }
00693 else if (! isalpha (c) && c != '_')
00694 if (! is_arg)
00695 continue;
00696 else if (isdigit (c))
00697 tmp_arg.append (1, c);
00698 else
00699 {
00700
00701 while (i < fun_length && isspace (c))
00702 c = fun[i++];
00703
00704
00705 if (c != '(')
00706 terminate_arg = true;
00707 else
00708 {
00709 tmp_arg = std::string ();
00710 is_arg = false;
00711 }
00712 }
00713 else if (! is_arg)
00714 {
00715 if (c == 'e' || c == 'E')
00716 {
00717
00718 if (isdigit (fun[i])
00719 || fun[i] == '-' || fun[i] == '+')
00720 continue;
00721 }
00722 is_arg = true;
00723 tmp_arg.append (1, c);
00724 }
00725 else
00726 {
00727 tmp_arg.append (1, c);
00728 }
00729
00730 if (terminate_arg || (i == fun_length && is_arg))
00731 {
00732 bool have_arg = false;
00733
00734 for (int j = 0; j < fargs.length (); j++)
00735 if (tmp_arg == fargs (j))
00736 {
00737 have_arg = true;
00738 break;
00739 }
00740
00741 if (! have_arg && tmp_arg != "i" && tmp_arg != "j" &&
00742 tmp_arg != "NaN" && tmp_arg != "nan" &&
00743 tmp_arg != "Inf" && tmp_arg != "inf" &&
00744 tmp_arg != "NA" && tmp_arg != "pi" &&
00745 tmp_arg != "e" && tmp_arg != "eps")
00746 fargs.append (tmp_arg);
00747
00748 tmp_arg = std::string ();
00749 is_arg = false;
00750 }
00751 }
00752
00753
00754 fargs.sort ();
00755 }
00756 else if (nargin == 2 && args(1).is_numeric_type ())
00757 {
00758 if (! args(1).is_scalar_type ())
00759 {
00760 error ("inline: N must be an integer");
00761 return retval;
00762 }
00763
00764 int n = args(1).int_value ();
00765
00766 if (! error_state)
00767 {
00768 if (n >= 0)
00769 {
00770 fargs.resize (n+1);
00771
00772 fargs(0) = "x";
00773
00774 for (int i = 1; i < n+1; i++)
00775 {
00776 std::ostringstream buf;
00777 buf << "P" << i;
00778 fargs(i) = buf.str ();
00779 }
00780 }
00781 else
00782 {
00783 error ("inline: N must be a positive integer or zero");
00784 return retval;
00785 }
00786 }
00787 else
00788 {
00789 error ("inline: N must be an integer");
00790 return retval;
00791 }
00792 }
00793 else
00794 {
00795 fargs.resize (nargin - 1);
00796
00797 for (int i = 1; i < nargin; i++)
00798 {
00799 if (args(i).is_string ())
00800 {
00801 std::string s = args(i).string_value ();
00802 fargs(i-1) = s;
00803 }
00804 else
00805 {
00806 error ("inline: expecting string arguments");
00807 return retval;
00808 }
00809 }
00810 }
00811
00812 retval = octave_value (new octave_fcn_inline (fun, fargs));
00813 }
00814 else
00815 error ("inline: STR argument must be a string");
00816 }
00817 else
00818 print_usage ();
00819
00820 return retval;
00821 }
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 DEFUN (formula, args, ,
00839 "-*- texinfo -*-\n\
00840 @deftypefn {Built-in Function} {} formula (@var{fun})\n\
00841 Return a character string representing the inline function @var{fun}.\n\
00842 Note that @code{char (@var{fun})} is equivalent to\n\
00843 @code{formula (@var{fun})}.\n\
00844 @seealso{argnames, inline, vectorize}\n\
00845 @end deftypefn")
00846 {
00847 octave_value retval;
00848
00849 int nargin = args.length ();
00850
00851 if (nargin == 1)
00852 {
00853 octave_fcn_inline* fn = args(0).fcn_inline_value (true);
00854
00855 if (fn)
00856 retval = octave_value (fn->fcn_text ());
00857 else
00858 error ("formula: FUN must be an inline function");
00859 }
00860 else
00861 print_usage ();
00862
00863 return retval;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 DEFUN (argnames, args, ,
00877 "-*- texinfo -*-\n\
00878 @deftypefn {Built-in Function} {} argnames (@var{fun})\n\
00879 Return a cell array of character strings containing the names of\n\
00880 the arguments of the inline function @var{fun}.\n\
00881 @seealso{inline, formula, vectorize}\n\
00882 @end deftypefn")
00883 {
00884 octave_value retval;
00885
00886 int nargin = args.length ();
00887
00888 if (nargin == 1)
00889 {
00890 octave_fcn_inline *fn = args(0).fcn_inline_value (true);
00891
00892 if (fn)
00893 {
00894 string_vector t1 = fn->fcn_arg_names ();
00895
00896 Cell t2 (dim_vector (t1.length (), 1));
00897
00898 for (int i = 0; i < t1.length (); i++)
00899 t2(i) = t1(i);
00900
00901 retval = t2;
00902 }
00903 else
00904 error ("argnames: FUN must be an inline function");
00905 }
00906 else
00907 print_usage ();
00908
00909 return retval;
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 DEFUN (vectorize, args, ,
00924 "-*- texinfo -*-\n\
00925 @deftypefn {Built-in Function} {} vectorize (@var{fun})\n\
00926 Create a vectorized version of the inline function @var{fun}\n\
00927 by replacing all occurrences of @code{*}, @code{/}, etc., with\n\
00928 @code{.*}, @code{./}, etc.\n\
00929 \n\
00930 This may be useful, for example, when using inline functions with\n\
00931 numerical integration or optimization where a vector-valued function\n\
00932 is expected.\n\
00933 \n\
00934 @example\n\
00935 @group\n\
00936 fcn = vectorize (inline (\"x^2 - 1\"))\n\
00937 @result{} fcn = f(x) = x.^2 - 1\n\
00938 quadv (fcn, 0, 3)\n\
00939 @result{} 6\n\
00940 @end group\n\
00941 @end example\n\
00942 @seealso{inline, formula, argnames}\n\
00943 @end deftypefn")
00944 {
00945 octave_value retval;
00946
00947 int nargin = args.length ();
00948
00949 if (nargin == 1)
00950 {
00951 std::string old_func;
00952 octave_fcn_inline* old = 0;
00953 bool func_is_string = true;
00954
00955 if (args(0).is_string ())
00956 old_func = args(0).string_value ();
00957 else
00958 {
00959 old = args(0).fcn_inline_value (true);
00960 func_is_string = false;
00961
00962 if (old)
00963 old_func = old->fcn_text ();
00964 else
00965 error ("vectorize: FUN must be a string or inline function");
00966 }
00967
00968 if (! error_state)
00969 {
00970 std::string new_func;
00971 size_t i = 0;
00972
00973 while (i < old_func.length ())
00974 {
00975 std::string t1 = old_func.substr (i, 1);
00976
00977 if (t1 == "*" || t1 == "/" || t1 == "\\" || t1 == "^")
00978 {
00979 if (i && old_func.substr (i-1, 1) != ".")
00980 new_func.append (".");
00981
00982
00983 if (t1 == "*" && i < (old_func.length () - 1)
00984 && old_func.substr (i+1, 1) == "*")
00985 {
00986 new_func.append ("*");
00987 i++;
00988 }
00989 }
00990 new_func.append (t1);
00991 i++;
00992 }
00993
00994 if (func_is_string)
00995 retval = octave_value (new_func);
00996 else
00997 retval = octave_value (new octave_fcn_inline
00998 (new_func, old->fcn_arg_names ()));
00999 }
01000 }
01001 else
01002 print_usage ();
01003
01004 return retval;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020