# HG changeset patch # User John W. Eaton # Date 1552026274 0 # Node ID 041caa61ed340039c5e6587a53b1b670b444c27f # Parent c589db954a4e58b86f84ff878235dcf44a787c16 use get_function_handle instead of extract_function * cellfun.cc (Fcellfun, Farrayfun): Use get_function_handle instead of extract_function. * daspk.cc (daspk_fcn, daspk_jac): Now octave_value objects instead of a pointers to octave_function objects. Change all uses. (Fdaspk): Use get_function_handle instead of extract_function. * dasrt.cc (dasrt_fcn, dasrt_jac, dasrt_cf): Now octave_value objects instead of a pointers to octave_function objects. Change all uses. (Fdasrt): Use get_function_handle instead of extract_function. * dassl.cc (dassl_fcn, dassl_jac): Now octave_value objects instead of a pointers to octave_function objects. Change all uses. (Fdassl): Use get_function_handle instead of extract_function. * lsode.cc (lsode_fcn, lsode_jac): Now octave_value objects instead of a pointers to octave_function objects. Change all uses. (Flsode): Use get_function_handle instead of extract_function. * quad.cc (quad_fcn): Now an octave_value object instead of a pointer to an octave_function object. Change all uses. (Fquad): Use get_function_handle instead of extract_function. New tests. * quadcc.cc (fcn): Now an octave_value object instead of a pointer to an octave_function object. Change all uses. (Fquadcc): Use get_function_handle instead of extract_function. * __eigs__.cc (eigs_fcn): Now an octave_value object instead of a pointer to an octave_function object. Change all uses. (F__eigs__): Use get_function_handle instead of extract_function. New tests. * interpreter-private.cc (get_function_handle): Don't scold users for poor choices. * variables.h (extract_function): Tag as deprecated. diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/cellfun.cc --- a/libinterp/corefcn/cellfun.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/cellfun.cc Fri Mar 08 06:24:34 2019 +0000 @@ -39,6 +39,7 @@ #include "Cell.h" #include "oct-map.h" #include "defun.h" +#include "interpreter-private.h" #include "interpreter.h" #include "parse.h" #include "variables.h" @@ -426,17 +427,7 @@ std::string name = args(0).string_value (); if (! octave::valid_identifier (name)) - { - std::string fcn_name = unique_symbol_name ("__cellfun_fcn__"); - std::string fname = "function y = " + fcn_name + "(x) y = "; - - octave_function *ptr_func - = extract_function (args(0), "cellfun", fcn_name, - fname, "; endfunction"); - - if (ptr_func) - func = octave_value (ptr_func, true); - } + func = octave::get_function_handle (interp, args(0), "x"); else { func = symtab.find_function (name); @@ -1147,17 +1138,7 @@ std::string name = args(0).string_value (); if (! octave::valid_identifier (name)) - { - std::string fcn_name = unique_symbol_name ("__arrayfun_fcn__"); - std::string fname = "function y = " + fcn_name + "(x) y = "; - - octave_function *ptr_func - = extract_function (args(0), "arrayfun", fcn_name, - fname, "; endfunction"); - - if (ptr_func) - func = octave_value (ptr_func, true); - } + func = octave::get_function_handle (interp, args(0), "x"); else { func = symtab.find_function (name); diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/daspk.cc --- a/libinterp/corefcn/daspk.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/daspk.cc Fri Mar 08 06:24:34 2019 +0000 @@ -24,6 +24,7 @@ # include "config.h" #endif +#include #include #include "DASPK.h" @@ -31,6 +32,7 @@ #include "defun.h" #include "error.h" #include "errwarn.h" +#include "interpreter-private.h" #include "ovl.h" #include "ov-fcn.h" #include "ov-cell.h" @@ -43,10 +45,10 @@ #include "DASPK-opts.cc" // Global pointer for user defined function required by daspk. -static octave_function *daspk_fcn; +static octave_value daspk_fcn; // Global pointer for optional user defined jacobian function. -static octave_function *daspk_jac; +static octave_value daspk_jac; // Have we warned about imaginary values returned from user function? static bool warned_fcn_imaginary = false; @@ -69,7 +71,7 @@ args(1) = xdot; args(0) = x; - if (daspk_fcn) + if (daspk_fcn.is_defined ()) { octave_value_list tmp; @@ -119,7 +121,7 @@ args(1) = xdot; args(0) = x; - if (daspk_jac) + if (daspk_jac.is_defined ()) { octave_value_list tmp; @@ -269,17 +271,19 @@ frame.protect_var (call_depth); call_depth++; - octave::symbol_table& symtab = interp.get_symbol_table (); - if (call_depth > 1) error ("daspk: invalid recursive call"); std::string fcn_name, fname, jac_name, jname; - daspk_fcn = nullptr; - daspk_jac = nullptr; + + daspk_fcn = octave_value (); + daspk_jac = octave_value (); octave_value f_arg = args(0); + std::list fcn_param_names ({"x", "xdot", "t"}); + std::list jac_param_names ({"x", "xdot", "t", "cj"}); + if (f_arg.iscell ()) { Cell c = f_arg.cell_value (); @@ -287,99 +291,61 @@ f_arg = c(0); else if (c.numel () == 2) { - if (c(0).is_function_handle () || c(0).is_inline_function ()) - daspk_fcn = c(0).function_value (); - else - { - fcn_name = unique_symbol_name ("__daspk_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - daspk_fcn = extract_function (c(0), "daspk", fcn_name, - fname, "; endfunction"); - } + daspk_fcn = octave::get_function_handle (interp, c(0), + fcn_param_names); - if (daspk_fcn) + if (daspk_fcn.is_defined ()) { - if (c(1).is_function_handle () || c(1).is_inline_function ()) - daspk_jac = c(1).function_value (); - else - { - jac_name = unique_symbol_name ("__daspk_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, xdot, t, cj) jac = "); - daspk_jac = extract_function (c(1), "daspk", jac_name, - jname, "; endfunction"); + daspk_jac = octave::get_function_handle (interp, c(1), + jac_param_names); - if (! daspk_jac) - { - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - daspk_fcn = nullptr; - } - } + if (daspk_jac.is_undefined ()) + daspk_fcn = octave_value (); } } else error ("daspk: incorrect number of elements in cell array"); } - if (! daspk_fcn && ! f_arg.iscell ()) + if (daspk_fcn.is_undefined () && ! f_arg.iscell ()) { if (f_arg.is_function_handle () || f_arg.is_inline_function ()) - daspk_fcn = f_arg.function_value (); + daspk_fcn = f_arg; else { switch (f_arg.rows ()) { case 1: - do - { - fcn_name = unique_symbol_name ("__daspk_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - daspk_fcn = extract_function (f_arg, "daspk", fcn_name, - fname, "; endfunction"); - } - while (0); + daspk_fcn = octave::get_function_handle (interp, f_arg, + fcn_param_names); break; case 2: { string_vector tmp = f_arg.string_vector_value (); - fcn_name = unique_symbol_name ("__daspk_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - daspk_fcn = extract_function (tmp(0), "daspk", fcn_name, - fname, "; endfunction"); + daspk_fcn = octave::get_function_handle (interp, tmp(0), + fcn_param_names); - if (daspk_fcn) + if (daspk_fcn.is_defined ()) { - jac_name = unique_symbol_name ("__daspk_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, xdot, t, cj) jac = "); - daspk_jac = extract_function (tmp(1), "daspk", jac_name, - jname, "; endfunction"); + daspk_jac = octave::get_function_handle (interp, tmp(1), + jac_param_names); - if (! daspk_jac) - { - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - daspk_fcn = nullptr; - } + if (daspk_jac.is_undefined ()) + daspk_fcn = octave_value (); } } + break; + + default: + error ("daspk: first arg should be a string or 2-element string array"); } } } - if (! daspk_fcn) - return retval; + if (daspk_fcn.is_undefined ()) + error ("daspk: FCN argument is not a valid function name or handle"); ColumnVector state = args(1).xvector_value ("daspk: initial state X_0 must be a vector"); @@ -402,7 +368,7 @@ double tzero = out_times (0); DAEFunc func (daspk_user_function); - if (daspk_jac) + if (daspk_jac.is_defined ()) func.set_jacobian_function (daspk_user_jacobian); DASPK dae (state, deriv, tzero, func); @@ -416,11 +382,6 @@ else output = dae.integrate (out_times, deriv_output); - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - if (jac_name.length ()) - symtab.clear_function (jac_name); - std::string msg = dae.error_message (); if (dae.integration_ok ()) diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/dasrt.cc --- a/libinterp/corefcn/dasrt.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/dasrt.cc Fri Mar 08 06:24:34 2019 +0000 @@ -24,6 +24,7 @@ # include "config.h" #endif +#include #include #include "DASRT.h" @@ -32,6 +33,7 @@ #include "defun.h" #include "error.h" #include "errwarn.h" +#include "interpreter-private.h" #include "ovl.h" #include "ov-fcn.h" #include "ov-cell.h" @@ -44,9 +46,9 @@ #include "DASRT-opts.cc" // Global pointers for user defined function required by dasrt. -static octave_function *dasrt_f; -static octave_function *dasrt_j; -static octave_function *dasrt_cf; +static octave_value dasrt_fcn; +static octave_value dasrt_jac; +static octave_value dasrt_cf; // Have we warned about imaginary values returned from user function? static bool warned_fcn_imaginary = false; @@ -70,13 +72,13 @@ args(1) = xdot; args(0) = x; - if (dasrt_f) + if (dasrt_fcn.is_defined ()) { octave_value_list tmp; try { - tmp = octave::feval (dasrt_f, args, 1); + tmp = octave::feval (dasrt_fcn, args, 1); } catch (octave::execution_exception& e) { @@ -111,7 +113,7 @@ args(1) = t; args(0) = x; - if (dasrt_cf) + if (dasrt_cf.is_defined ()) { octave_value_list tmp; @@ -157,13 +159,13 @@ args(1) = xdot; args(0) = x; - if (dasrt_j) + if (dasrt_jac.is_defined ()) { octave_value_list tmp; try { - tmp = octave::feval (dasrt_j, args, 1); + tmp = octave::feval (dasrt_jac, args, 1); } catch (octave::execution_exception& e) { @@ -353,11 +355,10 @@ int argp = 0; std::string fcn_name, fname, jac_name, jname; - dasrt_f = nullptr; - dasrt_j = nullptr; - dasrt_cf = nullptr; - octave::symbol_table& symtab = interp.get_symbol_table (); + dasrt_fcn = octave_value (); + dasrt_jac = octave_value (); + dasrt_cf = octave_value (); // Check all the arguments. Are they the right animals? @@ -365,6 +366,9 @@ octave_value f_arg = args(0); + std::list fcn_param_names ({"x", "xdot", "t"}); + std::list jac_param_names ({"x", "xdot", "t", "cj"}); + if (f_arg.iscell ()) { Cell c = f_arg.cell_value (); @@ -372,83 +376,49 @@ f_arg = c(0); else if (c.numel () == 2) { - if (c(0).is_function_handle () || c(0).is_inline_function ()) - dasrt_f = c(0).function_value (); - else - { - fcn_name = unique_symbol_name ("__dasrt_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - dasrt_f = extract_function (c(0), "dasrt", fcn_name, fname, - "; endfunction"); - } + dasrt_fcn = octave::get_function_handle (interp, c(0), + fcn_param_names); - if (dasrt_f) + if (dasrt_fcn.is_defined ()) { - if (c(1).is_function_handle () || c(1).is_inline_function ()) - dasrt_j = c(1).function_value (); - else - { - jac_name = unique_symbol_name ("__dasrt_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, xdot, t, cj) jac = "); - dasrt_j = extract_function (c(1), "dasrt", jac_name, jname, - "; endfunction"); + dasrt_jac = octave::get_function_handle (interp, c(1), + jac_param_names); - if (! dasrt_j) - { - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - dasrt_f = nullptr; - } - } + if (dasrt_jac.is_undefined ()) + dasrt_fcn = octave_value (); } } else error ("dasrt: incorrect number of elements in cell array"); } - if (! dasrt_f && ! f_arg.iscell ()) + if (dasrt_fcn.is_undefined () && ! f_arg.iscell ()) { if (f_arg.is_function_handle () || f_arg.is_inline_function ()) - dasrt_f = f_arg.function_value (); + dasrt_fcn = f_arg; else { switch (f_arg.rows ()) { case 1: - fcn_name = unique_symbol_name ("__dasrt_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - dasrt_f = extract_function (f_arg, "dasrt", fcn_name, fname, - "; endfunction"); + dasrt_fcn = octave::get_function_handle (interp, f_arg, + fcn_param_names); break; case 2: { - string_vector tmp = args(0).string_vector_value (); + string_vector tmp = f_arg.string_vector_value (); - fcn_name = unique_symbol_name ("__dasrt_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - dasrt_f = extract_function (tmp(0), "dasrt", fcn_name, - fname, "; endfunction"); + dasrt_fcn = octave::get_function_handle (interp, tmp(0), + fcn_param_names); - if (dasrt_f) + if (dasrt_fcn.is_defined ()) { - jac_name = unique_symbol_name ("__dasrt_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, xdot, t, cj) jac = "); - dasrt_j = extract_function (tmp(1), "dasrt", jac_name, - jname, "; endfunction"); + dasrt_jac = octave::get_function_handle (interp, tmp(1), + jac_param_names); - if (! dasrt_j) - dasrt_f = nullptr; + if (dasrt_jac.is_undefined ()) + dasrt_fcn = octave_value (); } } break; @@ -459,8 +429,8 @@ } } - if (! dasrt_f) - return retval; + if (dasrt_fcn.is_undefined ()) + error ("dasrt: FCN argument is not a valid function name or handle"); DAERTFunc func (dasrt_user_f); @@ -475,19 +445,15 @@ } else { - if (args(1).is_function_handle () || args(1).is_inline_function ()) - dasrt_cf = args(1).function_value (); - else if (args(1).is_string ()) + if (args(1).is_function_handle () || args(1).is_inline_function () + || args(1).is_string ()) { - fcn_name = unique_symbol_name ("__dasrt_constraint_fcn__"); - fname = "function g_out = "; - fname.append (fcn_name); - fname.append (" (x, t) g_out = "); - dasrt_cf = extract_function (args(1), "dasrt", fcn_name, fname, - "; endfunction"); + std::list cf_param_names ({"x", "t"}); + + dasrt_cf = octave::get_function_handle (interp, args(1), cf_param_names); } - if (dasrt_cf) + if (dasrt_cf.is_defined ()) { argp++; @@ -518,7 +484,7 @@ crit_times_set = true; } - if (dasrt_j) + if (dasrt_jac.is_defined ()) func.set_jacobian_function (dasrt_user_j); DASRT_result output; @@ -532,11 +498,6 @@ else output = dae.integrate (out_times); - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - if (jac_name.length ()) - symtab.clear_function (jac_name); - std::string msg = dae.error_message (); if (dae.integration_ok ()) diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/dassl.cc --- a/libinterp/corefcn/dassl.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/dassl.cc Fri Mar 08 06:24:34 2019 +0000 @@ -31,6 +31,7 @@ #include "defun.h" #include "error.h" #include "errwarn.h" +#include "interpreter-private.h" #include "ovl.h" #include "ov-fcn.h" #include "ov-cell.h" @@ -43,10 +44,10 @@ #include "DASSL-opts.cc" // Global pointer for user defined function required by dassl. -static octave_function *dassl_fcn; +static octave_value dassl_fcn; // Global pointer for optional user defined jacobian function. -static octave_function *dassl_jac; +static octave_value dassl_jac; // Have we warned about imaginary values returned from user function? static bool warned_fcn_imaginary = false; @@ -69,7 +70,7 @@ args(1) = xdot; args(0) = x; - if (dassl_fcn) + if (dassl_fcn.is_defined ()) { octave_value_list tmp; @@ -119,7 +120,7 @@ args(1) = xdot; args(0) = x; - if (dassl_jac) + if (dassl_jac.is_defined ()) { octave_value_list tmp; @@ -273,14 +274,16 @@ if (call_depth > 1) error ("dassl: invalid recursive call"); - octave::symbol_table& symtab = interp.get_symbol_table (); + std::string fcn_name, fname, jac_name, jname; - std::string fcn_name, fname, jac_name, jname; - dassl_fcn = nullptr; - dassl_jac = nullptr; + dassl_fcn = octave_value (); + dassl_jac = octave_value (); octave_value f_arg = args(0); + std::list fcn_param_names ({"x", "xdot", "t"}); + std::list jac_param_names ({"x", "xdot", "t", "cj"}); + if (f_arg.iscell ()) { Cell c = f_arg.cell_value (); @@ -288,100 +291,61 @@ f_arg = c(0); else if (c.numel () == 2) { - if (c(0).is_function_handle () || c(0).is_inline_function ()) - dassl_fcn = c(0).function_value (); - else - { - fcn_name = unique_symbol_name ("__dassl_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - dassl_fcn = extract_function (c(0), "dassl", fcn_name, fname, - "; endfunction"); - } + dassl_fcn = octave::get_function_handle (interp, c(0), + fcn_param_names); - if (dassl_fcn) + if (dassl_fcn.is_defined ()) { - if (c(1).is_function_handle () || c(1).is_inline_function ()) - dassl_jac = c(1).function_value (); - else - { - jac_name = unique_symbol_name ("__dassl_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, xdot, t, cj) jac = "); - dassl_jac = extract_function (c(1), "dassl", jac_name, - jname, "; endfunction"); + dassl_jac = octave::get_function_handle (interp, c(1), + jac_param_names); - if (! dassl_jac) - { - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - dassl_fcn = nullptr; - } - } + if (dassl_jac.is_undefined ()) + dassl_fcn = octave_value (); } } else error ("dassl: incorrect number of elements in cell array"); } - if (! dassl_fcn && ! f_arg.iscell ()) + if (dassl_fcn.is_undefined () && ! f_arg.iscell ()) { if (f_arg.is_function_handle () || f_arg.is_inline_function ()) - dassl_fcn = f_arg.function_value (); + dassl_fcn = f_arg; else { switch (f_arg.rows ()) { case 1: - do - { - fcn_name = unique_symbol_name ("__dassl_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - dassl_fcn = extract_function (f_arg, "dassl", fcn_name, - fname, "; endfunction"); - } - while (0); + dassl_fcn = octave::get_function_handle (interp, f_arg, + fcn_param_names); break; case 2: { string_vector tmp = f_arg.string_vector_value (); - fcn_name = unique_symbol_name ("__dassl_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, xdot, t) y = "); - dassl_fcn = extract_function (tmp(0), "dassl", fcn_name, - fname, "; endfunction"); + dassl_fcn = octave::get_function_handle (interp, tmp(0), + fcn_param_names); - if (dassl_fcn) + if (dassl_fcn.is_defined ()) { - jac_name = unique_symbol_name ("__dassl_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, xdot, t, cj) jac = "); - dassl_jac = extract_function (tmp(1), "dassl", - jac_name, jname, - "; endfunction"); + dassl_jac = octave::get_function_handle (interp, tmp(1), + jac_param_names); - if (! dassl_jac) - { - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - dassl_fcn = nullptr; - } + if (dassl_jac.is_undefined ()) + dassl_fcn = octave_value (); } } + break; + + default: + error ("dassl: first arg should be a string or 2-element string array"); } } } - if (! dassl_fcn) - return retval; + if (dassl_fcn.is_undefined ()) + error ("dassl: FCN argument is not a valid function name or handle"); ColumnVector state = args(1).xvector_value ("dassl: initial state X_0 must be a vector"); @@ -404,7 +368,7 @@ double tzero = out_times (0); DAEFunc func (dassl_user_function); - if (dassl_jac) + if (dassl_jac.is_defined ()) func.set_jacobian_function (dassl_user_jacobian); DASSL dae (state, deriv, tzero, func); @@ -419,11 +383,6 @@ else output = dae.integrate (out_times, deriv_output); - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - if (jac_name.length ()) - symtab.clear_function (jac_name); - std::string msg = dae.error_message (); if (dae.integration_ok ()) diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/interpreter-private.cc --- a/libinterp/corefcn/interpreter-private.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/interpreter-private.cc Fri Mar 08 06:24:34 2019 +0000 @@ -213,9 +213,8 @@ fcn = octave_value (new octave_fcn_inline (fstr, parameter_names)); - if (fcn.is_defined ()) - warning_with_id ("Octave:function-from-text", - "get_function_handle: passing function body as text is discouraged; use an anonymous function instead"); + // Possibly warn here that passing the function body in a + // character string is discouraged. return fcn; } diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/interpreter-private.h --- a/libinterp/corefcn/interpreter-private.h Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/interpreter-private.h Fri Mar 08 06:24:34 2019 +0000 @@ -91,7 +91,7 @@ // Convert octave_value object ARG to be a function handle object. It // may be a function handle, inline function, the name of a function, // or the text of an inline function that has the given argument names - // PARAMETER_NAMES. The latter form is deprecated. + // PARAMETER_NAMES. Use of the latter form is discouraged. octave_value get_function_handle (octave::interpreter& interp, const octave_value& arg, diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/lsode.cc --- a/libinterp/corefcn/lsode.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/lsode.cc Fri Mar 08 06:24:34 2019 +0000 @@ -24,6 +24,7 @@ # include "config.h" #endif +#include #include #include "LSODE.h" @@ -32,6 +33,7 @@ #include "defun.h" #include "error.h" #include "errwarn.h" +#include "interpreter-private.h" #include "ovl.h" #include "ov-fcn.h" #include "ov-cell.h" @@ -45,10 +47,10 @@ #include "LSODE-opts.cc" // Global pointer for user defined function required by lsode. -static octave_function *lsode_fcn; +static octave_value lsode_fcn; // Global pointer for optional user defined jacobian function used by lsode. -static octave_function *lsode_jac; +static octave_value lsode_jac; // Have we warned about imaginary values returned from user function? static bool warned_fcn_imaginary = false; @@ -66,7 +68,7 @@ args(1) = t; args(0) = x; - if (lsode_fcn) + if (lsode_fcn.is_defined ()) { octave_value_list tmp; @@ -106,7 +108,7 @@ args(1) = t; args(0) = x; - if (lsode_jac) + if (lsode_jac.is_defined ()) { octave_value_list tmp; @@ -275,11 +277,14 @@ octave::symbol_table& symtab = interp.get_symbol_table (); std::string fcn_name, fname, jac_name, jname; - lsode_fcn = nullptr; - lsode_jac = nullptr; + + lsode_fcn = octave_value (); + lsode_jac = octave_value (); octave_value f_arg = args(0); + std::list parameter_names ({"x", "t"}); + if (f_arg.iscell ()) { Cell c = f_arg.cell_value (); @@ -287,92 +292,49 @@ f_arg = c(0); else if (c.numel () == 2) { - if (c(0).is_function_handle () || c(0).is_inline_function ()) - lsode_fcn = c(0).function_value (); - else - { - fcn_name = unique_symbol_name ("__lsode_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, t) y = "); - lsode_fcn = extract_function (c(0), "lsode", fcn_name, fname, - "; endfunction"); - } + lsode_fcn = octave::get_function_handle (interp, c(0), + parameter_names); - if (lsode_fcn) + if (lsode_fcn.is_defined ()) { - if (c(1).is_function_handle () || c(1).is_inline_function ()) - lsode_jac = c(1).function_value (); - else - { - jac_name = unique_symbol_name ("__lsode_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, t) jac = "); - lsode_jac = extract_function (c(1), "lsode", jac_name, - jname, "; endfunction"); + lsode_jac = octave::get_function_handle (interp, c(1), + parameter_names); - if (! lsode_jac) - { - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - lsode_fcn = nullptr; - } - } + if (lsode_jac.is_undefined ()) + lsode_fcn = octave_value (); } } else error ("lsode: incorrect number of elements in cell array"); } - if (! lsode_fcn && ! f_arg.iscell ()) + if (lsode_fcn.is_undefined () && ! f_arg.iscell ()) { if (f_arg.is_function_handle () || f_arg.is_inline_function ()) - lsode_fcn = f_arg.function_value (); + lsode_fcn = f_arg; else { switch (f_arg.rows ()) { case 1: - do - { - fcn_name = unique_symbol_name ("__lsode_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, t) y = "); - lsode_fcn = extract_function (f_arg, "lsode", fcn_name, - fname, "; endfunction"); - } - while (0); + lsode_fcn = octave::get_function_handle (interp, f_arg, + parameter_names); break; case 2: { string_vector tmp = f_arg.string_vector_value (); - fcn_name = unique_symbol_name ("__lsode_fcn__"); - fname = "function y = "; - fname.append (fcn_name); - fname.append (" (x, t) y = "); - lsode_fcn = extract_function (tmp(0), "lsode", fcn_name, - fname, "; endfunction"); + lsode_fcn = octave::get_function_handle (interp, tmp(0), + parameter_names); - if (lsode_fcn) + if (lsode_fcn.is_defined ()) { - jac_name = unique_symbol_name ("__lsode_jac__"); - jname = "function jac = "; - jname.append (jac_name); - jname.append (" (x, t) jac = "); - lsode_jac = extract_function (tmp(1), "lsode", - jac_name, jname, - "; endfunction"); + lsode_jac = octave::get_function_handle (interp, tmp(1), + parameter_names); - if (! lsode_jac) - { - if (fcn_name.length ()) - symtab.clear_function (fcn_name); - lsode_fcn = nullptr; - } + if (lsode_jac.is_undefined ()) + lsode_fcn = octave_value (); } } break; @@ -383,7 +345,7 @@ } } - if (! lsode_fcn) + if (lsode_fcn.is_undefined ()) error ("lsode: FCN argument is not a valid function name or handle"); ColumnVector state = args(1).xvector_value ("lsode: initial state X_0 must be a vector"); @@ -402,7 +364,8 @@ double tzero = out_times (0); ODEFunc func (lsode_user_function); - if (lsode_jac) + + if (lsode_jac.is_defined ()) func.set_jacobian_function (lsode_user_jacobian); LSODE ode (state, tzero, func); diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/quad.cc --- a/libinterp/corefcn/quad.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/quad.cc Fri Mar 08 06:24:34 2019 +0000 @@ -32,10 +32,11 @@ #include "defun.h" #include "error.h" #include "errwarn.h" +#include "interpreter-private.h" #include "pager.h" #include "parse.h" +#include "ov.h" #include "ovl.h" -#include "ov-fcn.h" #include "unwind-prot.h" #include "utils.h" #include "variables.h" @@ -43,7 +44,7 @@ #include "Quad-opts.cc" // Global pointer for user defined function required by quadrature functions. -static octave_function *quad_fcn; +static octave_value quad_fcn; // Have we warned about imaginary values returned from user function? static bool warned_imaginary = false; @@ -59,7 +60,7 @@ octave_value_list args; args(0) = x; - if (quad_fcn) + if (quad_fcn.is_defined ()) { octave_value_list tmp; @@ -95,7 +96,7 @@ octave_value_list args; args(0) = x; - if (quad_fcn) + if (quad_fcn.is_defined ()) { octave_value_list tmp; @@ -184,24 +185,7 @@ if (call_depth > 1) error ("quad: invalid recursive call"); - std::string fcn_name; - - if (args(0).is_function_handle () || args(0).is_inline_function ()) - quad_fcn = args(0).function_value (); - else - { - fcn_name = unique_symbol_name ("__quad_fcn__"); - std::string fname = "function y = "; - fname.append (fcn_name); - fname.append ("(x) y = "); - quad_fcn = extract_function (args(0), "quad", fcn_name, fname, - "; endfunction"); - octave::symbol_table& symtab = interp.get_symbol_table (); - frame.add_method (symtab, &octave::symbol_table::clear_function, fcn_name); - } - - if (! quad_fcn) - error ("quad: FCN argument is not a valid function name or handle"); + quad_fcn = octave::get_function_handle (interp, args(0), "x"); octave_value_list retval; @@ -430,6 +414,33 @@ %! assert (nfun > 0); %!test +%! [v, ier, nfun, err] = quad (@__f, 0.001, 3); +%! assert (ier == 0 || ier == 1); +%! assert (v, 1.98194120273598, sqrt (eps)); +%! assert (nfun > 0); + +%!test +%! fstr = "x .* sin (1 ./ x) .* sqrt (abs (1 - x))"; +%! [v, ier, nfun, err] = quad (fstr, 0.001, 3); +%! assert (ier == 0 || ier == 1); +%! assert (v, 1.98194120273598, sqrt (eps)); +%! assert (nfun > 0); + +%!test +%! anon_fcn = @(x) x .* sin (1 ./ x) .* sqrt (abs (1 - x)); +%! [v, ier, nfun, err] = quad (anon_fcn, 0.001, 3); +%! assert (ier == 0 || ier == 1); +%! assert (v, 1.98194120273598, sqrt (eps)); +%! assert (nfun > 0); + +%!test +%! inline_fcn = inline ("x .* sin (1 ./ x) .* sqrt (abs (1 - x))", "x"); +%! [v, ier, nfun, err] = quad (inline_fcn, 0.001, 3); +%! assert (ier == 0 || ier == 1); +%! assert (v, 1.98194120273598, sqrt (eps)); +%! assert (nfun > 0); + +%!test %! [v, ier, nfun, err] = quad ("__f", single (0.001), single (3)); %! assert (ier == 0 || ier == 1); %! assert (v, 1.98194120273598, sqrt (eps ("single"))); diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/quadcc.cc --- a/libinterp/corefcn/quadcc.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/quadcc.cc Fri Mar 08 06:24:34 2019 +0000 @@ -33,6 +33,7 @@ #include "defun.h" #include "error.h" +#include "interpreter-private.h" #include "ovl.h" #include "parse.h" #include "utils.h" @@ -1483,8 +1484,8 @@ // The actual integration routine. -DEFUN (quadcc, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (quadcc, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}) @deftypefnx {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}, @var{tol}) @deftypefnx {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}, @var{tol}, @var{sing}) @@ -1575,7 +1576,7 @@ // Arguments left and right. int nargin = args.length (); - octave_function *fcn; + octave_value fcn; double a, b, abstol, reltol, *sing; bool issingle; @@ -1600,17 +1601,7 @@ if (nargin < 3) print_usage (); - if (args(0).is_function_handle () || args(0).is_inline_function ()) - fcn = args(0).function_value (); - else - { - std::string fcn_name = unique_symbol_name ("__quadcc_fcn__"); - std::string fname = "function y = "; - fname.append (fcn_name); - fname.append ("(x) y = "); - fcn = extract_function (args(0), "quadcc", fcn_name, fname, - "; endfunction"); - } + fcn = octave::get_function_handle (interp, args(0), "x"); if (! args(1).is_real_scalar ()) error ("quadcc: lower limit of integration (A) must be a real scalar"); diff -r c589db954a4e -r 041caa61ed34 libinterp/corefcn/variables.h --- a/libinterp/corefcn/variables.h Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/corefcn/variables.h Fri Mar 08 06:24:34 2019 +0000 @@ -53,6 +53,7 @@ is_valid_function (const std::string&, const std::string& = "", bool warn = false); +OCTAVE_DEPRECATED (6, "use 'octave::get_function_handle' instead") extern OCTINTERP_API octave_function * extract_function (const octave_value& arg, const std::string& warn_for, const std::string& fname, const std::string& header, diff -r c589db954a4e -r 041caa61ed34 libinterp/dldfcn/__eigs__.cc --- a/libinterp/dldfcn/__eigs__.cc Fri Mar 08 02:49:52 2019 +0000 +++ b/libinterp/dldfcn/__eigs__.cc Fri Mar 08 06:24:34 2019 +0000 @@ -34,6 +34,7 @@ #include "defun-dld.h" #include "error.h" #include "errwarn.h" +#include "interpreter-private.h" #include "oct-map.h" #include "ov.h" #include "ovl.h" @@ -44,7 +45,7 @@ #if defined (HAVE_ARPACK) // Global pointer for user defined function. -static octave_function *eigs_fcn = nullptr; +static octave_value eigs_fcn; // Have we warned about imaginary values returned from user function? static bool warned_imaginary = false; @@ -59,7 +60,7 @@ octave_value_list args; args(0) = x; - if (eigs_fcn) + if (eigs_fcn.is_defined ()) { octave_value_list tmp; @@ -99,7 +100,7 @@ octave_value_list args; args(0) = x; - if (eigs_fcn) + if (eigs_fcn.is_defined ()) { octave_value_list tmp; @@ -206,20 +207,9 @@ if (args(0).is_function_handle () || args(0).is_inline_function () || args(0).is_string ()) { - if (args(0).is_string ()) - { - std::string name = args(0).string_value (); - std::string fname = "function y = "; - fcn_name = unique_symbol_name ("__eigs_fcn__"); - fname.append (fcn_name); - fname.append ("(x) y = "); - eigs_fcn = extract_function (args(0), "eigs", fcn_name, fname, - "; endfunction"); - } - else - eigs_fcn = args(0).function_value (); + eigs_fcn = octave::get_function_handle (interp, args(0), "x"); - if (! eigs_fcn) + if (eigs_fcn.is_undefined ()) error ("eigs: unknown function"); if (nargin < 2)