# HG changeset patch # User Rik # Date 1401038945 25200 # Node ID 888f8ce79bbee984265d9503d68132038953c932 # Parent 70ea5a2856fe0ca6780f4b70f976790cf6a719ff# Parent bd1fd4ed3d67fb3bfd60184071a96ac5eb5f848d maint: Periodic merge gui-release -> default. diff -r bd1fd4ed3d67 -r 888f8ce79bbe Makefile.am --- a/Makefile.am Sun May 25 10:26:18 2014 -0700 +++ b/Makefile.am Sun May 25 10:29:05 2014 -0700 @@ -129,6 +129,11 @@ check: all $(MAKE) -C test check +if AMCOND_HAVE_LLVM +check-jit: all + $(MAKE) -C test check-jit +endif + run-octave: run-octave.in Makefile @$(do_subst_script_vals) chmod a+rx "$@" diff -r bd1fd4ed3d67 -r 888f8ce79bbe NEWS --- a/NEWS Sun May 25 10:26:18 2014 -0700 +++ b/NEWS Sun May 25 10:29:05 2014 -0700 @@ -1,3 +1,80 @@ +Summary of important user-visible changes for version 4.2: +--------------------------------------------------------- + + ** Interpolation function changes for Matlab compatibility + + The interpolation method 'cubic' is now equivalent to 'pchip' + for interp1, interp2, and interp3. Previously, 'cubic' was equivalent + to 'spline' for interp2. This may produce different results as 'spline' + has continuous 1st and 2nd derivatives while 'pchip' only has a continuous + 1st derivative. + + ** Integer formats used in the printf family of functions now work for + 64-bit integers and are more compatible with Matlab when printing + non-integer values. Now instead of truncating, Octave will switch + the effective format to '%g' in the following circumstances: + + * the value of an integer type (int8, uint32, etc.) value exceeds + the maximum for the format specifier. For '%d', the limit is + intmax ('int64') and for '%u' it is intmax ('uint64'). + + * round(x) != x or the value is outside the range allowed by the + integer format specifier. + + There is still one difference: Matlab switches to '%e' and Octave + is currently switching to '%g'. + + ** linkprop has been completely re-coded for performance and Matlab + compatibility. It now returns a linkprop object which must be stored + in a variable for as long as the graphic objects should remain linked. + To unlink properties use 'clear hlink' where hlink is the variable + containing the linkprop object. + + ** Other new functions added in 4.2: + + dir_in_loadpath numfields + hgload + hgsave + javachk + linkaxes + + ** Deprecated functions. + + The following functions have been deprecated in Octave 4.2 and will + be removed from Octave 4.6 (or whatever version is the second major + release after 4.2): + + bicubic + find_dir_in_path + nfields + + The following functions were deprecated in Octave 3.8 and have been + removed from Octave 4.2. + + default_save_options java_new + gen_doc_cache java_set + interp1q java_unsigned_conversion + isequalwithequalnans javafields + java_convert_matrix javamethods + java_debug re_read_readline_init_file + java_get read_readline_init_file + java_invoke saving_history + + The following keywords were deprecated in Octave 3.8 and have been + removed from Octave 4.2 + + static + + The following configuration variables were deprecated in Octave 3.8 + and have been removed from Octave 4.2 + + CC_VERSION (now GCC_VERSION) + CXX_VERSION (now GXX_VERSION) + + The internal class was deprecated in Octave 3.8 and has + been removed from Octave 4.2. Replacement classes are + (struct array) or for a single structure. + Summary of important user-visible changes for version 4.0: --------------------------------------------------------- @@ -27,7 +104,7 @@ ** Other new functions added in 4.0.0: - validateattributes + validateattributes ** Deprecated functions. diff -r bd1fd4ed3d67 -r 888f8ce79bbe build-aux/common.mk --- a/build-aux/common.mk Sun May 25 10:26:18 2014 -0700 +++ b/build-aux/common.mk Sun May 25 10:29:05 2014 -0700 @@ -107,8 +107,6 @@ # C compiler flags. CC = @CC@ -## FIXME: CC_VERSION is deprecated and should be removed in version 3.12 -CC_VERSION = @CC_VERSION@ GCC_VERSION = @GCC_VERSION@ CPICFLAG = @CPICFLAG@ XTRA_CFLAGS = @XTRA_CFLAGS@ @@ -131,8 +129,6 @@ # C++ compiler flags. CXX = @CXX@ -## FIXME: CXX_VERSION is deprecated and should be removed in version 3.12 -CXX_VERSION = @CXX_VERSION@ GXX_VERSION = @GXX_VERSION@ CXXCPP = @CXXCPP@ CXXPICFLAG = @CXXPICFLAG@ @@ -518,7 +514,6 @@ -e "s|%OCTAVE_CONF_CANONICAL_HOST_TYPE%|\"${canonical_host_type}\"|" \ -e "s|%OCTAVE_CONF_CARBON_LIBS%|\"${CARBON_LIBS}\"|" \ -e "s|%OCTAVE_CONF_CC%|\"${CC}\"|" \ - -e "s|%OCTAVE_CONF_CC_VERSION%|\"${CC_VERSION}\"|" \ -e "s|%OCTAVE_CONF_CCOLAMD_CPPFLAGS%|\"${CCOLAMD_CPPFLAGS}\"|" \ -e "s|%OCTAVE_CONF_CCOLAMD_LDFLAGS%|\"${CCOLAMD_LDFLAGS}\"|" \ -e "s|%OCTAVE_CONF_CCOLAMD_LIBS%|\"${CCOLAMD_LIBS}\"|" \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe configure.ac --- a/configure.ac Sun May 25 10:26:18 2014 -0700 +++ b/configure.ac Sun May 25 10:29:05 2014 -0700 @@ -19,13 +19,13 @@ ### . AC_PREREQ([2.62]) -AC_INIT([GNU Octave], [3.9.0+], [http://octave.org/bugs.html], [octave]) +AC_INIT([GNU Octave], [4.1.0+], [http://octave.org/bugs.html], [octave]) dnl Note that the version number is duplicated here and in AC_INIT dnl because AC_INIT requires it to be static, not computed from dnl shell variables. -OCTAVE_MAJOR_VERSION=3 -OCTAVE_MINOR_VERSION=9 +OCTAVE_MAJOR_VERSION=4 +OCTAVE_MINOR_VERSION=1 OCTAVE_PATCH_VERSION=0+ dnl PACKAGE_VERSION is set by the AC_INIT VERSION arg @@ -329,10 +329,6 @@ fi AC_SUBST(GXX_VERSION) -## FIXME: CXX_VERSION is deprecated and should be removed in Octave version 3.12 -CXX_VERSION=$gxx_version -AC_SUBST(CXX_VERSION) - ### Determine which C compiler to use (we expect to find gcc). AC_PROG_CC @@ -379,10 +375,6 @@ fi AC_SUBST(GCC_VERSION) -## FIXME: CC_VERSION is deprecated and should be removed in Octave version 3.12 -CC_VERSION=$GCC_VERSION -AC_SUBST(CC_VERSION) - ### Also check g++ version number, it might be different from the ## gcc version number. @@ -895,6 +887,7 @@ AC_SUBST(LLVM_CXXFLAGS) AC_SUBST(LLVM_LDFLAGS) AC_SUBST(LLVM_LIBS) +AM_CONDITIONAL([AMCOND_HAVE_LLVM], [test -z "$warn_llvm"]) ### Check for HDF5 library. @@ -2186,7 +2179,7 @@ AC_CHECK_FUNCS([log1p log1pf pipe]) AC_CHECK_FUNCS([realpath resolvepath roundl]) AC_CHECK_FUNCS([select setgrent setpwent siglongjmp strsignal]) -AC_CHECK_FUNCS([tcgetattr tcsetattr tempnam tgammaf toascii]) +AC_CHECK_FUNCS([tcgetattr tcsetattr tgammaf toascii]) AC_CHECK_FUNCS([umask waitpid]) AC_CHECK_FUNCS([_kbhit]) @@ -2845,7 +2838,8 @@ fi AM_CONDITIONAL([AMCOND_BUILD_GUI], [test $build_gui = yes]) -AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], [test "$octave_cv_lib_qscintilla" = yes]) +AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], + [test "$octave_cv_lib_qscintilla" = yes]) AM_CONDITIONAL([WIN32_TERMINAL], [test $win32_terminal = yes]) AC_SUBST(QT_CPPFLAGS) AC_SUBST(QT_LDFLAGS) diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/container.txi --- a/doc/interpreter/container.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/container.txi Sun May 25 10:29:05 2014 -0700 @@ -507,7 +507,7 @@ Other functions that can manipulate the fields of a structure are given below. -@DOCSTRING(nfields) +@DOCSTRING(numfields) @DOCSTRING(fieldnames) diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/contributors.in --- a/doc/interpreter/contributors.in Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/contributors.in Sun May 25 10:29:05 2014 -0700 @@ -15,6 +15,7 @@ Heinz Bauschke Julien Bect Roman Belov +Markus Bergholz Karl Berry David Billinghurst Don Bindner @@ -69,6 +70,7 @@ Peter Ekberg Rolf Fabian Gunnar Farnebäck +Massimiliano Fasi Stephen Fegan Ramon Garcia Fernandez Torsten Finke @@ -80,6 +82,7 @@ Walter Gautschi Klaus Gebhardt Driss Ghaddab +Eugenio Gianniti Nicolo Giorgetti Arun Giridhar Michael D. Godfrey @@ -88,6 +91,7 @@ Tomislav Goles Keith Goodman Brian Gough +Michael C. Grant Steffen Groot Etienne Grossmann David Grundberg @@ -119,6 +123,7 @@ John Hunt Teemu Ikonen Alan W. Irwin +Allan Jacobs Geoff Jacobsen Mats Jansson Cai Jianming @@ -188,6 +193,7 @@ Júlio Hoffimann Mendes Ed Meyer Thorsten Meyer +Stefan Miereis Petr Mikulik Mike Miller Stefan Monnier @@ -210,6 +216,7 @@ Michael O'Brien Peter O'Gorman Thorsten Ohl +Kai T. Ohlhus Arno Onken Valentin Ortega-Clavero Luis F. Ortiz @@ -234,6 +241,7 @@ Francesco Potortì Konstantinos Poulios Jarno Rajahalme +Eduardo Ramos James B. Rawlings Eric S. Raymond Balint Reczey @@ -266,6 +274,7 @@ Julian Schnidder Nicol N. Schraudolph Sebastian Schubert +Lasse Schuirmann Ludwig Schwardt Thomas L. Scofield Daniel J. Sebald @@ -282,6 +291,7 @@ Joerg Specht Quentin H. Spencer Christoph Spiel +David Spies Richard Stallman Russell Standish Brett Stewart @@ -325,6 +335,7 @@ Martin Weiser Michael Weitzel David Wells +Joachim Wiesemann Fook Fah Yap Sean Young Michael Zeising diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/errors.txi --- a/doc/interpreter/errors.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/errors.txi Sun May 25 10:29:05 2014 -0700 @@ -285,7 +285,7 @@ @group function rand42 old_state = rand ("state"); - restore_state = onCleanup (@@() rand ("state", old_state); + restore_state = onCleanup (@@() rand ("state", old_state)); rand ("state", 42); @dots{} endfunction # rand generator state restored by onCleanup diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/func.txi --- a/doc/interpreter/func.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/func.txi Sun May 25 10:29:05 2014 -0700 @@ -802,7 +802,7 @@ @DOCSTRING(command_line_path) -@DOCSTRING(find_dir_in_path) +@DOCSTRING(dir_in_loadpath) @node Subfunctions @subsection Subfunctions diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/grammar.txi --- a/doc/interpreter/grammar.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/grammar.txi Sun May 25 10:29:05 2014 -0700 @@ -49,9 +49,8 @@ @item @code{function} @tab @code{global} @tab @code{if} @item @code{methods} @tab @code{otherwise} @tab @code{parfor} @item @code{persistent} @tab @code{properties} @tab @code{return} -@item @code{static} @tab @code{switch} @tab @code{try} -@item @code{until} @tab @code{unwind_protect} @tab @code{unwind_protect_cleanup} -@item @code{while} +@item @code{switch} @tab @code{try} @tab @code{until} +@item @code{unwind_protect} @tab @code{unwind_protect_cleanup} @tab @code{while} @end multitable The function @code{iskeyword} can be used to quickly check whether an diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/install.txi --- a/doc/interpreter/install.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/install.txi Sun May 25 10:29:05 2014 -0700 @@ -846,7 +846,7 @@ @noindent in the kernel configuration files (typically found in the directory -@file{/sys/i386/conf}. After making this change, you'll need to rebuild +@file{/sys/i386/conf}). After making this change, you'll need to rebuild the kernel, install it, and reboot. @item diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/java.txi --- a/doc/interpreter/java.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/java.txi Sun May 25 10:29:05 2014 -0700 @@ -95,9 +95,11 @@ @cindex path, removing from classpath @DOCSTRING(javarmpath) -The following four functions provide information and control over the interface +The following functions provide information and control over the interface between Octave and the Java Virtual Machine. +@DOCSTRING(javachk) + @DOCSTRING(usejava) @cindex memory, displaying Java memory status diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/macros.texi --- a/doc/interpreter/macros.texi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/macros.texi Sun May 25 10:29:05 2014 -0700 @@ -28,14 +28,14 @@ @c which is `XXX'. This looks particularly bad when the macro body is @c single or double-quoted text, such as a property value `"position"' @ifinfo -@rmacro qcode{arg} +@macro qcode{arg} \arg\ -@end rmacro +@end macro @end ifinfo @ifnotinfo -@rmacro qcode{arg} +@macro qcode{arg} @code{\arg\} -@end rmacro +@end macro @end ifnotinfo @c The following macro is used for the on-line help system, but we don't diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/plot.txi --- a/doc/interpreter/plot.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/plot.txi Sun May 25 10:29:05 2014 -0700 @@ -937,6 +937,17 @@ @DOCSTRING(orient) +@code{print} and @code{saveas} are used when work on a plot has finished +and the output must be in a publication-ready format. During intermediate +stages it is often better to save the graphics object and all of its +associated information so that changes---to colors, axis limits, marker styles, +etc.---can be made easily from within Octave. The @code{hgsave}/@code{hgload} +commands can be used to save and re-create a graphics object. + +@DOCSTRING(hgsave) + +@DOCSTRING(hgload) + @node Interacting with Plots @subsection Interacting with Plots @@ -1233,18 +1244,21 @@ @noindent sets the range of the x-axis for the current axes object in the current -figure to @samp{[-10, 10]}. Additionally, calling set with a graphics -object index as the only argument returns a structure containing the -default values for all the properties for the given object type. For -example, +figure to @samp{[-10, 10]}. + +Default property values can also be queried if the @code{set} function is +called without a value argument. When only one argument is given (a graphic +handle) then a structure with defaults for all properties of the given object +type is returned. For example, @example set (gca ()) @end example @noindent -returns a structure containing the default property values for axes -objects. +returns a structure containing the default property values for axes objects. +If @code{set} is called with two arguments (a graphic handle and a property +name) then only the defaults for the requested property are returned. @DOCSTRING(get) @@ -2868,6 +2882,8 @@ @DOCSTRING(linkprop) +@DOCSTRING(linkaxes) + These capabilities are used in a number of basic graphics objects. The @code{hggroup} objects created by the functions of Octave contain one or more graphics object and are used to: diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/sparse.txi --- a/doc/interpreter/sparse.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/sparse.txi Sun May 25 10:29:05 2014 -0700 @@ -793,8 +793,8 @@ @item If the matrix is not square, or any of the previous solvers flags a singular or near singular matrix, find a minimum norm solution using -@sc{cxsparse}@footnote{The @sc{cholmod}, @sc{umfpack} and @sc{cxsparse} packages were -written by Tim Davis and are available at +@sc{cxsparse}@footnote{The @sc{cholmod}, @sc{umfpack} and @sc{cxsparse} +packages were written by Tim Davis and are available at @url{http://www.cise.ufl.edu/research/sparse/}}. @end enumerate @@ -997,7 +997,7 @@ as constant on each simplex (represented by the vector @code{conductivity}). Based on the finite element geometry, we first calculate a system (or stiffness) matrix for each simplex (represented as 3-by-3 elements on the -diagonal of the element-wise system matrix @code{SE}. Based on @code{SE} +diagonal of the element-wise system matrix @code{SE}). Based on @code{SE} and a N-by-DE connectivity matrix @code{C}, representing the connections between simplices and vertices, the global connectivity matrix @code{S} is calculated. diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/var.txi --- a/doc/interpreter/var.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/var.txi Sun May 25 10:29:05 2014 -0700 @@ -221,8 +221,7 @@ @end example The behavior of persistent variables is equivalent to the behavior of -static variables in C@. The command @code{static} in Octave is also -recognized and is equivalent to @code{persistent}. +static variables in C@. Like global variables, a persistent variable may only be initialized once. For example, after executing the following code diff -r bd1fd4ed3d67 -r 888f8ce79bbe doc/interpreter/vectorize.txi --- a/doc/interpreter/vectorize.txi Sun May 25 10:26:18 2014 -0700 +++ b/doc/interpreter/vectorize.txi Sun May 25 10:29:05 2014 -0700 @@ -697,7 +697,7 @@ for i = 1:length (A) ## this will be two columns, the first is the difference and ## the second the mean of the two elements used for the diff. - B(i,:) = [A(i+1)-A(i), (A(i+1) + A(i))/2)]; + B(i,:) = [A(i+1)-A(i), (A(i+1) + A(i))/2]; endfor @end group @end example diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Backend.cc --- a/libgui/graphics/Backend.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Backend.cc Sun May 25 10:29:05 2014 -0700 @@ -53,16 +53,16 @@ if (go.isa ("figure")) return std::string ("__plot_stream__"); else if (go.isa ("uicontrol") - || go.isa ("uipanel") - || go.isa ("uimenu") - || go.isa ("uicontextmenu") - || go.isa ("uitoolbar") - || go.isa ("uipushtool") - || go.isa ("uitoggletool")) + || go.isa ("uipanel") + || go.isa ("uimenu") + || go.isa ("uicontextmenu") + || go.isa ("uitoolbar") + || go.isa ("uipushtool") + || go.isa ("uitoggletool")) return std::string ("__object__"); else qCritical ("QtHandles::Backend: no __object__ property known for object " - "of type %s", go.type ().c_str ()); + "of type %s", go.type ().c_str ()); return std::string (); } @@ -73,7 +73,7 @@ ObjectFactory* factory = ObjectFactory::instance (); connect (this, SIGNAL (createObject (double)), - factory, SLOT (createObject (double))); + factory, SLOT (createObject (double))); } Backend::~Backend (void) @@ -92,13 +92,13 @@ || go.isa ("uitoggletool")) { Logger::debug ("Backend::initialize %s from thread %08x", - go.type ().c_str (), QThread::currentThreadId ()); + go.type ().c_str (), QThread::currentThreadId ()); ObjectProxy* proxy = new ObjectProxy (); graphics_object gObj (go); gObj.get_properties ().set(toolkitObjectProperty (go), - OCTAVE_PTR_TYPE ((OCTAVE_INTPTR_TYPE) proxy)); + OCTAVE_PTR_TYPE ((OCTAVE_INTPTR_TYPE) proxy)); emit createObject (go.get_handle ().value ()); @@ -123,30 +123,30 @@ return; Logger::debug ("Backend::update %s(%d) from thread %08x", - go.type ().c_str (), pId, QThread::currentThreadId ()); + go.type ().c_str (), pId, QThread::currentThreadId ()); ObjectProxy* proxy = toolkitObjectProxy (go); if (proxy) { if (go.isa ("uicontrol") - && pId == uicontrol::properties::ID_STYLE) - { - // Special case: we need to recreate the control widget - // associated with the octave graphics_object + && pId == uicontrol::properties::ID_STYLE) + { + // Special case: we need to recreate the control widget + // associated with the octave graphics_object - finalize (go); - initialize (go); - } + finalize (go); + initialize (go); + } else - proxy->update (pId); + proxy->update (pId); } } void Backend::finalize (const graphics_object& go) { Logger::debug ("Backend::finalize %s from thread %08x", - go.type ().c_str (), QThread::currentThreadId ()); + go.type ().c_str (), QThread::currentThreadId ()); ObjectProxy* proxy = toolkitObjectProxy (go); @@ -168,7 +168,7 @@ ObjectProxy* proxy = toolkitObjectProxy (go); if (proxy) - proxy->redraw (); + proxy->redraw (); } } @@ -189,12 +189,12 @@ octave_value ov = go.get (toolkitObjectProperty (go)); if (ov.is_defined () && ! ov.is_empty ()) - { - OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value (); + { + OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value (); - if (! error_state) - return reinterpret_cast (ptr); - } + if (! error_state) + return reinterpret_cast (ptr); + } } return 0; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/BaseControl.cc --- a/libgui/graphics/BaseControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/BaseControl.cc Sun May 25 10:29:05 2014 -0700 @@ -45,24 +45,24 @@ || props.style_is ("popupmenu")) { p.setColor (QPalette::Base, - Utils::fromRgb (props.get_backgroundcolor_rgb ())); + Utils::fromRgb (props.get_backgroundcolor_rgb ())); p.setColor (QPalette::Text, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); + Utils::fromRgb (props.get_foregroundcolor_rgb ())); } else if (props.style_is ("pushbutton") - || props.style_is ("togglebutton")) + || props.style_is ("togglebutton")) { p.setColor (QPalette::Button, - Utils::fromRgb (props.get_backgroundcolor_rgb ())); + Utils::fromRgb (props.get_backgroundcolor_rgb ())); p.setColor (QPalette::ButtonText, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); + Utils::fromRgb (props.get_foregroundcolor_rgb ())); } else { p.setColor (QPalette::Window, - Utils::fromRgb (props.get_backgroundcolor_rgb ())); + Utils::fromRgb (props.get_backgroundcolor_rgb ())); p.setColor (QPalette::WindowText, - Utils::fromRgb (props.get_foregroundcolor_rgb ())); + Utils::fromRgb (props.get_foregroundcolor_rgb ())); } w->setPalette (p); @@ -83,7 +83,7 @@ Matrix bb = up.get_boundingbox (false); w->setGeometry (xround (bb(0)), xround (bb(1)), - xround (bb(2)), xround (bb(3))); + xround (bb(2)), xround (bb(3))); w->setFont (Utils::computeFont (up, bb(3))); updatePalette (up, w); w->setEnabled (up.enable_is ("on")); @@ -108,11 +108,11 @@ switch (pId) { case uicontrol::properties::ID_POSITION: - { - Matrix bb = up.get_boundingbox (false); - w->setGeometry (xround (bb(0)), xround (bb(1)), - xround (bb(2)), xround (bb(3))); - } + { + Matrix bb = up.get_boundingbox (false); + w->setGeometry (xround (bb(0)), xround (bb(1)), + xround (bb(2)), xround (bb(3))); + } break; case uicontrol::properties::ID_FONTNAME: case uicontrol::properties::ID_FONTSIZE: @@ -153,56 +153,56 @@ { case QEvent::Resize: if (m_normalizedFont) - { - gh_manager::auto_lock lock; + { + gh_manager::auto_lock lock; - qWidget ()->setFont (Utils::computeFont - (properties ())); - } + qWidget ()->setFont (Utils::computeFont + (properties ())); + } break; case QEvent::MouseButtonPress: - { - gh_manager::auto_lock lock; + { + gh_manager::auto_lock lock; - QMouseEvent* m = dynamic_cast (event); - graphics_object go = object (); - uicontrol::properties& up = Utils::properties (go); - graphics_object fig = go.get_ancestor ("figure"); + QMouseEvent* m = dynamic_cast (event); + graphics_object go = object (); + uicontrol::properties& up = Utils::properties (go); + graphics_object fig = go.get_ancestor ("figure"); - if (m->button () != Qt::LeftButton - || ! up.enable_is ("on")) - { - gh_manager::post_set (fig.get_handle (), "selectiontype", - Utils::figureSelectionType (m), false); - gh_manager::post_set (fig.get_handle (), "currentpoint", - Utils::figureCurrentPoint (fig, m), - false); - gh_manager::post_callback (fig.get_handle (), - "windowbuttondownfcn"); - gh_manager::post_callback (m_handle, "buttondownfcn"); + if (m->button () != Qt::LeftButton + || ! up.enable_is ("on")) + { + gh_manager::post_set (fig.get_handle (), "selectiontype", + Utils::figureSelectionType (m), false); + gh_manager::post_set (fig.get_handle (), "currentpoint", + Utils::figureCurrentPoint (fig, m), + false); + gh_manager::post_callback (fig.get_handle (), + "windowbuttondownfcn"); + gh_manager::post_callback (m_handle, "buttondownfcn"); - if (m->button () == Qt::RightButton) - ContextMenu::executeAt (up, m->globalPos ()); - } - else - { - if (up.style_is ("listbox")) - gh_manager::post_set (fig.get_handle (), "selectiontype", - Utils::figureSelectionType (m), false); - else - gh_manager::post_set (fig.get_handle (), "selectiontype", - octave_value ("normal"), false); - } - } + if (m->button () == Qt::RightButton) + ContextMenu::executeAt (up, m->globalPos ()); + } + else + { + if (up.style_is ("listbox")) + gh_manager::post_set (fig.get_handle (), "selectiontype", + Utils::figureSelectionType (m), false); + else + gh_manager::post_set (fig.get_handle (), "selectiontype", + octave_value ("normal"), false); + } + } break; case QEvent::MouseMove: if (qWidget ()->hasMouseTracking ()) { - gh_manager::auto_lock lock; + gh_manager::auto_lock lock; - QMouseEvent* m = dynamic_cast (event); - graphics_object go = object (); - graphics_object fig = go.get_ancestor ("figure"); + QMouseEvent* m = dynamic_cast (event); + graphics_object go = object (); + graphics_object fig = go.get_ancestor ("figure"); gh_manager::post_set (fig.get_handle (), "currentpoint", Utils::figureCurrentPoint (fig, m), false); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ButtonControl.cc --- a/libgui/graphics/ButtonControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ButtonControl.cc Sun May 25 10:29:05 2014 -0700 @@ -46,7 +46,7 @@ Matrix value = up.get_value ().matrix_value (); if (value.numel () > 0 && value(0) == up.get_max ()) - btn->setChecked (true); + btn->setChecked (true); } connect (btn, SIGNAL (clicked (void)), SLOT (clicked (void))); @@ -70,19 +70,19 @@ case uicontrol::properties::ID_VALUE: m_blockCallback = true; if (btn->isCheckable ()) - { - Matrix value = up.get_value ().matrix_value (); + { + Matrix value = up.get_value ().matrix_value (); - if (value.numel () > 0) - { - double dValue = value(0); + if (value.numel () > 0) + { + double dValue = value(0); - if (dValue == up.get_min () && btn->isChecked ()) - btn->setChecked (false); - else if (dValue == up.get_max () && ! btn->isChecked ()) - btn->setChecked (true); - } - } + if (dValue == up.get_min () && btn->isChecked ()) + btn->setChecked (false); + else if (dValue == up.get_max () && ! btn->isChecked ()) + btn->setChecked (true); + } + } m_blockCallback = false; break; default: @@ -105,8 +105,8 @@ double newValue = (checked ? up.get_max () : up.get_min ()); if (oldValue.numel() != 1 - || (newValue != oldValue(0))) - gh_manager::post_set (m_handle, "value", newValue, false); + || (newValue != oldValue(0))) + gh_manager::post_set (m_handle, "value", newValue, false); gh_manager::post_callback (m_handle, "callback"); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Canvas.cc --- a/libgui/graphics/Canvas.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Canvas.cc Sun May 25 10:29:05 2014 -0700 @@ -95,7 +95,7 @@ draw (m_handle); if (m_mouseMode == ZoomMode && m_mouseAxes.ok ()) - drawZoomBox (m_mouseAnchor, m_mouseCurrent); + drawZoomBox (m_mouseAnchor, m_mouseCurrent); } } @@ -109,65 +109,65 @@ axes::properties& ap = Utils::properties (ax); switch (m_mouseMode) - { - case RotateMode: - { - Matrix bb = ap.get_boundingbox (true); - Matrix view = ap.get_view ().matrix_value (); + { + case RotateMode: + { + Matrix bb = ap.get_boundingbox (true); + Matrix view = ap.get_view ().matrix_value (); - // Compute new view angles - view(0) += ((m_mouseCurrent.x () - event->x ()) - * (180.0 / bb(2))); - view(1) += ((event->y () - m_mouseCurrent.y ()) - * (180.0 / bb(3))); + // Compute new view angles + view(0) += ((m_mouseCurrent.x () - event->x ()) + * (180.0 / bb(2))); + view(1) += ((event->y () - m_mouseCurrent.y ()) + * (180.0 / bb(3))); - // Clipping - view(1) = std::min (view(1), 90.0); - view(1) = std::max (view(1), -90.0); - if (view(0) > 180.0) - view(0) -= 360.0; - else if (view(0) < -180.0) - view(0) += 360.0; + // Clipping + view(1) = std::min (view(1), 90.0); + view(1) = std::max (view(1), -90.0); + if (view(0) > 180.0) + view(0) -= 360.0; + else if (view(0) < -180.0) + view(0) += 360.0; - // Snapping - double snapMargin = 1.0; - for (int a = -90; a <= 90; a += 90) - if ((a - snapMargin) < view(1) - && view(1) < (a + snapMargin)) - { - view(1) = a; - break; - } - for (int a = -180; a <= 180; a += 180) - if ((a - snapMargin) < view(0) - && view(0) < (a + snapMargin)) - { - if (a == 180) - view(0) = -180; - else - view(0) = a; - break; - } + // Snapping + double snapMargin = 1.0; + for (int a = -90; a <= 90; a += 90) + if ((a - snapMargin) < view(1) + && view(1) < (a + snapMargin)) + { + view(1) = a; + break; + } + for (int a = -180; a <= 180; a += 180) + if ((a - snapMargin) < view(0) + && view(0) < (a + snapMargin)) + { + if (a == 180) + view(0) = -180; + else + view(0) = a; + break; + } - // Update axes properties - ap.set_view (view); + // Update axes properties + ap.set_view (view); - // Update current mouse position - m_mouseCurrent = event->pos (); + // Update current mouse position + m_mouseCurrent = event->pos (); - // Force immediate redraw - redraw (true); - } - break; - case ZoomMode: - m_mouseCurrent = event->pos(); - redraw (true); - break; - case PanMode: - break; - default: - break; - } + // Force immediate redraw + redraw (true); + } + break; + case ZoomMode: + m_mouseCurrent = event->pos(); + redraw (true); + break; + case PanMode: + break; + default: + break; + } } else if (m_mouseMode == NoMode) { @@ -178,8 +178,8 @@ graphics_object figObj (obj.get_ancestor ("figure")); updateCurrentPoint (figObj, obj, event); - gh_manager::post_callback (figObj.get_handle (), - "windowbuttonmotionfcn"); + gh_manager::post_callback (figObj.get_handle (), + "windowbuttonmotionfcn"); } } } @@ -199,24 +199,24 @@ octave_idx_type num_children = children.numel (); for (int i = 0; i < num_children; i++) - { - graphics_object childObj (gh_manager::get_object (children(i))); + { + graphics_object childObj (gh_manager::get_object (children(i))); if (childObj.isa ("axes")) axesList.append (childObj); - else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel")) - { - Matrix bb = childObj.get_properties ().get_boundingbox (false); - QRectF r (bb(0), bb(1), bb(2), bb(3)); + else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel")) + { + Matrix bb = childObj.get_properties ().get_boundingbox (false); + QRectF r (bb(0), bb(1), bb(2), bb(3)); - r.adjust (-5, -5, 5, 5); - if (r.contains (event->posF ())) - { - currentObj = childObj; - break; - } - } - } + r.adjust (-5, -5, 5, 5); + if (r.contains (event->posF ())) + { + currentObj = childObj; + break; + } + } + } if (! currentObj) { @@ -269,61 +269,61 @@ MouseMode newMouseMode = NoMode; if (fig) - newMouseMode = fig->mouseMode (); + newMouseMode = fig->mouseMode (); switch (newMouseMode) - { - case NoMode: - gh_manager::post_set (figObj.get_handle (), "selectiontype", - Utils::figureSelectionType (event), false); + { + case NoMode: + gh_manager::post_set (figObj.get_handle (), "selectiontype", + Utils::figureSelectionType (event), false); updateCurrentPoint (figObj, obj, event); - gh_manager::post_callback (figObj.get_handle (), - "windowbuttondownfcn"); + gh_manager::post_callback (figObj.get_handle (), + "windowbuttondownfcn"); gh_manager::post_callback (currentObj.get_handle (), "buttondownfcn"); - if (event->button () == Qt::RightButton) - ContextMenu::executeAt (currentObj.get_properties (), - event->globalPos ()); - break; - case RotateMode: - case ZoomMode: - case PanMode: - if (axesObj) - { - if (event->buttons () == Qt::LeftButton - && event->modifiers () == Qt::NoModifier) - { - m_mouseAnchor = m_mouseCurrent = event->pos (); - m_mouseAxes = axesObj.get_handle (); - m_mouseMode = newMouseMode; - } - else if (newMouseMode == ZoomMode - && event->modifiers () == Qt::NoModifier) - { - switch (event->buttons ()) - { - case Qt::RightButton: - Utils::properties (axesObj).unzoom (); - break; - case Qt::MidButton: - { - axes::properties& ap = - Utils::properties (axesObj); + if (event->button () == Qt::RightButton) + ContextMenu::executeAt (currentObj.get_properties (), + event->globalPos ()); + break; + case RotateMode: + case ZoomMode: + case PanMode: + if (axesObj) + { + if (event->buttons () == Qt::LeftButton + && event->modifiers () == Qt::NoModifier) + { + m_mouseAnchor = m_mouseCurrent = event->pos (); + m_mouseAxes = axesObj.get_handle (); + m_mouseMode = newMouseMode; + } + else if (newMouseMode == ZoomMode + && event->modifiers () == Qt::NoModifier) + { + switch (event->buttons ()) + { + case Qt::RightButton: + Utils::properties (axesObj).unzoom (); + break; + case Qt::MidButton: + { + axes::properties& ap = + Utils::properties (axesObj); - ap.clear_zoom_stack (); - ap.set_xlimmode ("auto"); - ap.set_ylimmode ("auto"); - ap.set_zlimmode ("auto"); - } - break; - } - redraw (false); - } - } - break; - default: - break; - } + ap.clear_zoom_stack (); + ap.set_xlimmode ("auto"); + ap.set_ylimmode ("auto"); + ap.set_zlimmode ("auto"); + } + break; + } + redraw (false); + } + } + break; + default: + break; + } } } @@ -337,26 +337,26 @@ graphics_object ax = gh_manager::get_object (m_mouseAxes); if (ax.valid_object ()) - { - axes::properties& ap = Utils::properties (ax); + { + axes::properties& ap = Utils::properties (ax); - ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (), - m_mouseAnchor.y ()); - ColumnVector p1 = ap.pixel2coord (event->x (), - event->y ()); + ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (), + m_mouseAnchor.y ()); + ColumnVector p1 = ap.pixel2coord (event->x (), + event->y ()); - Matrix xl (1, 2, 0.0); - Matrix yl (1, 2, 0.0); + Matrix xl (1, 2, 0.0); + Matrix yl (1, 2, 0.0); - xl(0) = std::min (p0(0), p1(0)); - xl(1) = std::max (p0(0), p1(0)); - yl(0) = std::min (p0(1), p1(1)); - yl(1) = std::max (p0(1), p1(1)); + xl(0) = std::min (p0(0), p1(0)); + xl(1) = std::max (p0(0), p1(0)); + yl(0) = std::min (p0(1), p1(1)); + yl(1) = std::max (p0(1), p1(1)); - ap.zoom (xl, yl); + ap.zoom (xl, yl); - redraw (false); - } + redraw (false); + } } else if (m_mouseMode == NoMode) { @@ -407,7 +407,7 @@ } Canvas* Canvas::create (const std::string& /* name */, QWidget* parent, - const graphics_handle& handle) + const graphics_handle& handle) { // Only OpenGL return new GLCanvas (parent, handle); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Canvas.h --- a/libgui/graphics/Canvas.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Canvas.h Sun May 25 10:29:05 2014 -0700 @@ -58,7 +58,7 @@ virtual QWidget* qWidget (void) = 0; static Canvas* create (const std::string& name, QWidget* parent, - const graphics_handle& handle); + const graphics_handle& handle); protected: virtual void draw (const graphics_handle& handle) = 0; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/CheckBoxControl.cc --- a/libgui/graphics/CheckBoxControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/CheckBoxControl.cc Sun May 25 10:29:05 2014 -0700 @@ -41,7 +41,7 @@ Container* container = parent->innerContainer (); if (container) - return new CheckBoxControl (go, new QCheckBox (container)); + return new CheckBoxControl (go, new QCheckBox (container)); } return 0; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Container.cc --- a/libgui/graphics/Container.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Container.cc Sun May 25 10:29:05 2014 -0700 @@ -54,18 +54,18 @@ graphics_object go = gh_manager::get_object (handle); if (go) - { - graphics_object fig = go.get_ancestor ("figure"); + { + graphics_object fig = go.get_ancestor ("figure"); - m_canvas = Canvas::create (fig.get("renderer").string_value (), - this, handle); + m_canvas = Canvas::create (fig.get("renderer").string_value (), + this, handle); - QWidget* canvasWidget = m_canvas->qWidget (); + QWidget* canvasWidget = m_canvas->qWidget (); - canvasWidget->lower (); - canvasWidget->show (); - canvasWidget->setGeometry (0, 0, width (), height ()); - } + canvasWidget->lower (); + canvasWidget->show (); + canvasWidget->setGeometry (0, 0, width (), height ()); + } } return m_canvas; @@ -81,18 +81,18 @@ foreach (QObject* qObj, children ()) { if (qObj->isWidgetType ()) - { - Object* obj = Object::fromQObject (qObj); + { + Object* obj = Object::fromQObject (qObj); - if (obj) - { - Matrix bb = obj->properties ().get_boundingbox (false); + if (obj) + { + Matrix bb = obj->properties ().get_boundingbox (false); - obj->qWidget () - ->setGeometry (xround (bb(0)), xround (bb(1)), - xround (bb(2)), xround (bb(3))); - } - } + obj->qWidget () + ->setGeometry (xround (bb(0)), xround (bb(1)), + xround (bb(2)), xround (bb(3))); + } + } } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ContextMenu.cc --- a/libgui/graphics/ContextMenu.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ContextMenu.cc Sun May 25 10:29:05 2014 -0700 @@ -69,19 +69,19 @@ { case base_properties::ID_VISIBLE: if (up.is_visible ()) - { - Matrix pos = up.get_position ().matrix_value (); - QWidget* parentW = menu->parentWidget (); - QPoint pt; + { + Matrix pos = up.get_position ().matrix_value (); + QWidget* parentW = menu->parentWidget (); + QPoint pt; - pt.rx () = xround (pos(0)); - pt.ry () = parentW->height () - xround (pos(1)); - pt = parentW->mapToGlobal (pt); + pt.rx () = xround (pos(0)); + pt.ry () = parentW->height () - xround (pos(1)); + pt = parentW->mapToGlobal (pt); - menu->popup (pt); - } + menu->popup (pt); + } else - menu->hide (); + menu->hide (); break; default: Object::update (pId); @@ -114,18 +114,18 @@ graphics_object go = gh_manager::get_object (h); if (go.valid_object ()) - { - ContextMenu* cMenu = - dynamic_cast (Backend::toolkitObject (go)); + { + ContextMenu* cMenu = + dynamic_cast (Backend::toolkitObject (go)); - if (cMenu) - { - QMenu* menu = cMenu->qWidget (); + if (cMenu) + { + QMenu* menu = cMenu->qWidget (); - if (menu) - menu->popup (pt); - } - } + if (menu) + menu->popup (pt); + } + } } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/EditControl.cc --- a/libgui/graphics/EditControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/EditControl.cc Sun May 25 10:29:05 2014 -0700 @@ -43,14 +43,14 @@ Container* container = parent->innerContainer (); if (container) - { - uicontrol::properties& up = Utils::properties (go); + { + uicontrol::properties& up = Utils::properties (go); - if ((up.get_max () - up.get_min ()) > 1) - return new EditControl (go, new TextEdit (container)); - else - return new EditControl (go, new QLineEdit (container)); - } + if ((up.get_max () - up.get_min ()) > 1) + return new EditControl (go, new TextEdit (container)); + else + return new EditControl (go, new QLineEdit (container)); + } } return 0; @@ -74,12 +74,12 @@ edit->setText (Utils::fromStdString (up.get_string_string ())); edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); + up.get_verticalalignment ())); connect (edit, SIGNAL (textEdited (const QString&)), - SLOT (textChanged (void))); + SLOT (textChanged (void))); connect (edit, SIGNAL (editingFinished (void)), - SLOT (editingFinished (void))); + SLOT (editingFinished (void))); } EditControl::EditControl (const graphics_object& go, TextEdit* edit) @@ -103,9 +103,9 @@ edit->setPlainText (Utils::fromStdString (up.get_string_string ())); connect (edit, SIGNAL (textChanged (void)), - SLOT (textChanged (void))); + SLOT (textChanged (void))); connect (edit, SIGNAL (editingFinished (void)), - SLOT (editingFinished (void))); + SLOT (editingFinished (void))); } EditControl::~EditControl (void) @@ -129,11 +129,11 @@ if (! handled) { switch (pId) - { - default: - BaseControl::update (pId); - break; - } + { + default: + BaseControl::update (pId); + break; + } } } @@ -150,17 +150,17 @@ case uicontrol::properties::ID_HORIZONTALALIGNMENT: case uicontrol::properties::ID_VERTICALALIGNMENT: edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); + up.get_verticalalignment ())); return true; case uicontrol::properties::ID_MIN: case uicontrol::properties::ID_MAX: if ((up.get_max () - up.get_min ()) > 1) - { - QWidget* container = edit->parentWidget (); + { + QWidget* container = edit->parentWidget (); - delete edit; - init (new TextEdit (container), true); - } + delete edit; + init (new TextEdit (container), true); + } return true; default: break; @@ -182,12 +182,12 @@ case uicontrol::properties::ID_MIN: case uicontrol::properties::ID_MAX: if ((up.get_max () - up.get_min ()) <= 1) - { - QWidget* container = edit->parentWidget (); + { + QWidget* container = edit->parentWidget (); - delete edit; - init (new QLineEdit (container), true); - } + delete edit; + init (new QLineEdit (container), true); + } return true; default: break; @@ -206,8 +206,8 @@ if (m_textChanged) { QString txt = (m_multiLine - ? qWidget ()->toPlainText () - : qWidget ()->text ()); + ? qWidget ()->toPlainText () + : qWidget ()->text ()); gh_manager::post_set (m_handle, "string", Utils::toStdString (txt), false); gh_manager::post_callback (m_handle, "callback"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Figure.cc --- a/libgui/graphics/Figure.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Figure.cc Sun May 25 10:29:05 2014 -0700 @@ -61,8 +61,8 @@ graphics_object go (gh_manager::get_object (kids(i))); if (go && (go.isa ("uicontrol") || go.isa ("uipanel") - || go.isa ("uibuttongroup"))) - return true; + || go.isa ("uibuttongroup"))) + return true; } return false; @@ -77,7 +77,7 @@ graphics_object go (gh_manager::get_object (kids(i))); if (go && go.isa ("uimenu")) - return true; + return true; } return false; @@ -173,7 +173,7 @@ MouseModeActionGroup* mouseModeGroup = new MouseModeActionGroup (win); connect (mouseModeGroup, SIGNAL (modeChanged (MouseMode)), - SLOT (setMouseMode (MouseMode))); + SLOT (setMouseMode (MouseMode))); m_figureToolBar->addActions (mouseModeGroup->actions ()); m_menuBar = new MenuBar (win); @@ -188,23 +188,23 @@ fileMenu->addAction (tr ("Save &As"))->setEnabled (false); fileMenu->addSeparator (); fileMenu->addAction (tr ("&Close Figure"), this, - SLOT (fileCloseFigure (void)), Qt::CTRL|Qt::Key_W); + SLOT (fileCloseFigure (void)), Qt::CTRL|Qt::Key_W); QMenu* editMenu = m_menuBar->addMenu (tr ("&Edit")); editMenu->menuAction ()->setObjectName ("builtinMenu"); editMenu->addAction (tr ("Cop&y"), this, SLOT (editCopy (void)), - Qt::CTRL|Qt::Key_C)->setEnabled (false); + Qt::CTRL|Qt::Key_C)->setEnabled (false); editMenu->addAction (tr ("Cu&t"), this, SLOT (editCut (void)), - Qt::CTRL|Qt::Key_X)->setEnabled (false); + Qt::CTRL|Qt::Key_X)->setEnabled (false); editMenu->addAction (tr ("&Paste"), this, SLOT (editPaste(void)), - Qt::CTRL|Qt::Key_V)->setEnabled (false); + Qt::CTRL|Qt::Key_V)->setEnabled (false); editMenu->addSeparator (); editMenu->addActions (mouseModeGroup->actions ()); QMenu* helpMenu = m_menuBar->addMenu (tr ("&Help")); helpMenu->menuAction ()->setObjectName ("builtinMenu"); helpMenu->addAction (tr ("&About QtHandles"), this, - SLOT (helpAboutQtHandles (void))); + SLOT (helpAboutQtHandles (void))); helpMenu->addAction (tr ("About &Qt"), qApp, SLOT (aboutQt (void))); m_menuBar->addReceiver (this); @@ -226,12 +226,12 @@ } foreach (QFrame* frame, - qWidget ()->findChildren ("UIPanel")) + qWidget ()->findChildren ("UIPanel")) { Object* obj = Object::fromQObject (frame); if (obj) - obj->slotRedraw (); + obj->slotRedraw (); } } @@ -260,20 +260,20 @@ switch (pId) { case figure::properties::ID_POSITION: - { + { m_innerRect = boundingBoxToRect (fp.get_boundingbox (true)); //qDebug () << "Figure::update(position):" << m_innerRect; - int offset = 0; + int offset = 0; foreach (QToolBar* tb, win->findChildren ()) if (! tb->isHidden ()) offset += tb->sizeHint ().height (); - if (! m_menuBar->isHidden ()) - offset += m_menuBar->sizeHint ().height () + 1; + if (! m_menuBar->isHidden ()) + offset += m_menuBar->sizeHint ().height () + 1; //qDebug () << "Figure::update(position)(adjusted):" << m_innerRect.adjusted (0, -offset, 0, 0); - win->setGeometry (m_innerRect.adjusted (0, -offset, 0, 0)); + win->setGeometry (m_innerRect.adjusted (0, -offset, 0, 0)); //qDebug () << "Figure::update(position): done"; - } + } break; case figure::properties::ID_NAME: case figure::properties::ID_NUMBERTITLE: @@ -281,17 +281,17 @@ break; case figure::properties::ID_VISIBLE: if (fp.is_visible ()) - QTimer::singleShot (0, win, SLOT (show ())); + QTimer::singleShot (0, win, SLOT (show ())); else - win->hide (); + win->hide (); break; case figure::properties::ID_TOOLBAR: if (fp.toolbar_is ("none")) - showFigureToolBar (false); + showFigureToolBar (false); else if (fp.toolbar_is ("figure")) - showFigureToolBar (true); + showFigureToolBar (true); else // "auto" - showFigureToolBar (! hasUiControlChildren (fp)); + showFigureToolBar (! hasUiControlChildren (fp)); break; case figure::properties::ID_MENUBAR: showMenuBar (fp.menubar_is ("figure")); @@ -332,9 +332,9 @@ QRect r = qWidget ()->geometry (); if (! visible) - r.adjust (0, dy, 0, 0); + r.adjust (0, dy, 0, 0); else - r.adjust (0, -dy, 0, 0); + r.adjust (0, -dy, 0, 0); m_blockUpdates = true; qWidget ()->setGeometry (r); @@ -344,12 +344,12 @@ updateBoundingBox (false); if (visible) - m_mouseMode = m_lastMouseMode; + m_mouseMode = m_lastMouseMode; else - { - m_lastMouseMode = m_mouseMode; - m_mouseMode = NoMode; - } + { + m_lastMouseMode = m_mouseMode; + m_mouseMode = NoMode; + } } } @@ -373,9 +373,9 @@ //qDebug () << "Figure::showMenuBar:" << r; if (! visible) - r.adjust (0, dy, 0, 0); + r.adjust (0, dy, 0, 0); else - r.adjust (0, -dy, 0, 0); + r.adjust (0, -dy, 0, 0); //qDebug () << "Figure::showMenuBar(adjusted):" << r; m_blockUpdates = true; @@ -467,7 +467,7 @@ if (flags & UpdateBoundingBoxSize) r.setSize (win->frameGeometry ().size ()); - if (r.isValid () && r != m_outerRect ) + if (r.isValid () && r != m_outerRect) { //qDebug() << "outer rect changed:" << m_outerRect << "->>" << r; m_outerRect = r; @@ -498,38 +498,38 @@ if (! m_blockUpdates) { if (obj == m_container) - { + { // Do nothing... - } + } else if (obj == m_menuBar) - { - switch (event->type ()) - { - case QEvent::ActionRemoved: - { - QAction* a = dynamic_cast (event)->action (); + { + switch (event->type ()) + { + case QEvent::ActionRemoved: + { + QAction* a = dynamic_cast (event)->action (); - if (! a->isSeparator () - && a->objectName () != "builtinMenu") + if (! a->isSeparator () + && a->objectName () != "builtinMenu") updateMenuBar (); - } - break; - default: - break; - } - } + } + break; + default: + break; + } + } else - { - switch (event->type ()) - { - case QEvent::Close: - event->ignore (); - gh_manager::post_callback (m_handle, "closerequestfcn"); - return true; - default: - break; - } - } + { + switch (event->type ()) + { + case QEvent::Close: + event->ignore (); + gh_manager::post_callback (m_handle, "closerequestfcn"); + return true; + default: + break; + } + } } return false; @@ -541,55 +541,55 @@ { if (watched == m_container) { - switch (event->type ()) - { - case QEvent::Resize: - updateBoundingBox (true, UpdateBoundingBoxSize); - break; - case QEvent::ChildAdded: - if (dynamic_cast (event)->child - ()->isWidgetType()) - { - gh_manager::auto_lock lock; - const figure::properties& fp = properties
(); + switch (event->type ()) + { + case QEvent::Resize: + updateBoundingBox (true, UpdateBoundingBoxSize); + break; + case QEvent::ChildAdded: + if (dynamic_cast (event)->child + ()->isWidgetType()) + { + gh_manager::auto_lock lock; + const figure::properties& fp = properties
(); - showFigureToolBar (! hasUiControlChildren (fp)); - } - default: - break; - } + showFigureToolBar (! hasUiControlChildren (fp)); + } + default: + break; + } } else if (watched == m_menuBar) { - switch (event->type ()) - { - case QEvent::ActionAdded: - { - QAction* a = dynamic_cast (event)->action (); + switch (event->type ()) + { + case QEvent::ActionAdded: + { + QAction* a = dynamic_cast (event)->action (); - if (! a->isSeparator () + if (! a->isSeparator () && a->objectName () != "builtinMenu") updateMenuBar (); - } - break; - default: - break; - } + } + break; + default: + break; + } } else { - switch (event->type ()) - { - case QEvent::Move: - updateBoundingBox (false, UpdateBoundingBoxPosition); - updateBoundingBox (true, UpdateBoundingBoxPosition); - break; - case QEvent::Resize: - updateBoundingBox (false, UpdateBoundingBoxSize); - break; - default: - break; - } + switch (event->type ()) + { + case QEvent::Move: + updateBoundingBox (false, UpdateBoundingBoxPosition); + updateBoundingBox (true, UpdateBoundingBoxPosition); + break; + case QEvent::Resize: + updateBoundingBox (false, UpdateBoundingBoxSize); + break; + default: + break; + } } } } @@ -597,7 +597,7 @@ void Figure::helpAboutQtHandles (void) { QMessageBox::about (qWidget (), tr ("About QtHandles"), - ABOUT_TEXT); + ABOUT_TEXT); } void Figure::fileNewFigure (void) @@ -656,9 +656,9 @@ QRect r = win->geometry (); if (visible) - r.adjust (0, -sz.height (), 0, 0); + r.adjust (0, -sz.height (), 0, 0); else - r.adjust (0, sz.height (), 0, 0); + r.adjust (0, sz.height (), 0, 0); m_blockUpdates = true; win->setGeometry (r); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Figure.h --- a/libgui/graphics/Figure.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Figure.h Sun May 25 10:29:05 2014 -0700 @@ -37,11 +37,11 @@ enum MouseMode { - NoMode = 0, - RotateMode = 1, - ZoomMode = 2, - PanMode = 3, - SelectMode = 4 + NoMode = 0, + RotateMode = 1, + ZoomMode = 2, + PanMode = 3, + SelectMode = 4 }; class Container; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/GLCanvas.h --- a/libgui/graphics/GLCanvas.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/GLCanvas.h Sun May 25 10:29:05 2014 -0700 @@ -39,7 +39,7 @@ void draw (const graphics_handle& handle); void drawZoomBox (const QPoint& p1, const QPoint& p2); void resize (int /* x */, int /* y */, - int /* width */, int /* height */) { } + int /* width */, int /* height */) { } graphics_object selectFromAxes (const graphics_object& ax, const QPoint& pt); QWidget* qWidget (void) { return this; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ListBoxControl.cc --- a/libgui/graphics/ListBoxControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ListBoxControl.cc Sun May 25 10:29:05 2014 -0700 @@ -69,7 +69,7 @@ Container* container = parent->innerContainer (); if (container) - return new ListBoxControl (go, new QListWidget (container)); + return new ListBoxControl (go, new QListWidget (container)); } return 0; @@ -92,25 +92,25 @@ int lc = list->count (); for (octave_idx_type i = 0; i < n; i++) - { - int idx = xround (value(i)); + { + int idx = xround (value(i)); - if (1 <= idx && idx <= lc) - { - list->item (idx-1)->setSelected (true); - if (i == 0 - && list->selectionMode () == - QAbstractItemView::SingleSelection) - break; - } - } + if (1 <= idx && idx <= lc) + { + list->item (idx-1)->setSelected (true); + if (i == 0 + && list->selectionMode () == + QAbstractItemView::SingleSelection) + break; + } + } } list->removeEventFilter (this); list->viewport ()->installEventFilter (this); connect (list, SIGNAL (itemSelectionChanged (void)), - SLOT (itemSelectionChanged (void))); + SLOT (itemSelectionChanged (void))); } ListBoxControl::~ListBoxControl (void) @@ -134,9 +134,9 @@ case uicontrol::properties::ID_MIN: case uicontrol::properties::ID_MAX: if ((up.get_max () - up.get_min ()) > 1) - list->setSelectionMode (QAbstractItemView::ExtendedSelection); + list->setSelectionMode (QAbstractItemView::ExtendedSelection); else - list->setSelectionMode (QAbstractItemView::SingleSelection); + list->setSelectionMode (QAbstractItemView::SingleSelection); break; case uicontrol::properties::ID_VALUE: m_blockCallback = true; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Menu.cc --- a/libgui/graphics/Menu.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Menu.cc Sun May 25 10:29:05 2014 -0700 @@ -46,11 +46,11 @@ int keyMod = Qt::CTRL; if (c >= 'A' && c <= 'Z') - keyMod |= Qt::SHIFT; + keyMod |= Qt::SHIFT; if (c >= 'a' && c <= 'z') - c -= ('a' - 'A'); + c -= ('a' - 'A'); if (c >= 'A' && c <= 'Z') - return QKeySequence (keyMod | static_cast (c)); + return QKeySequence (keyMod | static_cast (c)); } return QKeySequence (); @@ -65,7 +65,7 @@ QObject* qObj = parent->qObject (); if (qObj) - return new Menu (go, new QAction (qObj), parent); + return new Menu (go, new QAction (qObj), parent); } return 0; @@ -102,46 +102,46 @@ int pos = static_cast (up.get_position ()); if (pos <= 0) - { - if (m_separator) - m_parent->insertAction (0, m_separator); - m_parent->insertAction (0, action); + { + if (m_separator) + m_parent->insertAction (0, m_separator); + m_parent->insertAction (0, action); - int count = 0; + int count = 0; - foreach (QAction* a, m_parent->actions ()) - if (! a->isSeparator () && a->objectName () != "builtinMenu") - count++; - up.get_property ("position").set - (octave_value (static_cast (count)), true, false); - } + foreach (QAction* a, m_parent->actions ()) + if (! a->isSeparator () && a->objectName () != "builtinMenu") + count++; + up.get_property ("position").set + (octave_value (static_cast (count)), true, false); + } else - { + { - int count = 0; - QAction* before = 0; + int count = 0; + QAction* before = 0; - foreach (QAction* a, m_parent->actions ()) - if (! a->isSeparator () && a->objectName () != "builtinMenu") - { - count++; - if (pos <= count) - { - before = a; - break; - } - } + foreach (QAction* a, m_parent->actions ()) + if (! a->isSeparator () && a->objectName () != "builtinMenu") + { + count++; + if (pos <= count) + { + before = a; + break; + } + } - if (m_separator) - m_parent->insertAction (before, m_separator); - m_parent->insertAction (before, action); + if (m_separator) + m_parent->insertAction (before, m_separator); + m_parent->insertAction (before, action); - if (before) - updateSiblingPositions (); - else - up.get_property ("position").set - (octave_value (static_cast (count+1)), true, false); - } + if (before) + updateSiblingPositions (); + else + up.get_property ("position").set + (octave_value (static_cast (count+1)), true, false); + } } connect (action, SIGNAL (triggered (bool)), SLOT (actionTriggered (void))); @@ -163,76 +163,76 @@ break; case uimenu::properties::ID_CHECKED: if (up.is_checked ()) - { - action->setCheckable (true); - action->setChecked (up.is_checked ()); - } + { + action->setCheckable (true); + action->setChecked (up.is_checked ()); + } else - { - action->setChecked (false); - action->setCheckable (false); - } + { + action->setChecked (false); + action->setCheckable (false); + } break; case uimenu::properties::ID_ENABLE: action->setEnabled (up.is_enable ()); break; case uimenu::properties::ID_ACCELERATOR: if (! action->menu ()) - action->setShortcut (accelSequence (up)); + action->setShortcut (accelSequence (up)); break; case uimenu::properties::ID_SEPARATOR: if (up.is_separator ()) - { - if (! m_separator) - { - m_separator = new QAction (action); - m_separator->setSeparator (true); - m_separator->setVisible (up.is_visible ()); - if (m_parent) - m_parent->insertAction (action, m_separator); - } - } + { + if (! m_separator) + { + m_separator = new QAction (action); + m_separator->setSeparator (true); + m_separator->setVisible (up.is_visible ()); + if (m_parent) + m_parent->insertAction (action, m_separator); + } + } else - { - if (m_separator) - delete m_separator; - m_separator = 0; - } + { + if (m_separator) + delete m_separator; + m_separator = 0; + } break; case uimenu::properties::ID_VISIBLE: action->setVisible (up.is_visible ()); if (m_separator) - m_separator->setVisible (up.is_visible ()); + m_separator->setVisible (up.is_visible ()); break; case uimenu::properties::ID_POSITION: if (m_separator) - m_parent->removeAction (m_separator); + m_parent->removeAction (m_separator); m_parent->removeAction (action); - { - int pos = static_cast (up.get_position ()); - QAction* before = 0; + { + int pos = static_cast (up.get_position ()); + QAction* before = 0; - if (pos > 0) - { - int count = 0; + if (pos > 0) + { + int count = 0; - foreach (QAction* a, m_parent->actions ()) - if (! a->isSeparator () && a->objectName () != "builtinMenu") - { - count++; - if (pos <= count) - { - before = a; - break; - } - } - } + foreach (QAction* a, m_parent->actions ()) + if (! a->isSeparator () && a->objectName () != "builtinMenu") + { + count++; + if (pos <= count) + { + before = a; + break; + } + } + } - if (m_separator) - m_parent->insertAction (before, m_separator); - m_parent->insertAction (before, action); - updateSiblingPositions (); - } + if (m_separator) + m_parent->insertAction (before, m_separator); + m_parent->insertAction (before, action); + updateSiblingPositions (); + } break; default: Object::update (pId); @@ -251,7 +251,7 @@ action->setMenu (_menu); action->setShortcut (QKeySequence ()); connect (_menu, SIGNAL (aboutToShow (void)), - this, SLOT (actionHovered (void))); + this, SLOT (actionHovered (void))); } return _menu; @@ -278,29 +278,29 @@ double count = 1.0; foreach (QAction* a, m_parent->actions ()) - { - if (! a->isSeparator () && a->objectName () != "builtinMenu") - { - Object* aObj = Object::fromQObject (a); + { + if (! a->isSeparator () && a->objectName () != "builtinMenu") + { + Object* aObj = Object::fromQObject (a); - if (aObj) - { - graphics_object go = aObj->object (); + if (aObj) + { + graphics_object go = aObj->object (); - // Probably overkill as a uimenu child can only be another - // uimenu object. - if (go.isa ("uimenu")) - { - uimenu::properties& up = Utils::properties (go); + // Probably overkill as a uimenu child can only be another + // uimenu object. + if (go.isa ("uimenu")) + { + uimenu::properties& up = Utils::properties (go); - up.get_property ("position").set - (octave_value (count), true, false); - } - } + up.get_property ("position").set + (octave_value (count), true, false); + } + } - count++; - } - } + count++; + } + } } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/MouseModeActionGroup.cc --- a/libgui/graphics/MouseModeActionGroup.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/MouseModeActionGroup.cc Sun May 25 10:29:05 2014 -0700 @@ -37,13 +37,13 @@ : QObject (parent), m_current (0) { m_actions.append (new QAction (QIcon (":/images/rotate.png"), - tr ("Rotate"), this)); + tr ("Rotate"), this)); m_actions.append (new QAction (QIcon (":/images/zoom.png"), - tr ("Zoom"), this)); + tr ("Zoom"), this)); m_actions.append (new QAction (QIcon (":/images/pan.png"), - tr ("Pan"), this)); + tr ("Pan"), this)); m_actions.append (new QAction (QIcon (":/images/select.png"), - tr ("Select"), this)); + tr ("Select"), this)); m_actions[2]->setEnabled (false); m_actions[3]->setEnabled (false); @@ -63,23 +63,23 @@ if (! checked) { if (sender () == m_current) - { - m_current = 0; - emit modeChanged (NoMode); - } + { + m_current = 0; + emit modeChanged (NoMode); + } } else { int i = m_actions.indexOf (qobject_cast (sender ())); if (i >= 0) - { - m_current = m_actions[i]; - for (int j = 0; j < m_actions.size (); j++) - if (j != i) - m_actions[j]->setChecked (false); - emit modeChanged (static_cast (i+1)); - } + { + m_current = m_actions[i]; + for (int j = 0; j < m_actions.size (); j++) + if (j != i) + m_actions[j]->setChecked (false); + emit modeChanged (static_cast (i+1)); + } } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Object.cc --- a/libgui/graphics/Object.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Object.cc Sun May 25 10:29:05 2014 -0700 @@ -40,8 +40,8 @@ if (! lock) qCritical ("QtHandles::Object::Object: " - "creating Object (h=%g) without a valid lock!!!", - m_handle.value ()); + "creating Object (h=%g) without a valid lock!!!", + m_handle.value ()); init (obj); } @@ -50,16 +50,16 @@ { if (m_qobject) qCritical ("QtHandles::Object::init: " - "resetting QObject while in invalid state"); + "resetting QObject while in invalid state"); m_qobject = obj; if (m_qobject) { m_qobject->setProperty ("QtHandles::Object", - qVariantFromValue (this)); + qVariantFromValue (this)); connect (m_qobject, SIGNAL (destroyed (QObject*)), - SLOT (objectDestroyed (QObject*))); + SLOT (objectDestroyed (QObject*))); } } @@ -73,8 +73,8 @@ if (! lock) qCritical ("QtHandles::Object::object: " - "accessing graphics object (h=%g) without a valid lock!!!", - m_handle.value ()); + "accessing graphics object (h=%g) without a valid lock!!!", + m_handle.value ()); return gh_manager::get_object (m_handle); } @@ -93,7 +93,7 @@ break; default: if (object ().valid_object ()) - update (pId); + update (pId); break; } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Object.h --- a/libgui/graphics/Object.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Object.h Sun May 25 10:29:05 2014 -0700 @@ -55,14 +55,14 @@ typename T::properties& properties (void) { return dynamic_cast - (object ().get_properties ()); + (object ().get_properties ()); } template const typename T::properties& properties (void) const { return dynamic_cast - (object ().get_properties ()); + (object ().get_properties ()); } graphics_object object (void) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ObjectFactory.cc --- a/libgui/graphics/ObjectFactory.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ObjectFactory.cc Sun May 25 10:29:05 2014 -0700 @@ -62,7 +62,7 @@ if (! s_instanceCreated) { if (QThread::currentThread () != QApplication::instance ()->thread ()) - s_instance.moveToThread (QApplication::instance ()->thread ()); + s_instance.moveToThread (QApplication::instance ()->thread ()); s_instanceCreated = true; } @@ -78,72 +78,72 @@ if (go.valid_object ()) { if (go.get_properties ().is_beingdeleted ()) - qWarning ("ObjectFactory::createObject: object is being deleted"); + qWarning ("ObjectFactory::createObject: object is being deleted"); else - { - ObjectProxy* proxy = Backend::toolkitObjectProxy (go); + { + ObjectProxy* proxy = Backend::toolkitObjectProxy (go); - if (proxy) - { - Logger::debug ("ObjectFactory::createObject: " - "create %s from thread %08x", - go.type ().c_str (), QThread::currentThreadId ()); + if (proxy) + { + Logger::debug ("ObjectFactory::createObject: " + "create %s from thread %08x", + go.type ().c_str (), QThread::currentThreadId ()); - Object* obj = 0; + Object* obj = 0; - if (go.isa ("figure")) - obj = Figure::create (go); - else if (go.isa ("uicontrol")) - { - uicontrol::properties& up = - Utils::properties (go); + if (go.isa ("figure")) + obj = Figure::create (go); + else if (go.isa ("uicontrol")) + { + uicontrol::properties& up = + Utils::properties (go); - if (up.style_is ("pushbutton")) - obj = PushButtonControl::create (go); - else if (up.style_is ("edit")) - obj = EditControl::create (go); - else if (up.style_is ("checkbox")) - obj = CheckBoxControl::create (go); - else if (up.style_is ("radiobutton")) - obj = RadioButtonControl::create (go); - else if (up.style_is ("togglebutton")) - obj = ToggleButtonControl::create (go); - else if (up.style_is ("text")) - obj = TextControl::create (go); - else if (up.style_is ("popupmenu")) - obj = PopupMenuControl::create (go); - else if (up.style_is ("slider")) - obj = SliderControl::create (go); - else if (up.style_is ("listbox")) - obj = ListBoxControl::create (go); - } - else if (go.isa ("uipanel")) - obj = Panel::create (go); - else if (go.isa ("uimenu")) - obj = Menu::create (go); - else if (go.isa ("uicontextmenu")) - obj = ContextMenu::create (go); - else if (go.isa ("uitoolbar")) - obj = ToolBar::create (go); - else if (go.isa ("uipushtool")) - obj = PushTool::create (go); - else if (go.isa ("uitoggletool")) - obj = ToggleTool::create (go); - else - qWarning ("ObjectFactory::createObject: unsupported type `%s'", - go.type ().c_str ()); + if (up.style_is ("pushbutton")) + obj = PushButtonControl::create (go); + else if (up.style_is ("edit")) + obj = EditControl::create (go); + else if (up.style_is ("checkbox")) + obj = CheckBoxControl::create (go); + else if (up.style_is ("radiobutton")) + obj = RadioButtonControl::create (go); + else if (up.style_is ("togglebutton")) + obj = ToggleButtonControl::create (go); + else if (up.style_is ("text")) + obj = TextControl::create (go); + else if (up.style_is ("popupmenu")) + obj = PopupMenuControl::create (go); + else if (up.style_is ("slider")) + obj = SliderControl::create (go); + else if (up.style_is ("listbox")) + obj = ListBoxControl::create (go); + } + else if (go.isa ("uipanel")) + obj = Panel::create (go); + else if (go.isa ("uimenu")) + obj = Menu::create (go); + else if (go.isa ("uicontextmenu")) + obj = ContextMenu::create (go); + else if (go.isa ("uitoolbar")) + obj = ToolBar::create (go); + else if (go.isa ("uipushtool")) + obj = PushTool::create (go); + else if (go.isa ("uitoggletool")) + obj = ToggleTool::create (go); + else + qWarning ("ObjectFactory::createObject: unsupported type `%s'", + go.type ().c_str ()); - if (obj) - proxy->setObject (obj); - } - else - qWarning ("ObjectFactory::createObject: no proxy for handle %g", - handle); - } + if (obj) + proxy->setObject (obj); + } + else + qWarning ("ObjectFactory::createObject: no proxy for handle %g", + handle); + } } else qWarning ("ObjectFactory::createObject: invalid object for handle %g", - handle); + handle); } }; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ObjectProxy.cc --- a/libgui/graphics/ObjectProxy.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ObjectProxy.cc Sun May 25 10:29:05 2014 -0700 @@ -43,26 +43,26 @@ if (obj != m_object) { if (m_object) - { - disconnect (this, SIGNAL (sendUpdate (int)), - m_object, SLOT (slotUpdate (int))); - disconnect (this, SIGNAL (sendFinalize (void)), - m_object, SLOT (slotFinalize (void))); - disconnect (this, SIGNAL (sendRedraw (void)), - m_object, SLOT (slotRedraw (void))); - } + { + disconnect (this, SIGNAL (sendUpdate (int)), + m_object, SLOT (slotUpdate (int))); + disconnect (this, SIGNAL (sendFinalize (void)), + m_object, SLOT (slotFinalize (void))); + disconnect (this, SIGNAL (sendRedraw (void)), + m_object, SLOT (slotRedraw (void))); + } m_object = obj; if (m_object) - { - connect (this, SIGNAL (sendUpdate (int)), - m_object, SLOT (slotUpdate (int))); - connect (this, SIGNAL (sendFinalize (void)), - m_object, SLOT (slotFinalize (void))); - connect (this, SIGNAL (sendRedraw (void)), - m_object, SLOT (slotRedraw (void))); - } + { + connect (this, SIGNAL (sendUpdate (int)), + m_object, SLOT (slotUpdate (int))); + connect (this, SIGNAL (sendFinalize (void)), + m_object, SLOT (slotFinalize (void))); + connect (this, SIGNAL (sendRedraw (void)), + m_object, SLOT (slotRedraw (void))); + } } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/Panel.cc --- a/libgui/graphics/Panel.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/Panel.cc Sun May 25 10:29:05 2014 -0700 @@ -58,13 +58,13 @@ static void setupPalette (const uipanel::properties& pp, QPalette& p) { p.setColor (QPalette::Window, - Utils::fromRgb (pp.get_backgroundcolor_rgb ())); + Utils::fromRgb (pp.get_backgroundcolor_rgb ())); p.setColor (QPalette::WindowText, - Utils::fromRgb (pp.get_foregroundcolor_rgb ())); + Utils::fromRgb (pp.get_foregroundcolor_rgb ())); p.setColor (QPalette::Light, - Utils::fromRgb (pp.get_highlightcolor_rgb ())); + Utils::fromRgb (pp.get_highlightcolor_rgb ())); p.setColor (QPalette::Dark, - Utils::fromRgb (pp.get_shadowcolor_rgb ())); + Utils::fromRgb (pp.get_shadowcolor_rgb ())); } static int borderWidthFromProperties (const uipanel::properties& pp) @@ -75,7 +75,7 @@ { bw = xround (pp.get_borderwidth ()); if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout")) - bw *= 2; + bw *= 2; } return bw; @@ -90,7 +90,7 @@ Container* container = parent->innerContainer (); if (container) - return new Panel (go, new QFrame (container)); + return new Panel (go, new QFrame (container)); } return 0; @@ -105,7 +105,7 @@ frame->setAutoFillBackground (true); Matrix bb = pp.get_boundingbox (false); frame->setGeometry (xround (bb(0)), xround (bb(1)), - xround (bb(2)), xround (bb(3))); + xround (bb(2)), xround (bb(3))); frame->setFrameStyle (frameStyleFromProperties (pp)); frame->setLineWidth (xround (pp.get_borderwidth ())); QPalette pal = frame->palette (); @@ -149,66 +149,66 @@ if (! m_blockUpdates) { if (watched == qObject ()) - { - switch (event->type ()) - { - case QEvent::Resize: - { - gh_manager::auto_lock lock; - graphics_object go = object (); + { + switch (event->type ()) + { + case QEvent::Resize: + { + gh_manager::auto_lock lock; + graphics_object go = object (); - if (go.valid_object ()) - { - if (m_title) - { - const uipanel::properties& pp = - Utils::properties (go); + if (go.valid_object ()) + { + if (m_title) + { + const uipanel::properties& pp = + Utils::properties (go); - if (pp.fontunits_is ("normalized")) - { - QFrame* frame = qWidget (); + if (pp.fontunits_is ("normalized")) + { + QFrame* frame = qWidget (); - m_title->setFont (Utils::computeFont - (pp, frame->height ())); - m_title->resize (m_title->sizeHint ()); - } - } - updateLayout (); - } - } - break; - case QEvent::MouseButtonPress: - { - QMouseEvent* m = dynamic_cast (event); + m_title->setFont (Utils::computeFont + (pp, frame->height ())); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } + } + break; + case QEvent::MouseButtonPress: + { + QMouseEvent* m = dynamic_cast (event); - if (m->button () == Qt::RightButton) - { - gh_manager::auto_lock lock; + if (m->button () == Qt::RightButton) + { + gh_manager::auto_lock lock; - ContextMenu::executeAt (properties (), m->globalPos ()); - } - } - break; - default: - break; - } - } + ContextMenu::executeAt (properties (), m->globalPos ()); + } + } + break; + default: + break; + } + } else if (watched == m_container) - { - switch (event->type ()) - { - case QEvent::Resize: - if (qWidget ()->isVisible ()) - { - gh_manager::auto_lock lock; + { + switch (event->type ()) + { + case QEvent::Resize: + if (qWidget ()->isVisible ()) + { + gh_manager::auto_lock lock; - properties ().update_boundingbox (); - } - break; - default: - break; - } - } + properties ().update_boundingbox (); + } + break; + default: + break; + } + } } return false; @@ -224,13 +224,13 @@ switch (pId) { case uipanel::properties::ID_POSITION: - { - Matrix bb = pp.get_boundingbox (false); + { + Matrix bb = pp.get_boundingbox (false); - frame->setGeometry (xround (bb(0)), xround (bb(1)), - xround (bb(2)), xround (bb(3))); - updateLayout (); - } + frame->setGeometry (xround (bb(0)), xround (bb(1)), + xround (bb(2)), xround (bb(3))); + updateLayout (); + } break; case uipanel::properties::ID_BORDERWIDTH: frame->setLineWidth (xround (pp.get_borderwidth ())); @@ -240,46 +240,46 @@ case uipanel::properties::ID_FOREGROUNDCOLOR: case uipanel::properties::ID_HIGHLIGHTCOLOR: case uipanel::properties::ID_SHADOWCOLOR: - { - QPalette pal = frame->palette (); + { + QPalette pal = frame->palette (); - setupPalette (pp, pal); - frame->setPalette (pal); - if (m_title) - m_title->setPalette (pal); - } + setupPalette (pp, pal); + frame->setPalette (pal); + if (m_title) + m_title->setPalette (pal); + } break; case uipanel::properties::ID_TITLE: - { - QString title = Utils::fromStdString (pp.get_title ()); + { + QString title = Utils::fromStdString (pp.get_title ()); - if (title.isEmpty ()) - { - if (m_title) - delete m_title; - m_title = 0; - } - else - { - if (! m_title) - { - QPalette pal = frame->palette (); + if (title.isEmpty ()) + { + if (m_title) + delete m_title; + m_title = 0; + } + else + { + if (! m_title) + { + QPalette pal = frame->palette (); - m_title = new QLabel (title, frame); - m_title->setAutoFillBackground (true); - m_title->setContentsMargins (4, 0, 4, 0); - m_title->setPalette (pal); - m_title->setFont (Utils::computeFont (pp)); - m_title->show (); - } - else - { - m_title->setText (title); - m_title->resize (m_title->sizeHint ()); - } - } - updateLayout (); - } + m_title = new QLabel (title, frame); + m_title->setAutoFillBackground (true); + m_title->setContentsMargins (4, 0, 4, 0); + m_title->setPalette (pal); + m_title->setFont (Utils::computeFont (pp)); + m_title->show (); + } + else + { + m_title->setText (title); + m_title->resize (m_title->sizeHint ()); + } + } + updateLayout (); + } case uipanel::properties::ID_TITLEPOSITION: updateLayout (); break; @@ -292,11 +292,11 @@ case uipanel::properties::ID_FONTWEIGHT: case uipanel::properties::ID_FONTANGLE: if (m_title) - { - m_title->setFont (Utils::computeFont (pp)); - m_title->resize (m_title->sizeHint ()); - updateLayout (); - } + { + m_title->setFont (Utils::computeFont (pp)); + m_title->resize (m_title->sizeHint ()); + updateLayout (); + } break; case uipanel::properties::ID_VISIBLE: frame->setVisible (pp.is_visible ()); @@ -326,9 +326,9 @@ int bw = borderWidthFromProperties (pp); frame->setFrameRect (QRect (xround (bb(0)) - bw, xround (bb(1)) - bw, - xround (bb(2)) + 2*bw, xround (bb(3)) + 2*bw)); + xround (bb(2)) + 2*bw, xround (bb(3)) + 2*bw)); m_container->setGeometry (xround (bb(0)), xround (bb(1)), - xround (bb(2)), xround (bb(3))); + xround (bb(2)), xround (bb(3))); if (m_blockUpdates) pp.update_boundingbox (); @@ -339,19 +339,19 @@ int offset = 5; if (pp.titleposition_is ("lefttop")) - m_title->move (bw+offset, 0); + m_title->move (bw+offset, 0); else if (pp.titleposition_is ("righttop")) - m_title->move (frame->width () - bw - offset - sz.width (), 0); + m_title->move (frame->width () - bw - offset - sz.width (), 0); else if (pp.titleposition_is ("leftbottom")) - m_title->move (bw+offset, frame->height () - sz.height ()); + m_title->move (bw+offset, frame->height () - sz.height ()); else if (pp.titleposition_is ("rightbottom")) - m_title->move (frame->width () - bw - offset - sz.width (), - frame->height () - sz.height ()); + m_title->move (frame->width () - bw - offset - sz.width (), + frame->height () - sz.height ()); else if (pp.titleposition_is ("centertop")) - m_title->move (frame->width () / 2 - sz.width () / 2, 0); + m_title->move (frame->width () / 2 - sz.width () / 2, 0); else if (pp.titleposition_is ("centerbottom")) - m_title->move (frame->width () / 2 - sz.width () / 2, - frame->height () - sz.height ()); + m_title->move (frame->width () / 2 - sz.width () / 2, + frame->height () - sz.height ()); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/PopupMenuControl.cc --- a/libgui/graphics/PopupMenuControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/PopupMenuControl.cc Sun May 25 10:29:05 2014 -0700 @@ -42,7 +42,7 @@ Container* container = parent->innerContainer (); if (container) - return new PopupMenuControl (go, new QComboBox (container)); + return new PopupMenuControl (go, new QComboBox (container)); } return 0; @@ -56,7 +56,7 @@ box->addItems (Utils::fromStdString (up.get_string_string ()).split ('|')); connect (box, SIGNAL (currentIndexChanged (int)), - SLOT (currentIndexChanged (int))); + SLOT (currentIndexChanged (int))); } PopupMenuControl::~PopupMenuControl (void) @@ -72,43 +72,43 @@ { case uicontrol::properties::ID_STRING: m_blockUpdate = true; - { - int oldCurrent = box->currentIndex (); + { + int oldCurrent = box->currentIndex (); - box->clear (); - box->addItems (Utils::fromStdString - (up.get_string_string ()).split ('|')); - if (box->count() > 0 - && oldCurrent >= 0 - && oldCurrent < box->count ()) - { - box->setCurrentIndex (oldCurrent); - } - else - { - gh_manager::post_set (m_handle, "value", - octave_value (box->count () > 0 - ? 1.0 : 0.0), - false); - } - } + box->clear (); + box->addItems (Utils::fromStdString + (up.get_string_string ()).split ('|')); + if (box->count() > 0 + && oldCurrent >= 0 + && oldCurrent < box->count ()) + { + box->setCurrentIndex (oldCurrent); + } + else + { + gh_manager::post_set (m_handle, "value", + octave_value (box->count () > 0 + ? 1.0 : 0.0), + false); + } + } m_blockUpdate = false; break; case uicontrol::properties::ID_VALUE: - { - Matrix value = up.get_value ().matrix_value (); + { + Matrix value = up.get_value ().matrix_value (); - if (value.numel () > 0) - { - int newIndex = int (value(0)) - 1; + if (value.numel () > 0) + { + int newIndex = int (value(0)) - 1; - if (newIndex >= 0 && newIndex < box->count () - && newIndex != box->currentIndex ()) - { - box->setCurrentIndex (newIndex); - } - } - } + if (newIndex >= 0 && newIndex < box->count () + && newIndex != box->currentIndex ()) + { + box->setCurrentIndex (newIndex); + } + } + } break; default: BaseControl::update (pId); @@ -121,8 +121,8 @@ if (! m_blockUpdate) { gh_manager::post_set (m_handle, "value", - octave_value (double (index + 1)), - false); + octave_value (double (index + 1)), + false); gh_manager::post_callback (m_handle, "callback"); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/PushButtonControl.cc --- a/libgui/graphics/PushButtonControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/PushButtonControl.cc Sun May 25 10:29:05 2014 -0700 @@ -43,7 +43,7 @@ Container* container = parent->innerContainer (); if (container) - return new PushButtonControl (go, new QPushButton (container)); + return new PushButtonControl (go, new QPushButton (container)); } return 0; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/PushTool.cc --- a/libgui/graphics/PushTool.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/PushTool.cc Sun May 25 10:29:05 2014 -0700 @@ -40,7 +40,7 @@ QWidget* parentWidget = parent->qWidget (); if (parentWidget) - return new PushTool (go, new QAction (parentWidget)); + return new PushTool (go, new QAction (parentWidget)); } return 0; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/QtHandlesUtils.cc --- a/libgui/graphics/QtHandlesUtils.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/QtHandlesUtils.cc Sun May 25 10:29:05 2014 -0700 @@ -108,9 +108,9 @@ } template QFont computeFont (const uicontrol::properties& props, - int height); + int height); template QFont computeFont (const uipanel::properties& props, - int height); + int height); QColor fromRgb (const Matrix& rgb) { @@ -142,26 +142,26 @@ Qt::KeyboardModifiers mods = event->modifiers (); if (mods == Qt::NoModifier) - { - if (buttons == Qt::LeftButton) - return std::string ("normal"); - else if (buttons == Qt::RightButton) - return std::string ("alt"); + { + if (buttons == Qt::LeftButton) + return std::string ("normal"); + else if (buttons == Qt::RightButton) + return std::string ("alt"); #if defined (Q_WS_WIN) - else if (buttons == (Qt::LeftButton|Qt::RightButton)) - return std::string ("extend"); + else if (buttons == (Qt::LeftButton|Qt::RightButton)) + return std::string ("extend"); #elif defined (Q_WS_X11) - else if (buttons == Qt::MidButton) - return std::string ("extend"); + else if (buttons == Qt::MidButton) + return std::string ("extend"); #endif - } + } else if (buttons == Qt::LeftButton) - { - if (mods == Qt::ShiftModifier) - return std::string ("extend"); - else if (mods == Qt::ControlModifier) - return std::string ("alt"); - } + { + if (mods == Qt::ShiftModifier) + return std::string ("extend"); + else if (mods == Qt::ControlModifier) + return std::string ("alt"); + } } return std::string ("normal"); @@ -176,20 +176,20 @@ Container* c = tkFig->innerContainer (); if (c) - { - QPoint qp = c->mapFromGlobal (event->globalPos ()); + { + QPoint qp = c->mapFromGlobal (event->globalPos ()); - return - tkFig->properties
().map_from_boundingbox (qp.x (), - qp.y ()); - } + return + tkFig->properties
().map_from_boundingbox (qp.x (), + qp.y ()); + } } return Matrix (1, 2, 0.0); } Qt::Alignment fromHVAlign (const caseless_str& halign, - const caseless_str& valign) + const caseless_str& valign) { Qt::Alignment flags; @@ -230,58 +230,58 @@ img.fill (qRgba (0, 0, 0, 0)); if (v.is_uint8_type ()) - { - uint8NDArray d = v.uint8_array_value (); + { + uint8NDArray d = v.uint8_array_value (); - for (int i = 0; i < w; i++) - for (int j = 0; j < h; j++) - { - int r = d(j, i, 0); - int g = d(j, i, 1); - int b = d(j, i, 2); - int a = 255; + for (int i = 0; i < w; i++) + for (int j = 0; j < h; j++) + { + int r = d(j, i, 0); + int g = d(j, i, 1); + int b = d(j, i, 2); + int a = 255; - img.setPixel (x_off + i, y_off + j, qRgba (r, g, b, a)); - } - } + img.setPixel (x_off + i, y_off + j, qRgba (r, g, b, a)); + } + } else if (v.is_single_type ()) - { - FloatNDArray f = v.float_array_value (); + { + FloatNDArray f = v.float_array_value (); - for (int i = 0; i < w; i++) - for (int j = 0; j < h; j++) - { - float r = f(j, i, 0); - float g = f(j, i, 1); - float b = f(j, i, 2); - int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255); + for (int i = 0; i < w; i++) + for (int j = 0; j < h; j++) + { + float r = f(j, i, 0); + float g = f(j, i, 1); + float b = f(j, i, 2); + int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255); - img.setPixel (x_off + i, y_off + j, - qRgba (xround (r * 255), - xround (g * 255), - xround (b * 255), - a)); - } - } + img.setPixel (x_off + i, y_off + j, + qRgba (xround (r * 255), + xround (g * 255), + xround (b * 255), + a)); + } + } else if (v.is_real_type ()) - { - NDArray d = v.array_value (); + { + NDArray d = v.array_value (); - for (int i = 0; i < w; i++) - for (int j = 0; j < h; j++) - { - double r = d(j, i, 0); - double g = d(j, i, 1); - double b = d(j, i, 2); - int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255); + for (int i = 0; i < w; i++) + for (int j = 0; j < h; j++) + { + double r = d(j, i, 0); + double g = d(j, i, 1); + double b = d(j, i, 2); + int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255); - img.setPixel (x_off + i, y_off + j, - qRgba (xround (r * 255), - xround (g * 255), - xround (b * 255), - a)); - } - } + img.setPixel (x_off + i, y_off + j, + qRgba (xround (r * 255), + xround (g * 255), + xround (b * 255), + a)); + } + } return img; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/QtHandlesUtils.h --- a/libgui/graphics/QtHandlesUtils.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/QtHandlesUtils.h Sun May 25 10:29:05 2014 -0700 @@ -54,10 +54,10 @@ Matrix toRgb (const QColor& c); Qt::Alignment fromHVAlign (const caseless_str& halign, - const caseless_str& valign); + const caseless_str& valign); std::string figureSelectionType (QMouseEvent* event, - bool isDoubleClick = false); + bool isDoubleClick = false); Matrix figureCurrentPoint (const graphics_object& fig, QMouseEvent* event); @@ -72,7 +72,7 @@ { return Utils::properties (gh_manager::get_object (h)); } QImage makeImageFromCData (const octave_value& v, int width = -1, - int height = -1); + int height = -1); octave_scalar_map makeKeyEventStruct (QKeyEvent* event); }; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/RadioButtonControl.cc --- a/libgui/graphics/RadioButtonControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/RadioButtonControl.cc Sun May 25 10:29:05 2014 -0700 @@ -42,14 +42,14 @@ Container* container = parent->innerContainer (); if (container) - return new RadioButtonControl (go, new QRadioButton (container)); + return new RadioButtonControl (go, new QRadioButton (container)); } return 0; } RadioButtonControl::RadioButtonControl (const graphics_object& go, - QRadioButton* radio) + QRadioButton* radio) : ButtonControl (go, radio) { radio->setAutoFillBackground (true); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/SliderControl.cc --- a/libgui/graphics/SliderControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/SliderControl.cc Sun May 25 10:29:05 2014 -0700 @@ -44,14 +44,14 @@ Container* container = parent->innerContainer (); if (container) - return new SliderControl (go, new QScrollBar (container)); + return new SliderControl (go, new QScrollBar (container)); } return 0; } SliderControl::SliderControl (const graphics_object& go, - QAbstractSlider* slider) + QAbstractSlider* slider) : BaseControl (go, slider), m_blockUpdates (false) { uicontrol::properties& up = properties (); @@ -70,7 +70,7 @@ double dmin = up.get_min (), dmax = up.get_max (); slider->setValue (xround (((value(0) - dmin) / (dmax - dmin)) - * RANGE_INT_MAX)); + * RANGE_INT_MAX)); } connect (slider, SIGNAL (valueChanged (int)), SLOT (valueChanged (int))); @@ -88,28 +88,28 @@ switch (pId) { case uicontrol::properties::ID_SLIDERSTEP: - { - Matrix steps = up.get_sliderstep ().matrix_value (); + { + Matrix steps = up.get_sliderstep ().matrix_value (); - slider->setSingleStep (xround (steps(0) * RANGE_INT_MAX)); - slider->setPageStep (xround (steps(1) * RANGE_INT_MAX)); - } + slider->setSingleStep (xround (steps(0) * RANGE_INT_MAX)); + slider->setPageStep (xround (steps(1) * RANGE_INT_MAX)); + } break; case uicontrol::properties::ID_VALUE: - { - Matrix value = up.get_value ().matrix_value (); - double dmax = up.get_max (), dmin = up.get_min (); + { + Matrix value = up.get_value ().matrix_value (); + double dmax = up.get_max (), dmin = up.get_min (); - if (value.numel () > 0) - { - int ival = xround (((value(0) - dmin) / (dmax - dmin)) - * RANGE_INT_MAX); + if (value.numel () > 0) + { + int ival = xround (((value(0) - dmin) / (dmax - dmin)) + * RANGE_INT_MAX); - m_blockUpdates = true; - slider->setValue (ival); - m_blockUpdates = false; - } - } + m_blockUpdates = true; + slider->setValue (ival); + m_blockUpdates = false; + } + } break; default: BaseControl::update (pId); @@ -125,25 +125,25 @@ graphics_object go = object (); if (go.valid_object ()) - { - uicontrol::properties& up = Utils::properties (go); + { + uicontrol::properties& up = Utils::properties (go); - Matrix value = up.get_value ().matrix_value (); - double dmin = up.get_min (), dmax = up.get_max (); + Matrix value = up.get_value ().matrix_value (); + double dmin = up.get_min (), dmax = up.get_max (); - int ival_tmp = (value.numel () > 0 ? - xround (((value(0) - dmin) / (dmax - dmin)) - * RANGE_INT_MAX) : - 0); + int ival_tmp = (value.numel () > 0 ? + xround (((value(0) - dmin) / (dmax - dmin)) + * RANGE_INT_MAX) : + 0); - if (ival != ival_tmp || value.numel () > 0) - { - double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX); + if (ival != ival_tmp || value.numel () > 0) + { + double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX); - gh_manager::post_set (m_handle, "value", octave_value (dval)); - gh_manager::post_callback (m_handle, "callback"); - } - } + gh_manager::post_set (m_handle, "value", octave_value (dval)); + gh_manager::post_callback (m_handle, "callback"); + } + } } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/TextControl.cc --- a/libgui/graphics/TextControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/TextControl.cc Sun May 25 10:29:05 2014 -0700 @@ -42,7 +42,7 @@ Container* container = parent->innerContainer (); if (container) - return new TextControl (go, new QLabel (container)); + return new TextControl (go, new QLabel (container)); } return 0; @@ -57,7 +57,7 @@ label->setTextFormat (Qt::PlainText); label->setWordWrap (false); label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); + up.get_verticalalignment ())); // FIXME: support string_vector label->setText (Utils::fromStdString (up.get_string_string ())); } @@ -80,7 +80,7 @@ case uicontrol::properties::ID_HORIZONTALALIGNMENT: case uicontrol::properties::ID_VERTICALALIGNMENT: label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (), - up.get_verticalalignment ())); + up.get_verticalalignment ())); break; default: BaseControl::update (pId); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ToggleButtonControl.cc --- a/libgui/graphics/ToggleButtonControl.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ToggleButtonControl.cc Sun May 25 10:29:05 2014 -0700 @@ -42,14 +42,14 @@ Container* container = parent->innerContainer (); if (container) - return new ToggleButtonControl (go, new QPushButton (container)); + return new ToggleButtonControl (go, new QPushButton (container)); } return 0; } ToggleButtonControl::ToggleButtonControl (const graphics_object& go, - QPushButton* btn) + QPushButton* btn) : ButtonControl (go, btn) { btn->setCheckable (true); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ToggleTool.cc --- a/libgui/graphics/ToggleTool.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ToggleTool.cc Sun May 25 10:29:05 2014 -0700 @@ -40,7 +40,7 @@ QWidget* parentWidget = parent->qWidget (); if (parentWidget) - return new ToggleTool (go, new QAction (parentWidget)); + return new ToggleTool (go, new QAction (parentWidget)); } return 0; @@ -55,7 +55,7 @@ action->setChecked (tp.is_state ()); connect (action, SIGNAL (toggled (bool)), - this, SLOT (triggered (bool))); + this, SLOT (triggered (bool))); } ToggleTool::~ToggleTool (void) @@ -82,9 +82,9 @@ { gh_manager::post_set (m_handle, "state", checked, false); gh_manager::post_callback (m_handle, - checked - ? "oncallback" - : "offcallback"); + checked + ? "oncallback" + : "offcallback"); gh_manager::post_callback (m_handle, "clickedcallback"); } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ToolBar.cc --- a/libgui/graphics/ToolBar.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ToolBar.cc Sun May 25 10:29:05 2014 -0700 @@ -71,7 +71,7 @@ QWidget* parentWidget = parent->qWidget (); if (parentWidget) - return new ToolBar (go, new QToolBar (parentWidget)); + return new ToolBar (go, new QToolBar (parentWidget)); } return 0; @@ -110,7 +110,7 @@ { case base_properties::ID_VISIBLE: if (m_figure) - m_figure->showCustomToolBar (bar, tp.is_visible ()); + m_figure->showCustomToolBar (bar, tp.is_visible ()); break; default: Object::update (pId); @@ -123,31 +123,31 @@ if (watched == qObject ()) { switch (event->type ()) - { - case QEvent::ActionAdded: - case QEvent::ActionRemoved: - { - QActionEvent* ae = dynamic_cast (event); - QToolBar* bar = qWidget (); + { + case QEvent::ActionAdded: + case QEvent::ActionRemoved: + { + QActionEvent* ae = dynamic_cast (event); + QToolBar* bar = qWidget (); - if (ae->action () != m_empty) - { - if (event->type () == QEvent::ActionAdded) - { - if (bar->actions ().size () == 2) - QTimer::singleShot (0, this, SLOT (hideEmpty (void))); - } - else - { - if (bar->actions ().size () == 1) - m_empty->setVisible (true); - } - } - } - break; - default: - break; - } + if (ae->action () != m_empty) + { + if (event->type () == QEvent::ActionAdded) + { + if (bar->actions ().size () == 2) + QTimer::singleShot (0, this, SLOT (hideEmpty (void))); + } + else + { + if (bar->actions ().size () == 1) + m_empty->setVisible (true); + } + } + } + break; + default: + break; + } } return false; @@ -165,7 +165,7 @@ QToolBar* bar = qWidget (); if (bar) - m_figure->showCustomToolBar (bar, false); + m_figure->showCustomToolBar (bar, false); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/ToolBarButton.cc --- a/libgui/graphics/ToolBarButton.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/ToolBarButton.cc Sun May 25 10:29:05 2014 -0700 @@ -74,38 +74,38 @@ case base_properties::ID_VISIBLE: action->setVisible (tp.is_visible ()); if (m_separator) - m_separator->setVisible (tp.is_visible ()); + m_separator->setVisible (tp.is_visible ()); break; case T::properties::ID_TOOLTIPSTRING: action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ())); break; case T::properties::ID_CDATA: - { - QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16); + { + QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16); - action->setIcon (QIcon (QPixmap::fromImage (img))); - } + action->setIcon (QIcon (QPixmap::fromImage (img))); + } break; case T::properties::ID_SEPARATOR: if (tp.is_separator ()) - { - if (! m_separator) - { - m_separator = new QAction (action); - m_separator->setSeparator (true); - m_separator->setVisible (tp.is_visible ()); + { + if (! m_separator) + { + m_separator = new QAction (action); + m_separator->setSeparator (true); + m_separator->setVisible (tp.is_visible ()); - QWidget* w = qobject_cast (action->parent ()); + QWidget* w = qobject_cast (action->parent ()); - w->insertAction (action, m_separator); - } - } + w->insertAction (action, m_separator); + } + } else - { - if (m_separator) - delete m_separator; - m_separator = 0; - } + { + if (m_separator) + delete m_separator; + m_separator = 0; + } break; case T::properties::ID_ENABLE: action->setEnabled (tp.is_enable ()); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/graphics/__init_qt__.cc --- a/libgui/graphics/__init_qt__.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/graphics/__init_qt__.cc Sun May 25 10:29:05 2014 -0700 @@ -48,45 +48,45 @@ if (! qtHandlesInitialized) { if (qApp) - { - qRegisterMetaType ("graphics_object"); + { + qRegisterMetaType ("graphics_object"); - gh_manager::enable_event_processing (true); + gh_manager::enable_event_processing (true); - graphics_toolkit tk (new Backend ()); + graphics_toolkit tk (new Backend ()); gtk_manager::load_toolkit (tk); - octave_add_atexit_function ("__shutdown_qt__"); + octave_add_atexit_function ("__shutdown_qt__"); - // Change some default settings to use Qt default colors - QPalette p; - graphics_object root = gh_manager::get_object (0); + // Change some default settings to use Qt default colors + QPalette p; + graphics_object root = gh_manager::get_object (0); - /* - root.set ("defaultfigurecolor", - octave_value (Utils::toRgb (p.color (QPalette::Window)))); - */ - root.set ("defaultuicontrolbackgroundcolor", - octave_value (Utils::toRgb (p.color (QPalette::Window)))); - root.set ("defaultuicontrolforegroundcolor", - octave_value (Utils::toRgb - (p.color (QPalette::WindowText)))); - root.set ("defaultuipanelbackgroundcolor", - octave_value (Utils::toRgb (p.color (QPalette::Window)))); - root.set ("defaultuipanelforegroundcolor", - octave_value (Utils::toRgb - (p.color (QPalette::WindowText)))); - root.set ("defaultuipanelhighlightcolor", - octave_value (Utils::toRgb (p.color (QPalette::Light)))); - root.set ("defaultuipanelshadowcolor", - octave_value (Utils::toRgb (p.color (QPalette::Dark)))); + /* + root.set ("defaultfigurecolor", + octave_value (Utils::toRgb (p.color (QPalette::Window)))); + */ + root.set ("defaultuicontrolbackgroundcolor", + octave_value (Utils::toRgb (p.color (QPalette::Window)))); + root.set ("defaultuicontrolforegroundcolor", + octave_value (Utils::toRgb + (p.color (QPalette::WindowText)))); + root.set ("defaultuipanelbackgroundcolor", + octave_value (Utils::toRgb (p.color (QPalette::Window)))); + root.set ("defaultuipanelforegroundcolor", + octave_value (Utils::toRgb + (p.color (QPalette::WindowText)))); + root.set ("defaultuipanelhighlightcolor", + octave_value (Utils::toRgb (p.color (QPalette::Light)))); + root.set ("defaultuipanelshadowcolor", + octave_value (Utils::toRgb (p.color (QPalette::Dark)))); - qtHandlesInitialized = true; + qtHandlesInitialized = true; - return true; - } + return true; + } else - error ("__init_qt__: QApplication object must exist."); + error ("__init_qt__: QApplication object must exist."); } return false; @@ -213,45 +213,45 @@ QString filter; QStringList files = QFileDialog::getOpenFileNames (0, caption, defaultFileName, - filterSpecs.join (";;"), &filter, 0); + filterSpecs.join (";;"), &filter, 0); if (! files.isEmpty ()) - { - Cell cFiles (1, files.length ()); - QString dirName; - int i = 0; + { + Cell cFiles (1, files.length ()); + QString dirName; + int i = 0; - foreach (const QString& s, files) - { - QFileInfo fi (s); + foreach (const QString& s, files) + { + QFileInfo fi (s); - if (dirName.isEmpty ()) - dirName = appendDirSep (fi.canonicalPath ()); - cFiles(i++) = toStdString (fi.fileName ()); - } + if (dirName.isEmpty ()) + dirName = appendDirSep (fi.canonicalPath ()); + cFiles(i++) = toStdString (fi.fileName ()); + } - retval(0) = cFiles; - retval(1) = toStdString (dirName); - if (! filter.isEmpty ()) - retval(2) = static_cast (filterSpecs.indexOf (filter) + 1); - } + retval(0) = cFiles; + retval(1) = toStdString (dirName); + if (! filter.isEmpty ()) + retval(2) = static_cast (filterSpecs.indexOf (filter) + 1); + } } else { QString filter; QString fileName = QFileDialog::getOpenFileName (0, caption, defaultFileName, - filterSpecs.join (";;"), &filter, 0); + filterSpecs.join (";;"), &filter, 0); if (! fileName.isNull ()) - { - QFileInfo fi (fileName); + { + QFileInfo fi (fileName); - retval(0) = toStdString (fi.fileName ()); - retval(1) = toStdString (appendDirSep (fi.canonicalPath ())); - if (! filter.isEmpty ()) - retval(2) = static_cast (filterSpecs.indexOf (filter) + 1); - } + retval(0) = toStdString (fi.fileName ()); + retval(1) = toStdString (appendDirSep (fi.canonicalPath ())); + if (! filter.isEmpty ()) + retval(2) = static_cast (filterSpecs.indexOf (filter) + 1); + } } return retval; @@ -289,7 +289,7 @@ QString filter; QString fileName = QFileDialog::getSaveFileName (0, caption, defaultFileName, - filterSpecs.join (";;"), &filter, 0); + filterSpecs.join (";;"), &filter, 0); if (! fileName.isNull ()) { @@ -297,11 +297,11 @@ retval(0) = toStdString (fi.fileName ()); if (fi.exists ()) - retval(1) = toStdString (appendDirSep (fi.canonicalPath ())); + retval(1) = toStdString (appendDirSep (fi.canonicalPath ())); else - retval(1) = toStdString (appendDirSep (fi.absolutePath ())); + retval(1) = toStdString (appendDirSep (fi.absolutePath ())); if (! filter.isEmpty ()) - retval(2) = static_cast (filterSpecs.indexOf (filter) + 1); + retval(2) = static_cast (filterSpecs.indexOf (filter) + 1); } return retval; @@ -321,7 +321,7 @@ QString defaultDirectory = fromStdString (args(0).string_value ()); QString dirName = QFileDialog::getExistingDirectory (0, caption, - defaultDirectory); + defaultDirectory); if (! dirName.isNull ()) retval = toStdString (dirName); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/languages/pt_BR.ts diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/QTerminal.cc --- a/libgui/qterminal/libqterminal/QTerminal.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/QTerminal.cc Sun May 25 10:29:05 2014 -0700 @@ -118,5 +118,5 @@ (cursorUseForegroundColor, settings->value ("terminal/color_c", QVariant (colors.at (3))).value ()); - setScrollBufferSize (settings->value ("terminal/history_buffer",1000).toInt() ); + setScrollBufferSize (settings->value ("terminal/history_buffer",1000).toInt () ); } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp --- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp Sun May 25 10:29:05 2014 -0700 @@ -1,5 +1,5 @@ /* Copyright (C) 2008 e_k (e_k@users.sourceforge.net) - Copyright (C) 2012-2013 Jacob Dawid + Copyright (C) 2012-2013 Jacob Dawid This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h --- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h Sun May 25 10:29:05 2014 -0700 @@ -1,5 +1,5 @@ /* Copyright (C) 2008 e_k (e_k@users.sourceforge.net) - Copyright (C) 2012-2013 Jacob Dawid + Copyright (C) 2012-2013 Jacob Dawid This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/SelfListener.cpp --- a/libgui/qterminal/libqterminal/unix/SelfListener.cpp Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/SelfListener.cpp Sun May 25 10:29:05 2014 -0700 @@ -1,5 +1,5 @@ /* qterminal - a terminal widget for Qt - * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@googlemail.com) + * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/SelfListener.h --- a/libgui/qterminal/libqterminal/unix/SelfListener.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/SelfListener.h Sun May 25 10:29:05 2014 -0700 @@ -1,5 +1,5 @@ /* qterminal - a terminal widget for Qt - * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@googlemail.com) + * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/TerminalModel.cpp --- a/libgui/qterminal/libqterminal/unix/TerminalModel.cpp Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/TerminalModel.cpp Sun May 25 10:29:05 2014 -0700 @@ -5,7 +5,7 @@ Copyright (C) 1997,1998 by Lars Doelle Rewritten for QT4 by e_k , Copyright (C)2008 - Copyright (C) 2012-2013 Jacob Dawid + Copyright (C) 2012-2013 Jacob Dawid This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/TerminalModel.h --- a/libgui/qterminal/libqterminal/unix/TerminalModel.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/TerminalModel.h Sun May 25 10:29:05 2014 -0700 @@ -5,7 +5,7 @@ Copyright (C) 1997,1998 by Lars Doelle Rewritten for QT4 by e_k , Copyright (C)2008 - Copyright (C) 2012-2013 Jacob Dawid + Copyright (C) 2012-2013 Jacob Dawid This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/TerminalView.cpp --- a/libgui/qterminal/libqterminal/unix/TerminalView.cpp Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/TerminalView.cpp Sun May 25 10:29:05 2014 -0700 @@ -5,7 +5,7 @@ Copyright (C) 1997,1998 by Lars Doelle Rewritten for QT4 by e_k , Copyright (C)2008 - Copyright (C) 2012-2013 Jacob Dawid + Copyright (C) 2012-2013 Jacob Dawid This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/qterminal/libqterminal/unix/TerminalView.h --- a/libgui/qterminal/libqterminal/unix/TerminalView.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/qterminal/libqterminal/unix/TerminalView.h Sun May 25 10:29:05 2014 -0700 @@ -3,7 +3,7 @@ Copyright (C) 1997,1998 by Lars Doelle Rewritten for QT4 by e_k , Copyright (C)2008 - Copyright (C) 2012-2013 Jacob Dawid + Copyright (C) 2012-2013 Jacob Dawid This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/files-dock-widget.cc --- a/libgui/src/files-dock-widget.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/files-dock-widget.cc Sun May 25 10:29:05 2014 -0700 @@ -551,7 +551,7 @@ QItemSelectionModel *m = _file_tree_view->selectionModel (); QModelIndexList rows = m->selectedRows (); - for ( QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++) + for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++) { QFileInfo file = _file_system_model->fileInfo (*it); if (file.exists ()) @@ -661,7 +661,7 @@ QItemSelectionModel *m = _file_tree_view->selectionModel (); QModelIndexList rows = m->selectedRows (); - for ( QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++) + for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++) { QModelIndex index = *it; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/find-files-model.cc --- a/libgui/src/find-files-model.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/find-files-model.cc Sun May 25 10:29:05 2014 -0700 @@ -101,7 +101,7 @@ void find_files_model::addFile (const QFileInfo &info) { - beginInsertRows (QModelIndex (), _files.size (), _files.size () ); + beginInsertRows (QModelIndex (), _files.size (), _files.size ()); QList::Iterator it; find_file_less_than less_than (_sortorder); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/history-dock-widget.cc --- a/libgui/src/history-dock-widget.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/history-dock-widget.cc Sun May 25 10:29:05 2014 -0700 @@ -214,7 +214,7 @@ if (_filter_line_edit->hasFocus () && _filter_line_edit->hasSelectedText ()) { QClipboard *clipboard = QApplication::clipboard (); - clipboard->setText ( _filter_line_edit->selectedText ()); + clipboard->setText (_filter_line_edit->selectedText ()); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/m-editor/file-editor-interface.h --- a/libgui/src/m-editor/file-editor-interface.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/m-editor/file-editor-interface.h Sun May 25 10:29:05 2014 -0700 @@ -40,7 +40,7 @@ virtual ~file_editor_interface () { } - virtual QMenu *get_mru_menu ( ) = 0; + virtual QMenu *get_mru_menu () = 0; virtual QMenu *debug_menu () = 0; virtual QToolBar *toolbar () = 0; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/m-editor/find-dialog.cc --- a/libgui/src/m-editor/find-dialog.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/m-editor/find-dialog.cc Sun May 25 10:29:05 2014 -0700 @@ -211,7 +211,8 @@ void find_dialog::find (bool forward) { - int line = -1, col = -1; + int line, col; + line = col = -1; bool do_wrap = _wrap_check_box->isChecked (); bool do_forward = forward; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/m-editor/octave-qscintilla.cc --- a/libgui/src/m-editor/octave-qscintilla.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/m-editor/octave-qscintilla.cc Sun May 25 10:29:05 2014 -0700 @@ -158,7 +158,7 @@ octave_qscintilla::contextMenuEvent (QContextMenuEvent *e) { QPoint global_pos, local_pos; // the menu's position - QMenu *context_menu = createStandardContextMenu ( ); // standard menu + QMenu *context_menu = createStandardContextMenu (); // standard menu // fill context menu with editor's standard actions emit create_context_menu_signal (context_menu); @@ -243,7 +243,7 @@ { QStringList commands = selectedText ().split (QRegExp("[\r\n]"), QString::SkipEmptyParts); - for (int i = 0; i < commands.size (); i++ ) + for (int i = 0; i < commands.size (); i++) emit execute_command_in_terminal_signal (commands.at (i)); } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/main-window.cc --- a/libgui/src/main-window.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/main-window.cc Sun May 25 10:29:05 2014 -0700 @@ -1896,7 +1896,7 @@ main_window::show_gui_info (void) { QString gui_info - ( QObject::tr ("

A Note about Octave's New GUI

" + (QObject::tr ("

A Note about Octave's New GUI

" "

One of the biggest new features for Octave 3.8 is a graphical " "user interface. It is the one thing that users have requested " "most often over the last few years and now it is almost ready. " @@ -2371,7 +2371,7 @@ QSettings *settings = resource_manager::get_settings (); - if (settings->value ("prompt_to_exit", false ).toBool()) + if (settings->value ("prompt_to_exit", false).toBool ()) { int ans = QMessageBox::question (this, tr ("Octave"), tr ("Are you sure you want to exit Octave?"), diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/octave-dock-widget.cc --- a/libgui/src/octave-dock-widget.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/octave-dock-widget.cc Sun May 25 10:29:05 2014 -0700 @@ -66,7 +66,7 @@ _dock_button->setIconSize (QSize (12,12)); _close_action = new QAction - (QIcon (":/actions/icons/widget-close.png"), "", this ); + (QIcon (":/actions/icons/widget-close.png"), "", this); _close_action-> setToolTip (tr ("Hide widget")); connect (_close_action, SIGNAL (triggered (bool)), this, SLOT (change_visibility (bool))); @@ -178,7 +178,7 @@ _dock_action->setIcon (QIcon (":/actions/icons/widget-dock"+_icon_color+".png")); _dock_action->setToolTip (tr ("Dock widget")); - // restore the last geometry( when floating + // restore the last geometry when floating setGeometry (settings->value ("DockWidgets/" + objectName () + "_floating_geometry",QRect(50,100,480,480)).toRect ()); @@ -202,7 +202,7 @@ { #if defined (Q_OS_WIN32) - // windows: Since floating widget has no parent, we have to readd it + // windows: Since floating widget has no parent, we have to read it QSettings *settings = resource_manager::get_settings (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/octave-qt-link.cc --- a/libgui/src/octave-qt-link.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/octave-qt-link.cc Sun May 25 10:29:05 2014 -0700 @@ -100,7 +100,7 @@ tr ("File\n%1\ndoes not exist. Do you want to create it?"). arg (QDir::currentPath () + QDir::separator () + QString::fromStdString (file)), - tr ("Octave Editor"), "quest", btn, tr ("Yes"), role ); + tr ("Octave Editor"), "quest", btn, tr ("Yes"), role); // Wait while the user is responding to message box. uiwidget_creator.wait (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/qtinfo/parser.cc --- a/libgui/src/qtinfo/parser.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/qtinfo/parser.cc Sun May 25 10:29:05 2014 -0700 @@ -22,7 +22,7 @@ */ // Author: P. L. Lucas -// Author: Jacob Dawid +// Author: Jacob Dawid #ifdef HAVE_CONFIG_H #include @@ -77,7 +77,7 @@ parser::open_file (QFileInfo & file_info) { QIODevice *iodevice = 0; - if ( _compressors_map.contains(file_info.suffix ())) + if (_compressors_map.contains (file_info.suffix ())) { QProcess gzip; gzip.start (_compressors_map.value (file_info.suffix ()).arg (file_info.absoluteFilePath ())); @@ -277,7 +277,7 @@ QRegExp re ("(\\*[N|n]ote|\n\\*)([ |\n]+)([^:]+):([^:\\.,]*)([:,\\.]+)"); int i = 0, f; - while ( (i = re.indexIn (text,i)) != -1) + while ((i = re.indexIn (text,i)) != -1) { QString type = re.cap (1); QString note = re.cap (3); @@ -330,7 +330,7 @@ { QRegExp re ("`([^']+)'"); int i = 0, f; - while ( (i = re.indexIn (text, i)) != -1) + while ((i = re.indexIn (text, i)) != -1) { QString t = re.cap (1); QString bold = "" + t + @@ -436,7 +436,7 @@ while (! (nodeText=get_next_node (io)).isEmpty () && foundCount < 2) { QString first_line = get_first_line (nodeText); - if (first_line.startsWith ("Tag") ) + if (first_line.startsWith ("Tag")) { foundCount++; int pos = 0; @@ -471,7 +471,7 @@ foundCount++; int pos = 0; - while ( (pos = re_files.indexIn (nodeText, pos)) != -1) + while ((pos = re_files.indexIn (nodeText, pos)) != -1) { QString fileCap = re_files.cap (1).trimmed (); int index = re_files.cap (2).toInt (); @@ -501,7 +501,8 @@ void parser::real_position (int pos, QFileInfo & file_info, int & real_pos) { - int header = -1, sum = 0; + int header = -1; + int sum = 0; for (int i = 0; i < _info_file_real_size_list.size (); i++) { info_file_item item = _info_file_real_size_list.at (i); @@ -538,7 +539,7 @@ { int pos = 0; - while ( (pos = re.indexIn (text, pos)) != -1) + while ((pos = re.indexIn (text, pos)) != -1) { QString cap = text.mid (pos,re.matchedLength ()); QString a (after); @@ -578,7 +579,7 @@ } QString node_text; - while ( !(node_text = get_next_node (io)).isEmpty ()) + while (! (node_text = get_next_node (io)).isEmpty ()) { QString firstLine = get_first_line (node_text); QString node = get_node_name (node_text); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/qtinfo/parser.h --- a/libgui/src/qtinfo/parser.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/qtinfo/parser.h Sun May 25 10:29:05 2014 -0700 @@ -22,7 +22,7 @@ */ // Author: P. L. Lucas -// Author: Jacob Dawid +// Author: Jacob Dawid #include #include diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/qtinfo/webinfo.cc --- a/libgui/src/qtinfo/webinfo.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/qtinfo/webinfo.cc Sun May 25 10:29:05 2014 -0700 @@ -22,7 +22,7 @@ */ // Author: P. L. Lucas -// Author: Jacob Dawid +// Author: Jacob Dawid #ifdef HAVE_CONFIG_H #include @@ -181,7 +181,7 @@ _text_browser->show (); connect (_text_browser, SIGNAL (anchorClicked (const QUrl &)), this, - SLOT (link_clicked (const QUrl &)) ); + SLOT (link_clicked (const QUrl &))); disconnect(_tab_bar, SIGNAL (currentChanged(int)), this, SLOT (current_tab_changed (int))); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/qtinfo/webinfo.h --- a/libgui/src/qtinfo/webinfo.h Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/qtinfo/webinfo.h Sun May 25 10:29:05 2014 -0700 @@ -22,7 +22,7 @@ */ // Author: P. L. Lucas -// Author: 2012 Jacob Dawid +// Author: 2012 Jacob Dawid #include #include "parser.h" diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/settings-dialog.cc --- a/libgui/src/settings-dialog.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/settings-dialog.cc Sun May 25 10:29:05 2014 -0700 @@ -140,7 +140,7 @@ ui->customFileEditor->setText ( settings->value ("customFileEditor").toString ()); ui->editor_showLineNumbers->setChecked ( - settings->value ("editor/showLineNumbers",true).toBool () ); + settings->value ("editor/showLineNumbers",true).toBool ()); default_var = QColor (240, 240, 240); QColor setting_color = settings->value ("editor/highlight_current_line_color", @@ -152,7 +152,7 @@ connect (ui->editor_highlightCurrentLine, SIGNAL (toggled (bool)), _editor_current_line_color, SLOT (setEnabled (bool))); ui->editor_highlightCurrentLine->setChecked ( - settings->value ("editor/highlightCurrentLine",true).toBool () ); + settings->value ("editor/highlightCurrentLine",true).toBool ()); ui->editor_long_line_marker->setChecked ( settings->value ("editor/long_line_marker",true).toBool ()); ui->editor_long_line_column->setValue ( @@ -163,7 +163,7 @@ settings->value ("editor/code_folding",true).toBool ()); ui->editor_codeCompletion->setChecked ( - settings->value ("editor/codeCompletion", true).toBool () ); + settings->value ("editor/codeCompletion", true).toBool ()); ui->editor_spinbox_ac_threshold->setValue ( settings->value ("editor/codeCompletion_threshold",2).toInt ()); ui->editor_checkbox_ac_keywords->setChecked ( @@ -203,7 +203,7 @@ // terminal ui->terminal_fontName->setCurrentFont (QFont ( - settings->value ("terminal/fontName","Courier New").toString ()) ); + settings->value ("terminal/fontName","Courier New").toString ())); ui->terminal_fontSize->setValue ( settings->value ("terminal/fontSize", 10).toInt ()); ui->terminal_history_buffer->setValue ( @@ -262,7 +262,7 @@ int currentIndex = 0; QString proxyTypeString = settings->value ("proxyType").toString (); - while ( (currentIndex < ui->proxyType->count ()) + while ((currentIndex < ui->proxyType->count ()) && (ui->proxyType->currentText () != proxyTypeString)) { currentIndex++; @@ -558,7 +558,7 @@ settings->setValue ("toolbar_icon_size", ui->toolbar_icon_size->value ()); // promp to exit - settings->setValue ( "prompt_to_exit", ui->cb_prompt_to_exit->isChecked ()); + settings->setValue ("prompt_to_exit", ui->cb_prompt_to_exit->isChecked ()); // status bar settings->setValue ( "show_status_bar", ui->cb_status_bar->isChecked ()); @@ -661,7 +661,7 @@ settings->setValue ("terminal/focus_after_command", ui->terminal_focus_command->isChecked ()); settings->setValue ("terminal/history_buffer", - ui->terminal_history_buffer->value() ); + ui->terminal_history_buffer->value ()); // the cursor QString cursorType; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/shortcut-manager.cc --- a/libgui/src/shortcut-manager.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/shortcut-manager.cc Sun May 25 10:29:05 2014 -0700 @@ -82,25 +82,29 @@ // actions of the main window // file - init (tr ("New File"), "main_file:new_file", QKeySequence::New ); - init (tr ("New Function"), "main_file:new_function", QKeySequence ("Ctrl+Shift+N") ); - init (tr ("New Figure"), "main_file:new_figure", QKeySequence () ); - init (tr ("Open File"), "main_file:open_file", QKeySequence::Open ); - init (tr ("Load Workspace"), "main_file:load_workspace", QKeySequence () ); - init (tr ("Save Workspace As"), "main_file:save_workspace", QKeySequence () ); - init (tr ("Preferences"), "main_file:preferences", QKeySequence () ); - init (tr ("Exit Octave"), "main_file:exit", QKeySequence::Quit ); + init (tr ("New File"), "main_file:new_file", QKeySequence::New); + init (tr ("New Function"), "main_file:new_function", + QKeySequence ("Ctrl+Shift+N")); + init (tr ("New Figure"), "main_file:new_figure", QKeySequence ()); + init (tr ("Open File"), "main_file:open_file", QKeySequence::Open); + init (tr ("Load Workspace"), "main_file:load_workspace", QKeySequence ()); + init (tr ("Save Workspace As"), "main_file:save_workspace", QKeySequence ()); + init (tr ("Preferences"), "main_file:preferences", QKeySequence ()); + init (tr ("Exit Octave"), "main_file:exit", QKeySequence::Quit); // edit init (tr ("Copy"), "main_edit:copy", QKeySequence::Copy); init (tr ("Paste"), "main_edit:paste", QKeySequence::Paste); init (tr ("Undo"), "main_edit:undo", QKeySequence::Undo); - init (tr ("Select All"), "main_edit:select_all", QKeySequence () ); - init (tr ("Clear Clipboard"), "main_edit:clear_clipboard", QKeySequence () ); - init (tr ("Find in Files"), "main_edit:find_in_files", QKeySequence (Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_F) ); - init (tr ("Clear Command Window"), "main_edit:clear_command_window", QKeySequence () ); - init (tr ("Clear Command History"), "main_edit:clear_history", QKeySequence () ); - init (tr ("Clear Workspace"), "main_edit:clear_workspace", QKeySequence () ); + init (tr ("Select All"), "main_edit:select_all", QKeySequence ()); + init (tr ("Clear Clipboard"), "main_edit:clear_clipboard", QKeySequence ()); + init (tr ("Find in Files"), "main_edit:find_in_files", + QKeySequence (Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_F)); + init (tr ("Clear Command Window"), "main_edit:clear_command_window", + QKeySequence ()); + init (tr ("Clear Command History"), "main_edit:clear_history", + QKeySequence ()); + init (tr ("Clear Workspace"), "main_edit:clear_workspace", QKeySequence ()); // debug init (tr ("Step Over"), "main_debug:step_over", QKeySequence (Qt::Key_F10)); @@ -143,68 +147,96 @@ // actions of the editor // file - init (tr ("Edit Function"), "editor_file:edit_function", QKeySequence (Qt::ControlModifier + Qt::Key_E) ); - init (tr ("Save File"), "editor_file:save", QKeySequence::Save ); - init (tr ("Save File As"), "editor_file:save_as", QKeySequence::SaveAs ); - init (tr ("Close"), "editor_file:close", QKeySequence::Close ); - init (tr ("Close All"), "editor_file:close_all", QKeySequence () ); - init (tr ("Close Other"), "editor_file:close_other", QKeySequence () ); - init (tr ("Print"), "editor_file:print", QKeySequence::Print ); + init (tr ("Edit Function"), "editor_file:edit_function", + QKeySequence (Qt::ControlModifier + Qt::Key_E)); + init (tr ("Save File"), "editor_file:save", QKeySequence::Save); + init (tr ("Save File As"), "editor_file:save_as", QKeySequence::SaveAs); + init (tr ("Close"), "editor_file:close", QKeySequence::Close); + init (tr ("Close All"), "editor_file:close_all", QKeySequence ()); + init (tr ("Close Other"), "editor_file:close_other", QKeySequence ()); + init (tr ("Print"), "editor_file:print", QKeySequence::Print); // edit - init (tr ("Undo"), "editor_edit:undo", QKeySequence::Undo ); - init (tr ("Redo"), "editor_edit:redo", QKeySequence::Redo ); - init (tr ("Copy"), "editor_edit:copy", QKeySequence::Copy ); - init (tr ("Cuy"), "editor_edit:cut", QKeySequence::Cut ); - init (tr ("Paste"), "editor_edit:paste", QKeySequence::Paste ); - init (tr ("Select All"), "editor_edit:select_all", QKeySequence::SelectAll ); - init (tr ("Find and Replace"), "editor_edit:find_replace", QKeySequence::Find ); + init (tr ("Undo"), "editor_edit:undo", QKeySequence::Undo); + init (tr ("Redo"), "editor_edit:redo", QKeySequence::Redo); + init (tr ("Copy"), "editor_edit:copy", QKeySequence::Copy); + init (tr ("Cuy"), "editor_edit:cut", QKeySequence::Cut); + init (tr ("Paste"), "editor_edit:paste", QKeySequence::Paste); + init (tr ("Select All"), "editor_edit:select_all", QKeySequence::SelectAll); + init (tr ("Find and Replace"), "editor_edit:find_replace", + QKeySequence::Find); - init (tr ("Delete to Start of Word"), "editor_edit:delete_start_word", QKeySequence::DeleteStartOfWord ); - init (tr ("Delete to End of Word"), "editor_edit:delete_end_word", QKeySequence::DeleteEndOfWord ); - init (tr ("Delete to Start of Line"), "editor_edit:delete_start_line", QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Backspace) ); - init (tr ("Delete to End of Line"), "editor_edit:delete_end_line", QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Delete) ); - init (tr ("Delete Line"), "editor_edit:delete_line", QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_L) ); - init (tr ("Copy Line"), "editor_edit:copy_line", QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_C) ); - init (tr ("Cut Line"), "editor_edit:cut_line", QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_X) ); - init (tr ("Duplicate Selection/Line"), "editor_edit:duplicate_selection", QKeySequence (Qt::ControlModifier + Qt::Key_D) ); - init (tr ("Transpose Line"), "editor_edit:transpose_line", QKeySequence (Qt::ControlModifier + Qt::Key_T) ); - init (tr ("Completion List"), "editor_edit:completion_list", QKeySequence (Qt::ControlModifier + Qt::Key_Space) ); + init (tr ("Delete to Start of Word"), "editor_edit:delete_start_word", + QKeySequence::DeleteStartOfWord); + init (tr ("Delete to End of Word"), "editor_edit:delete_end_word", + QKeySequence::DeleteEndOfWord); + init (tr ("Delete to Start of Line"), "editor_edit:delete_start_line", + QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Backspace)); + init (tr ("Delete to End of Line"), "editor_edit:delete_end_line", + QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Delete)); + init (tr ("Delete Line"), "editor_edit:delete_line", + QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_L)); + init (tr ("Copy Line"), "editor_edit:copy_line", + QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_C)); + init (tr ("Cut Line"), "editor_edit:cut_line", + QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_X)); + init (tr ("Duplicate Selection/Line"), "editor_edit:duplicate_selection", + QKeySequence (Qt::ControlModifier + Qt::Key_D)); + init (tr ("Transpose Line"), "editor_edit:transpose_line", + QKeySequence (Qt::ControlModifier + Qt::Key_T)); + init (tr ("Completion List"), "editor_edit:completion_list", + QKeySequence (Qt::ControlModifier + Qt::Key_Space)); - init (tr ("Comment Selection"), "editor_edit:comment_selection", QKeySequence (Qt::ControlModifier + Qt::Key_R) ); - init (tr ("Uncomment Selection"), "editor_edit:uncomment_selection", QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_R) ); - init (tr ("Uppercase Selection"), "editor_edit:upper_case", QKeySequence (Qt::ControlModifier + Qt::Key_U) ); - init (tr ("Lowercase Selection"), "editor_edit:lower_case", QKeySequence (Qt::ControlModifier + Qt::AltModifier + Qt::Key_U) ); - init (tr ("Indent Selection"), "editor_edit:indent_selection", QKeySequence (Qt::ControlModifier + Qt::Key_Tab) ); - init (tr ("Unindent Selection"), "editor_edit:unindent_selection", QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_Tab) ); + init (tr ("Comment Selection"), "editor_edit:comment_selection", + QKeySequence (Qt::ControlModifier + Qt::Key_R)); + init (tr ("Uncomment Selection"), "editor_edit:uncomment_selection", + QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_R)); + init (tr ("Uppercase Selection"), "editor_edit:upper_case", + QKeySequence (Qt::ControlModifier + Qt::Key_U)); + init (tr ("Lowercase Selection"), "editor_edit:lower_case", + QKeySequence (Qt::ControlModifier + Qt::AltModifier + Qt::Key_U)); + init (tr ("Indent Selection"), "editor_edit:indent_selection", + QKeySequence (Qt::ControlModifier + Qt::Key_Tab)); + init (tr ("Unindent Selection"), "editor_edit:unindent_selection", + QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_Tab)); - init (tr ("Goto Line"), "editor_edit:goto_line", QKeySequence (Qt::ControlModifier+ Qt::Key_G) ); - init (tr ("Toggle Bookmark"), "editor_edit:toggle_bookmark", QKeySequence (Qt::Key_F7) ); - init (tr ("Next Bookmark"), "editor_edit:next_bookmark", QKeySequence (Qt::Key_F2) ); - init (tr ("Previous Bookmark"), "editor_edit:previous_bookmark", QKeySequence (Qt::SHIFT + Qt::Key_F2) ); - init (tr ("Remove All Bookmark"), "editor_edit:remove_bookmark", QKeySequence () ); + init (tr ("Goto Line"), "editor_edit:goto_line", + QKeySequence (Qt::ControlModifier+ Qt::Key_G)); + init (tr ("Toggle Bookmark"), "editor_edit:toggle_bookmark", + QKeySequence (Qt::Key_F7)); + init (tr ("Next Bookmark"), "editor_edit:next_bookmark", + QKeySequence (Qt::Key_F2)); + init (tr ("Previous Bookmark"), "editor_edit:previous_bookmark", + QKeySequence (Qt::SHIFT + Qt::Key_F2)); + init (tr ("Remove All Bookmark"), "editor_edit:remove_bookmark", + QKeySequence ()); - init (tr ("Preferences"), "editor_edit:preferences", QKeySequence () ); - init (tr ("Styles Preferences"), "editor_edit:styles_preferences", QKeySequence () ); + init (tr ("Preferences"), "editor_edit:preferences", QKeySequence ()); + init (tr ("Styles Preferences"), "editor_edit:styles_preferences", + QKeySequence ()); // view - init (tr ("Zoom In"), "editor_view:zoom_in", QKeySequence::ZoomIn ); - init (tr ("Zoom Out"), "editor_view:zoom_out", QKeySequence::ZoomOut ); + init (tr ("Zoom In"), "editor_view:zoom_in", QKeySequence::ZoomIn); + init (tr ("Zoom Out"), "editor_view:zoom_out", QKeySequence::ZoomOut); init (tr ("Zoom Normal"), "editor_view:zoom_normal", QKeySequence (Qt::ControlModifier + Qt::AltModifier + Qt::Key_0)); // debug - init (tr ("Toggle Breakpoint"), "editor_debug:toggle_breakpoint", QKeySequence () ); - init (tr ("Next Breakpoint"), "editor_debug:next_breakpoint", QKeySequence () ); - init (tr ("Previous Breakpoint"), "editor_debug:previous_breakpoint", QKeySequence () ); - init (tr ("Remove All Breakpoints"), "editor_debug:remove_breakpoints", QKeySequence () ); + init (tr ("Toggle Breakpoint"), "editor_debug:toggle_breakpoint", + QKeySequence ()); + init (tr ("Next Breakpoint"), "editor_debug:next_breakpoint", + QKeySequence ()); + init (tr ("Previous Breakpoint"), "editor_debug:previous_breakpoint", + QKeySequence ()); + init (tr ("Remove All Breakpoints"), "editor_debug:remove_breakpoints", + QKeySequence ()); // run - init (tr ("Run File"), "editor_run:run_file", QKeySequence (Qt::Key_F5) ); - init (tr ("Run Selection"), "editor_run:run_selection", QKeySequence (Qt::Key_F9) ); + init (tr ("Run File"), "editor_run:run_file", QKeySequence (Qt::Key_F5)); + init (tr ("Run Selection"), "editor_run:run_selection", QKeySequence (Qt::Key_F9)); // help - init (tr ("Help on Keyword"), "editor_help:help_keyword", QKeySequence::HelpContents ); - init (tr ("Document on Keyword"), "editor_help:doc_keyword", QKeySequence (Qt::SHIFT + Qt::Key_F1) ); + init (tr ("Help on Keyword"), "editor_help:help_keyword", QKeySequence::HelpContents); + init (tr ("Document on Keyword"), "editor_help:doc_keyword", QKeySequence (Qt::SHIFT + Qt::Key_F1)); } void @@ -342,7 +374,7 @@ key_set = key+"_1"; if (index > -1 && index < _sc.count ()) - action->setShortcut ( QKeySequence ( + action->setShortcut (QKeySequence ( _settings->value ("shortcuts/" + key_set, _sc.at (index).default_sc[set]).toString ())); else qDebug () << "Key: " << key_set << " not found in _action_hash"; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libgui/src/workspace-model.cc --- a/libgui/src/workspace-model.cc Sun May 25 10:26:18 2014 -0700 +++ b/libgui/src/workspace-model.cc Sun May 25 10:29:05 2014 -0700 @@ -141,7 +141,7 @@ if (role == Qt::DisplayRole || (idx.column () == 0 && role == Qt::EditRole) - || (idx.column () == 0 && role == Qt::ToolTipRole) ) + || (idx.column () == 0 && role == Qt::ToolTipRole)) { switch (idx.column ()) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/Makefile.am diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/__contourc__.cc --- a/libinterp/corefcn/__contourc__.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/__contourc__.cc Sun May 25 10:29:05 2014 -0700 @@ -307,10 +307,10 @@ if (args.length () == 4) { - RowVector X = args (0).row_vector_value (); - RowVector Y = args (1).row_vector_value (); - Matrix Z = args (2).matrix_value (); - RowVector L = args (3).row_vector_value (); + RowVector X = args(0).row_vector_value (); + RowVector Y = args(1).row_vector_value (); + Matrix Z = args(2).matrix_value (); + RowVector L = args(3).row_vector_value (); if (! error_state) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/__pchip_deriv__.cc --- a/libinterp/corefcn/__pchip_deriv__.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/__pchip_deriv__.cc Sun May 25 10:29:05 2014 -0700 @@ -59,7 +59,7 @@ octave_value retval; const int nargin = args.length (); - bool rows = (nargin == 3 && args (2).uint_value () == 2); + bool rows = (nargin == 3 && args(2).uint_value () == 2); if (nargin >= 2) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/balance.cc --- a/libinterp/corefcn/balance.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/balance.cc Sun May 25 10:29:05 2014 -0700 @@ -144,7 +144,8 @@ if (AEPcase) { // Algebraic eigenvalue problem. - bool noperm = false, noscal = false; + bool noperm = false; + bool noscal = false; if (nargin > 1) { std::string a1s = args(1).string_value (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/besselj.cc --- a/libinterp/corefcn/besselj.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/besselj.cc Sun May 25 10:29:05 2014 -0700 @@ -598,7 +598,7 @@ { int idx = nargin == 1 ? 0 : 1; - if (args (idx).is_single_type ()) + if (args(idx).is_single_type ()) { FloatComplexNDArray z = args(idx).float_complex_array_value (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/betainc.cc --- a/libinterp/corefcn/betainc.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/betainc.cc Sun May 25 10:29:05 2014 -0700 @@ -32,8 +32,6 @@ #include "oct-obj.h" #include "utils.h" -// FIXME: These functions do not need to be dynamically loaded. They should -// be placed elsewhere in the Octave code hierarchy. DEFUN (betainc, args, , "-*- texinfo -*-\n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/bitfcns.cc --- a/libinterp/corefcn/bitfcns.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/bitfcns.cc Sun May 25 10:29:05 2014 -0700 @@ -595,7 +595,7 @@ int bits_in_type = sizeof (double) * std::numeric_limits::digits; NDArray m = m_arg.array_value (); - DO_BITSHIFT ( ); + DO_BITSHIFT (); } else if (cname == "single") { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/bsxfun.cc --- a/libinterp/corefcn/bsxfun.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/bsxfun.cc Sun May 25 10:29:05 2014 -0700 @@ -201,7 +201,8 @@ bsxfun_builtin_op op = bsxfun_builtin_lookup (name); if (op != bsxfun_builtin_unknown) { - builtin_type_t btyp_a = a.builtin_type (), btyp_b = b.builtin_type (); + builtin_type_t btyp_a = a.builtin_type (); + builtin_type_t btyp_b = b.builtin_type (); // Simplify single/double combinations. if (btyp_a == btyp_float && btyp_b == btyp_double) @@ -351,8 +352,8 @@ || args(0).is_inline_function ())) error ("bsxfun: F must be a string or function handle"); - const octave_value A = args (1); - const octave_value B = args (2); + const octave_value A = args(1); + const octave_value B = args(2); if (func.is_builtin_function () || (func.is_function_handle () diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/cellfun.cc --- a/libinterp/corefcn/cellfun.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/cellfun.cc Sun May 25 10:29:05 2014 -0700 @@ -1227,7 +1227,7 @@ // fewer polymorphic function calls as the function gets called // for each value of the array. - if (! symbol_table_lookup ) + if (! symbol_table_lookup) { if (func.is_function_handle ()) { @@ -1783,7 +1783,8 @@ NDA parray = array.permute (perm); - octave_idx_type nela = arraydv.numel (), nelc = celldv.numel (); + octave_idx_type nela = arraydv.numel (); + octave_idx_type nelc = celldv.numel (); parray = parray.reshape (dim_vector (nela, nelc)); Cell retval (celldv); @@ -1901,7 +1902,7 @@ octave_value array = args(0); Array dimv; if (nargin > 1) - dimv = args (1).int_vector_value (true); + dimv = args(1).int_vector_value (true); if (error_state) ; @@ -2036,7 +2037,8 @@ if (ivec >= 0) { // Vector split. Use 1D indexing. - octave_idx_type l = 0, nidx = (ivec == 0 ? nridx : ncidx); + octave_idx_type l = 0; + octave_idx_type nidx = (ivec == 0 ? nridx : ncidx); for (octave_idx_type i = 0; i < nidx; i++) { octave_idx_type u = l + d[ivec](i); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/data.cc --- a/libinterp/corefcn/data.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/data.cc Sun May 25 10:29:05 2014 -0700 @@ -120,7 +120,7 @@ \n\ @example\n\ @group\n\ -all ([2, 3; 1, 0]))\n\ +all ([2, 3; 1, 0])\n\ @result{} [ 1, 0 ]\n\ @end group\n\ @end example\n\ @@ -302,7 +302,8 @@ { octave_value retval; - octave_value arg0 = x, arg1 = y; + octave_value arg0 = x; + octave_value arg1 = y; if (! arg0.is_numeric_type ()) gripe_wrong_type_arg ("hypot", arg0); else if (! arg1.is_numeric_type ()) @@ -561,7 +562,7 @@ X##NDArray a1 = args(1).X##_array_value (); \ retval = binmap (a0, a1, rem, "rem"); \ } \ - break + break; MAKE_INT_BRANCH (int8); MAKE_INT_BRANCH (int16); MAKE_INT_BRANCH (int32); @@ -695,7 +696,7 @@ X##NDArray a1 = args(1).X##_array_value (); \ retval = binmap (a0, a1, mod, "mod"); \ } \ - break + break; MAKE_INT_BRANCH (int8); MAKE_INT_BRANCH (int16); MAKE_INT_BRANCH (int32); @@ -1177,7 +1178,7 @@ retval = arg.X ## _array_value ().cumsum (dim); \ else \ retval = arg.array_value ().cumsum (dim); \ - break + break; MAKE_INT_BRANCH (int8); MAKE_INT_BRANCH (int16); MAKE_INT_BRANCH (int32); @@ -1353,6 +1354,11 @@ %!assert (diag ({1}, 2, 3), {1,[],[]; [],[],[]}); %!assert (diag ({1,2}, 3, 4), {1,[],[],[]; [],2,[],[]; [],[],[],[]}); +## Test out-of-range diagonals +%!assert (diag (ones (3,3), 4), zeros (0, 1)) +%!assert (diag (cell (3,3), 4), cell (0, 1)) +%!assert (diag (sparse (ones (3,3)), 4), sparse (zeros (0, 1))) + %% Test input validation %!error diag () %!error diag (1,2,3,4) @@ -1373,12 +1379,144 @@ "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} prod (@var{x})\n\ @deftypefnx {Built-in Function} {} prod (@var{x}, @var{dim})\n\ -Product of elements along dimension @var{dim}. If @var{dim} is\n\ -omitted, it defaults to the first non-singleton dimension.\n\ +@deftypefnx {Built-in Function} {} prod (@dots{}, \"native\")\n\ +@deftypefnx {Built-in Function} {} prod (@dots{}, \"double\")\n\ +Product of elements along dimension @var{dim}.\n\ +\n\ +If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\ +\n\ +The optional @qcode{\"type\"} input determines the class of the variable used for\n\ +calculations. If the argument @qcode{\"native\"} is given, then the operation is\n\ +performed in the same type as the original argument, rather than the default double\n\ +type.\n\ +\n\ +For example:\n\ +\n\ +@example\n\ +@group\n\ +prod ([true, true])\n\ + @result{} 1\n\ +prod ([true, true], \"native\")\n\ + @result{} true\n\ +@end group\n\ +@end example\n\ +\n\ +On the contrary, if @qcode{\"double\"} is given, the operation is performed in\n\ +double precision even for single precision inputs.\n\ @seealso{cumprod, sum}\n\ @end deftypefn") { - DATA_REDUCTION (prod); + octave_value retval; + + int nargin = args.length (); + + bool isnative = false; + bool isdouble = false; + + if (nargin > 1 && args(nargin - 1).is_string ()) + { + std::string str = args(nargin - 1).string_value (); + + if (! error_state) + { + if (str == "native") + isnative = true; + else if (str == "double") + isdouble = true; + else + error ("prod: unrecognized type argument '%s'", str.c_str ()); + nargin --; + } + } + + if (error_state) + return retval; + + if (nargin == 1 || nargin == 2) + { + octave_value arg = args(0); + + int dim = -1; + if (nargin == 2) + { + dim = args(1).int_value () - 1; + if (dim < 0) + error ("prod: invalid dimension DIM = %d", dim + 1); + } + + if (! error_state) + { + switch (arg.builtin_type ()) + { + case btyp_double: + if (arg.is_sparse_type ()) + retval = arg.sparse_matrix_value ().prod (dim); + else + retval = arg.array_value ().prod (dim); + break; + case btyp_complex: + if (arg.is_sparse_type ()) + retval = arg.sparse_complex_matrix_value ().prod (dim); + else + retval = arg.complex_array_value ().prod (dim); + break; + case btyp_float: + if (isdouble) + retval = arg.float_array_value ().dprod (dim); + else + retval = arg.float_array_value ().prod (dim); + break; + case btyp_float_complex: + if (isdouble) + retval = arg.float_complex_array_value ().dprod (dim); + else + retval = arg.float_complex_array_value ().prod (dim); + break; + +#define MAKE_INT_BRANCH(X) \ + case btyp_ ## X: \ + if (isnative) \ + retval = arg.X ## _array_value ().prod (dim); \ + else \ + retval = arg.array_value ().prod (dim); \ + break; + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); +#undef MAKE_INT_BRANCH + + // GAGME: Accursed Matlab compatibility... + case btyp_char: + retval = arg.array_value (true).prod (dim); + break; + case btyp_bool: + if (arg.is_sparse_type ()) + { + if (isnative) + retval = arg.sparse_bool_matrix_value ().all (dim); + else + retval = arg.sparse_matrix_value ().prod (dim); + } + else if (isnative) + retval = arg.bool_array_value ().all (dim); + else + retval = NDArray (arg.bool_array_value ().all (dim)); + break; + + default: + gripe_wrong_type_arg ("prod", arg); + } + } + } + else + print_usage (); + + return retval; } /* @@ -1392,6 +1530,13 @@ %!assert (prod (single ([i, 2+i, -3+2i, 4])), single (-4 - 32i)) %!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single ([-1+i, -8+8i, -27+27i])) +%% Test sparse +%!assert (prod (sparse ([1, 2, 3])), sparse (6)) +%!assert (prod (sparse ([-1; -2; -3])), sparse (-6)) +## Commented out until bug #42290 is fixed +#%!assert (prod (sparse ([i, 2+i, -3+2i, 4])), sparse (-4 - 32i)) +#%!assert (prod (sparse ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), sparse ([-1+i, -8+8i, -27+27i])) + %!assert (prod ([1, 2; 3, 4], 1), [3, 8]) %!assert (prod ([1, 2; 3, 4], 2), [2; 12]) %!assert (prod (zeros (1, 0)), 1) @@ -1422,7 +1567,24 @@ %!assert (prod (zeros (0, 2, "single"), 1), single ([1, 1])) %!assert (prod (zeros (0, 2, "single"), 2), zeros (0, 1, "single")) +%% Test "double" type argument +%!assert (prod (single ([1, 2, 3]), "double"), 6) +%!assert (prod (single ([-1; -2; -3]), "double"), -6) +%!assert (prod (single ([i, 2+i, -3+2i, 4]), "double"), -4 - 32i) +%!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), "double"), [-1+i, -8+8i, -27+27i]) + +%% Test "native" type argument +%!assert (prod (uint8 ([1, 2, 3]), "native"), uint8 (6)) +%!assert (prod (uint8 ([-1; -2; -3]), "native"), uint8 (0)) +%!assert (prod (int8 ([1, 2, 3]), "native"), int8 (6)) +%!assert (prod (int8 ([-1; -2; -3]), "native"), int8 (-6)) +%!assert (prod ([true false; true true], "native"), [true false]) +%!assert (prod ([true false; true true], 2, "native"), [false; true]) + +%% Test input validation %!error prod () +%!error prod (1,2,3) +%!error prod (1, "foobar") */ static bool @@ -1836,7 +1998,7 @@ // and then directly resize. However, for some types there might // be some additional setup needed, and so this should be avoided. - octave_value tmp = args (0); + octave_value tmp = args(0); tmp = tmp.resize (dim_vector (0,0)).resize (dv); if (error_state) @@ -1850,12 +2012,12 @@ // Can't fast return here to skip empty matrices as something // like cat (1,[],single ([])) must return an empty matrix of // the right type. - tmp = do_cat_op (tmp, args (j), ra_idx); + tmp = do_cat_op (tmp, args(j), ra_idx); if (error_state) return retval; - dim_vector dv_tmp = args (j).dims (); + dim_vector dv_tmp = args(j).dims (); if (dim >= dv_len) { @@ -2314,8 +2476,8 @@ %!assert (cat (3, [], [], [1,2;3,4]), [1,2;3,4]) %!assert (cat (4, [], [], [1,2;3,4]), [1,2;3,4]) -%!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2]) ) -%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2)) ) +%!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2])) +%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2))) %!error cat (3, cat (3, [], []), [1,2;3,4]) %!error cat (3, zeros (0, 0, 2), [1,2;3,4]) @@ -2677,12 +2839,16 @@ @deftypefnx {Built-in Function} {} sum (@dots{}, \"native\")\n\ @deftypefnx {Built-in Function} {} sum (@dots{}, \"double\")\n\ @deftypefnx {Built-in Function} {} sum (@dots{}, \"extra\")\n\ -Sum of elements along dimension @var{dim}. If @var{dim} is\n\ -omitted, it defaults to the first non-singleton dimension.\n\ -\n\ -If the optional argument @qcode{\"native\"} is given, then the sum is\n\ -performed in the same type as the original argument, rather than in the\n\ -default double type. For example:\n\ +Sum of elements along dimension @var{dim}.\n\ +\n\ +If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\ +\n\ +The optional @qcode{\"type\"} input determines the class of the variable used for\n\ +calculations. If the argument @qcode{\"native\"} is given, then the operation is\n\ +performed in the same type as the original argument, rather than the default double\n\ +type.\n\ +\n\ +For example:\n\ \n\ @example\n\ @group\n\ @@ -2696,10 +2862,10 @@ On the contrary, if @qcode{\"double\"} is given, the sum is performed in\n\ double precision even for single precision inputs.\n\ \n\ -For double precision inputs, @qcode{\"extra\"} indicates that a more accurate\n\ -algorithm than straightforward summation is to be used. For single precision\n\ -inputs, @qcode{\"extra\"} is the same as @qcode{\"double\"}. Otherwise,\n\ -@qcode{\"extra\"} has no effect.\n\ +For double precision inputs, the @qcode{\"extra\"} option will use a more accurate\n\ +algorithm than straightforward summation. For single precision inputs,\n\ +@qcode{\"extra\"} is the same as @qcode{\"double\"}. Otherwise, @qcode{\"extra\"}\n\ +has no effect.\n\ @seealso{cumsum, sumsq, prod}\n\ @end deftypefn") { @@ -2724,7 +2890,7 @@ else if (str == "extra") isextra = true; else - error ("sum: unrecognized string argument"); + error ("sum: unrecognized type argument '%s'", str.c_str ()); nargin --; } } @@ -2791,7 +2957,7 @@ retval = arg.X ## _array_value ().sum (dim); \ else \ retval = arg.X ## _array_value ().dsum (dim); \ - break + break; MAKE_INT_BRANCH (int8); MAKE_INT_BRANCH (int16); MAKE_INT_BRANCH (int32); @@ -2801,7 +2967,8 @@ MAKE_INT_BRANCH (uint32); MAKE_INT_BRANCH (uint64); #undef MAKE_INT_BRANCH - // GAGME: Accursed Matlab compatibility... + + // GAGME: Accursed Matlab compatibility... case btyp_char: if (isextra) retval = arg.array_value (true).xsum (dim); @@ -2834,11 +3001,6 @@ } /* -%!assert (sum ([true,true]), 2) -%!assert (sum ([true,true],"native"), true) -%!assert (sum (int8 ([127,10,-20])), 117) -%!assert (sum (int8 ([127,10,-20]),'native'), int8 (107)) - %!assert (sum ([1, 2, 3]), 6) %!assert (sum ([-1; -2; -3]), -6) %!assert (sum ([i, 2+i, -3+2i, 4]), 3+4i) @@ -2889,10 +3051,18 @@ %!assert (sum (zeros (2, 2, 0, 3, "single"), 4), zeros (2, 2, 0, "single")) %!assert (sum (zeros (2, 2, 0, 3, "single"), 7), zeros (2, 2, 0, 3, "single")) +## Test "native" +%!assert (sum ([true,true]), 2) +%!assert (sum ([true,true], "native"), true) +%!assert (sum (int8 ([127,10,-20])), 117) +%!assert (sum (int8 ([127,10,-20]), "native"), int8 (107)) + ;-) %!assert (sum ("Octave") + "8", sumsq (primes (17))) %!error sum () +%!error sum (1,2,3) +%!error sum (1, "foobar") */ DEFUN (sumsq, args, , @@ -4598,7 +4768,7 @@ @equiv{}\n\ eye (2, 2)\n\ @equiv{}\n\ -eye (size ([1, 2; 3, 4])\n\ +eye (size ([1, 2; 3, 4]))\n\ @end group\n\ @end example\n\ \n\ @@ -5344,7 +5514,7 @@ %!assert (norm (x,"inf"), single (7)) %!assert (norm (x,"fro"), single (10), -eps ("single")) %!assert (norm (x), single (10)) -%!assert (norm (single ([1e200, 1])), single (1e200)) +%!assert (norm (single ([1e38, 1])), single (1e38)) %!assert (norm (single ([3+4i, 3-4i, sqrt(31)])), single (9), -4*eps ("single")) %!shared m %! m = single (magic (4)); @@ -6561,7 +6731,7 @@ #define MAKE_INT_BRANCH(X) \ case btyp_ ## X: \ retval = argx.X ## _array_value ().nth_element (n, dim); \ - break + break; MAKE_INT_BRANCH (int8); MAKE_INT_BRANCH (int16); @@ -6705,7 +6875,8 @@ if (! error_state) { - octave_value vals = args(1), zero = args (2); + octave_value vals = args(1); + octave_value zero = args(2); switch (vals.builtin_type ()) { @@ -6732,7 +6903,7 @@ retval = do_accumarray_minmax (idx, vals.X ## _array_value (), \ n, ismin, \ zero.X ## _scalar_value ()); \ - break + break; MAKE_INT_BRANCH (int8); MAKE_INT_BRANCH (int16); @@ -6787,7 +6958,8 @@ else if (idx.extent (n) > n) error ("accumdim: index out of range"); - dim_vector vals_dim = vals.dims (), rdv = vals_dim; + dim_vector vals_dim = vals.dims (); + dim_vector rdv = vals_dim; if (dim < 0) dim = vals.dims ().first_non_singleton (); @@ -6866,7 +7038,8 @@ dim_vector dv = mask.dims (); NDT retval (dv); - bool tscl = tval.numel () == 1, fscl = fval.numel () == 1; + bool tscl = tval.numel () == 1; + bool fscl = fval.numel () == 1; if ((! tscl && tval.dims () != dv) || (! fscl && fval.dims () != dv)) @@ -6876,14 +7049,16 @@ T *rv = retval.fortran_vec (); octave_idx_type n = retval.numel (); - const T *tv = tval.data (), *fv = fval.data (); + const T *tv = tval.data (); + const T *fv = fval.data (); const bool *mv = mask.data (); if (tscl) { if (fscl) { - T ts = tv[0], fs = fv[0]; + T ts = tv[0]; + T fs = fv[0]; for (octave_idx_type i = 0; i < n; i++) rv[i] = mv[i] ? ts : fs; } @@ -6960,7 +7135,8 @@ else { boolNDArray mask = mask_val.bool_array_value (); - octave_value tval = args(1), fval = args(2); + octave_value tval = args(1); + octave_value fval = args(2); if (tval.is_double_type () && fval.is_double_type ()) { if (tval.is_complex_type () || fval.is_complex_type ()) @@ -7238,7 +7414,8 @@ assert (rep.ndims () == 2 && rep.rows () == 2); - octave_idx_type n = rep.columns (), l = 0; + octave_idx_type n = rep.columns (); + octave_idx_type l = 0; for (octave_idx_type i = 0; i < n; i++) { octave_idx_type k = rep(1, i); @@ -7325,7 +7502,7 @@ #define BTYP_BRANCH(X, EX) \ case btyp_ ## X: \ retval = do_repelems (x.EX ## _value (), r); \ - break + break; BTYP_BRANCH (double, array); BTYP_BRANCH (float, float_array); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/debug.cc --- a/libinterp/corefcn/debug.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/debug.cc Sun May 25 10:29:05 2014 -0700 @@ -85,7 +85,6 @@ if (file.eof ()) { // Expected to read the entire file. - retval = buf; } else @@ -99,8 +98,7 @@ static std::deque get_line_offsets (const std::string& buf) { - // This could maybe be smarter. Is deque the right thing to use - // here? + // This could maybe be smarter. Is deque the right thing to use here? std::deque offsets; @@ -207,28 +205,47 @@ if (args.length () == 0) return; - // If we are already in a debugging function. - if (octave_call_stack::caller_user_code ()) - { - idx = 0; - symbol_name = get_user_code ()->name (); - } + if (args(0).is_string ()) + { + // string could be function name or line number + int isint = atoi (args(0).string_value ().c_str ()); + + if (error_state) + return; + + if (isint == 0) + { + // It was a function name + symbol_name = args(0).string_value (); + if (error_state) + return; + idx = 1; + } + else + { + // It was a line number. Need to get function name from debugger. + if (Vdebugging) + { + symbol_name = get_user_code ()->name (); + idx = 0; + } + else + { + error ("%s: no function specified", who); + } + } + } else if (args(0).is_map ()) { - // Problem because parse_dbfunction_params() can only pass out a - // single function - } - else if (args(0).is_string ()) - { - symbol_name = args(0).string_value (); - if (error_state) - return; - idx = 1; + // This is a problem because parse_dbfunction_params() + // can only pass out a single function. + error ("%s: struct input not implemented", who); + return; } else error ("%s: invalid parameter specified", who); - for (int i = idx; i < nargin; i++ ) + for (int i = idx; i < nargin; i++) { if (args(i).is_string ()) { @@ -238,7 +255,7 @@ lines[list_idx++] = line; } else if (args(i).is_map ()) - octave_stdout << who << ": accepting a struct" << std::endl; + octave_stdout << who << ": skipping struct input" << std::endl; else { const NDArray arg = args(i).array_value (); @@ -356,7 +373,6 @@ return retval; } - int bp_table::do_remove_breakpoint_1 (octave_user_code *fcn, const std::string& fname, @@ -522,9 +538,12 @@ void bp_table::do_remove_all_breakpoints (void) { - for (const_bp_set_iterator it = bp_set.begin (); it != bp_set.end (); it++) - remove_all_breakpoints_in_file (*it); - + // Odd loop structure required because delete will invalidate bp_set iterators + for (const_bp_set_iterator it=bp_set.begin (), it_next=it; it != bp_set.end (); it=it_next) + { + ++it_next; + remove_all_breakpoints_in_file (*it); + } tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging; } @@ -537,7 +556,7 @@ for (int i = 0; i < slist.length (); i++) { - if (slist (i).string_value () == match) + if (slist(i).string_value () == match) { retval = slist(i).string_value (); break; @@ -547,7 +566,6 @@ return retval; } - bp_table::fname_line_map bp_table::do_get_breakpoint_list (const octave_value_list& fname_list) { @@ -576,7 +594,7 @@ bp_table::intmap bkpts_vec; for (int i = 0; i < len; i++) - bkpts_vec[i] = bkpts (i).double_value (); + bkpts_vec[i] = bkpts(i).double_value (); std::string symbol_name = f->name (); @@ -615,31 +633,36 @@ DEFUN (dbstop, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\")\n\ +@deftypefn {Command} dbstop @var{func}\n\ +@deftypefnx {Command} dbstop @var{func} @var{line}\n\ +@deftypefnx {Command} dbstop @var{func} @var{line1} @var{line2} @dots{}\n\ +@deftypefnx {Command} {} dbstop @var{line} @dots{}\n\ +@deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\")\n\ @deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\", @var{line})\n\ @deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\", @var{line1}, @var{line2}, @dots{})\n\ -Set a breakpoint in function @var{func}.\n\ +@deftypefnx {Built-in Function} {} dbstop (\"@var{func}\", [@var{line1}, @dots{}])\n\ +@deftypefnx {Built-in Function} {} dbstop (@var{line}, @dots{})\n\ +Set a breakpoint at line number @var{line} in function @var{func}.\n\ \n\ Arguments are\n\ \n\ @table @var\n\ @item func\n\ -Function name as a string variable. When already in debug\n\ -mode this should be left out and only the line should be given.\n\ +Function name as a string variable. When already in debug mode this argument\n\ +can be omitted and the current function will be used.\n\ \n\ @item line\n\ -Line number where the breakpoint should be set. Multiple\n\ -lines may be given as separate arguments or as a vector.\n\ +Line number where the breakpoint should be set. Multiple lines may be given\n\ +as separate arguments or as a vector.\n\ @end table\n\ \n\ -When called with a single argument @var{func}, the breakpoint\n\ -is set at the first executable line in the named function.\n\ +When called with a single argument @var{func}, the breakpoint is set at the\n\ +first executable line in the named function.\n\ \n\ -The optional output @var{rline} is the real line number where the\n\ -breakpoint was set. This can differ from specified line if\n\ -the line is not executable. For example, if a breakpoint attempted on a\n\ -blank line then Octave will set the real breakpoint at the\n\ -next executable line.\n\ +The optional output @var{rline} is the real line number where the breakpoint\n\ +was set. This can differ from the specified line if the line is not\n\ +executable. For example, if a breakpoint attempted on a blank line then\n\ +Octave will set the real breakpoint at the next executable line.\n\ @seealso{dbclear, dbstatus, dbstep, debug_on_error, debug_on_warning, debug_on_interrupt}\n\ @end deftypefn") { @@ -660,28 +683,38 @@ DEFUN (dbclear, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} dbclear (\"@var{func}\")\n\ -@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line}, @dots{})\n\ +@deftypefn {Command} {} dbclear @var{func}\n\ +@deftypefnx {Command} {} dbclear @var{func} @var{line}\n\ +@deftypefnx {Command} {} dbclear @var{func} @var{line1} @var{line2} @dots{}\n\ +@deftypefnx {Command} {} dbclear @var{line} @dots{}\n\ +@deftypefnx {Command} {} dbclear all\n\ +@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\")\n\ +@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line})\n\ +@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line1}, @var{line2}, @dots{})\n\ +@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", [@var{line1}, @dots{}])\n\ @deftypefnx {Built-in Function} {} dbclear (@var{line}, @dots{})\n\ -Delete a breakpoint in the function @var{func}.\n\ +@deftypefnx {Built-in Function} {} dbclear (\"all\")\n\ +Delete a breakpoint at line number @var{line} in the function @var{func}.\n\ \n\ Arguments are\n\ \n\ @table @var\n\ @item func\n\ -Function name as a string variable. When already in debug\n\ -mode this argument should be omitted and only the line number should be\n\ -given.\n\ +Function name as a string variable. When already in debug mode this argument\n\ +can be omitted and the current function will be used.\n\ \n\ @item line\n\ -Line number from which to remove a breakpoint. Multiple\n\ -lines may be given as separate arguments or as a vector.\n\ +Line number from which to remove a breakpoint. Multiple lines may be given\n\ +as separate arguments or as a vector.\n\ @end table\n\ \n\ -When called without a line number specification all breakpoints\n\ -in the named function are cleared.\n\ +When called without a line number specification all breakpoints in the named\n\ +function are cleared.\n\ \n\ If the requested line is not a breakpoint no action is performed.\n\ +\n\ +The special keyword @qcode{\"all\"} will clear all breakpoints from all\n\ +files.\n\ @seealso{dbstop, dbstatus, dbwhere}\n\ @end deftypefn") { @@ -689,10 +722,17 @@ std::string symbol_name = ""; bp_table::intmap lines; + int nargin = args.length (); + parse_dbfunction_params ("dbclear", args, symbol_name, lines); - if (! error_state) - bp_table::remove_breakpoint (symbol_name, lines); + if (nargin == 1 && symbol_name == "all") + bp_table::remove_all_breakpoints (); + else + { + if (! error_state) + bp_table::remove_breakpoint (symbol_name, lines); + } return retval; } @@ -724,6 +764,9 @@ A line number, or vector of line numbers, with a breakpoint.\n\ @end table\n\ \n\ +Note: When @code{dbstatus} is called from the debug prompt within a function,\n\ +the list of breakpoints is automatically trimmed to the breakpoints in the\n\ +current function.\n\ @seealso{dbclear, dbwhere}\n\ @end deftypefn") { @@ -752,11 +795,14 @@ } else { - octave_user_code *dbg_fcn = get_user_code (); - if (dbg_fcn) + if (Vdebugging) { - symbol_name = dbg_fcn->name (); - fcn_list(0) = symbol_name; + octave_user_code *dbg_fcn = get_user_code (); + if (dbg_fcn) + { + symbol_name = dbg_fcn->name (); + fcn_list(0) = symbol_name; + } } bp_list = bp_table::get_breakpoint_list (fcn_list); @@ -844,7 +890,7 @@ if (l > 0) { - octave_stdout << " line " << l << std::endl; + octave_stdout << "line " << l << std::endl; if (have_file) { @@ -855,7 +901,7 @@ } } else - octave_stdout << " " << std::endl; + octave_stdout << "" << std::endl; } else error ("dbwhere: must be inside a user function to use dbwhere\n"); @@ -863,8 +909,6 @@ return retval; } -// Copied and modified from the do_type command in help.cc -// Maybe we could share some code? void do_dbtype (std::ostream& os, const std::string& name, int start, int end) { @@ -876,30 +920,16 @@ if (fs) { - char ch; int line = 1; - bool isnewline = true; + std::string text; - // FIXME: Why not use line-oriented input here [getline()]? - while (fs.get (ch) && line <= end) - { - if (isnewline && line >= start) - { - os << line << "\t"; - isnewline = false; - } - - if (line >= start) - { - os << ch; - } - - if (ch == '\n') - { - line++; - isnewline = true; - } - } + while (std::getline (fs, text) && line <= end) + { + if (line >= start) + os << line << "\t" << text << "\n"; + + line++; + } } else os << "dbtype: unable to open '" << ff << "' for reading!\n"; @@ -946,13 +976,14 @@ dbg_fcn = get_user_code (); if (dbg_fcn) - do_dbtype (octave_stdout, dbg_fcn->name (), 0, - std::numeric_limits::max ()); + do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), + 0, std::numeric_limits::max ()); else error ("dbtype: must be inside a user function to give no arguments to dbtype\n"); + break; - case 1: // (dbtype func) || (dbtype start:end) + case 1: // (dbtype start:end) || (dbtype func) || (dbtype lineno) { std::string arg = argv[1]; @@ -975,28 +1006,51 @@ end = atoi (end_str.c_str ()); if (std::min (start, end) <= 0) - error ("dbtype: start and end lines must be >= 1\n"); + { + error ("dbtype: start and end lines must be >= 1\n"); + break; + } if (start <= end) - do_dbtype (octave_stdout, dbg_fcn->name (), start, end); + do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), + start, end); else error ("dbtype: start line must be less than end line\n"); } } - else // (dbtype func) + else // (dbtype func) || (dbtype lineno) { - dbg_fcn = get_user_code (arg); + int line = atoi (arg.c_str ()); + + if (line == 0) // (dbtype func) + { + dbg_fcn = get_user_code (arg); - if (dbg_fcn) - do_dbtype (octave_stdout, dbg_fcn->name (), 0, - std::numeric_limits::max ()); - else - error ("dbtype: function <%s> not found\n", arg.c_str ()); + if (dbg_fcn) + do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), + 0, std::numeric_limits::max ()); + else + error ("dbtype: function <%s> not found\n", arg.c_str ()); + } + else // (dbtype lineno) + { + if (line <= 0) + { + error ("dbtype: start and end lines must be >= 1\n"); + break; + } + + dbg_fcn = get_user_code (); + + if (dbg_fcn) + do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), + line, line); + } } } break; - case 2: // (dbtype func start:end) , (dbtype func start) + case 2: // (dbtype func start:end) || (dbtype func start) dbg_fcn = get_user_code (argv[1]); if (dbg_fcn) @@ -1023,10 +1077,14 @@ } if (std::min (start, end) <= 0) - error ("dbtype: start and end lines must be >= 1\n"); + { + error ("dbtype: start and end lines must be >= 1\n"); + break; + } if (start <= end) - do_dbtype (octave_stdout, dbg_fcn->name (), start, end); + do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), + start, end); else error ("dbtype: start line must be less than end line\n"); } @@ -1096,13 +1154,13 @@ { int l_min = std::max (l - n/2, 0); int l_max = l + n/2; - do_dbtype (octave_stdout, dbg_fcn->name (), l_min, l-1); + do_dbtype (octave_stdout, name, l_min, l-1); std::string line = get_file_line (name, l); if (! line.empty ()) octave_stdout << l << "-->\t" << line << std::endl; - do_dbtype (octave_stdout, dbg_fcn->name (), l+1, l_max); + do_dbtype (octave_stdout, name, l+1, l_max); } } else @@ -1166,10 +1224,9 @@ if (! error_state) { - octave_map stk = octave_call_stack::backtrace (nskip, curr_frame); - if (nargout == 0) { + octave_map stk = octave_call_stack::backtrace (nskip, curr_frame); octave_idx_type nframes_to_display = stk.numel (); if (nframes_to_display > 0) @@ -1215,6 +1272,10 @@ } else { + octave_map stk = octave_call_stack::backtrace (nskip, + curr_frame, + false); + retval(1) = curr_frame < 0 ? 1 : curr_frame + 1; retval(0) = stk; } @@ -1309,8 +1370,8 @@ DEFUN (dbup, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} dbup\n\ -@deftypefnx {Built-in Function} {} dbup (@var{n})\n\ +@deftypefn {Command} {} dbup\n\ +@deftypefnx {Command} {} dbup @var{n}\n\ In debugging mode, move up the execution stack @var{n} frames.\n\ If @var{n} is omitted, move up one frame.\n\ @seealso{dbstack, dbdown}\n\ @@ -1325,8 +1386,8 @@ DEFUN (dbdown, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} dbdown\n\ -@deftypefnx {Built-in Function} {} dbdown (@var{n})\n\ +@deftypefn {Command} {} dbdown\n\ +@deftypefnx {Command} {} dbdown @var{n}\n\ In debugging mode, move down the execution stack @var{n} frames.\n\ If @var{n} is omitted, move down one frame.\n\ @seealso{dbstack, dbup}\n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/dlmread.cc --- a/libinterp/corefcn/dlmread.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/dlmread.cc Sun May 25 10:29:05 2014 -0700 @@ -264,12 +264,15 @@ } // Take a subset if a range was given. - octave_idx_type r0 = 0, c0 = 0, r1 = idx_max-1, c1 = idx_max-1; + octave_idx_type r0 = 0; + octave_idx_type c0 = 0; + octave_idx_type r1 = idx_max-1; + octave_idx_type c1 = idx_max-1; if (nargin > 2) { if (nargin == 3) { - if (!parse_range_spec (args (2), r0, c0, r1, c1)) + if (!parse_range_spec (args(2), r0, c0, r1, c1)) error ("dlmread: error parsing RANGE"); } else if (nargin == 4) @@ -287,7 +290,12 @@ if (!error_state) { - octave_idx_type i = 0, j = 0, r = 1, c = 1, rmax = 0, cmax = 0; + octave_idx_type i = 0; + octave_idx_type j = 0; + octave_idx_type r = 1; + octave_idx_type c = 1; + octave_idx_type rmax = 0; + octave_idx_type cmax = 0; Matrix rdata; ComplexMatrix cdata; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/dot.cc --- a/libinterp/corefcn/dot.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/dot.cc Sun May 25 10:29:05 2014 -0700 @@ -128,11 +128,13 @@ return retval; } - octave_value argx = args(0), argy = args(1); + octave_value argx = args(0); + octave_value argy = args(1); if (argx.is_numeric_type () && argy.is_numeric_type ()) { - dim_vector dimx = argx.dims (), dimy = argy.dims (); + dim_vector dimx = argx.dims (); + dim_vector dimy = argy.dims (); bool match = dimx == dimy; if (! match && nargin == 2 && dimx.is_vector () && dimy.is_vector ()) @@ -301,13 +303,18 @@ return retval; } - octave_value argx = args(0), argy = args(1); + octave_value argx = args(0); + octave_value argy = args(1); if (argx.is_numeric_type () && argy.is_numeric_type ()) { - const dim_vector dimx = argx.dims (), dimy = argy.dims (); + const dim_vector dimx = argx.dims (); + const dim_vector dimy = argy.dims (); int nd = dimx.length (); - octave_idx_type m = dimx(0), k = dimx(1), n = dimy(1), np = 1; + octave_idx_type m = dimx(0); + octave_idx_type k = dimx(1); + octave_idx_type n = dimy(1); + octave_idx_type np = 1; bool match = dimy(0) == k && nd == dimy.length (); dim_vector dimz = dim_vector::alloc (nd); dimz(0) = m; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/eig.cc --- a/libinterp/corefcn/eig.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/eig.cc Sun May 25 10:29:05 2014 -0700 @@ -62,8 +62,8 @@ octave_value arg_a, arg_b; - octave_idx_type nr_a = 0, nr_b = 0; - octave_idx_type nc_a = 0, nc_b = 0; + octave_idx_type nr_a, nr_b, nc_a, nc_b; + nr_a = nr_b = nc_a = nc_b = 0; arg_a = args(0); nr_a = arg_a.rows (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/error.cc Sun May 25 10:29:05 2014 -0700 @@ -40,6 +40,7 @@ #include "utils.h" #include "ov.h" #include "ov-usr-fcn.h" +#include "pt-eval.h" #include "pt-pr-code.h" #include "pt-stmt.h" #include "toplev.h" @@ -66,8 +67,7 @@ // TRUE means that Octave will print a verbose warning. Currently unused. static bool Vverbose_warning; -// TRUE means that Octave will print no warnings, but lastwarn will be -//updated +// TRUE means that Octave will print no warnings, but lastwarn will be updated static bool Vquiet_warning = false; // A structure containing (most of) the current state of warnings. @@ -469,6 +469,10 @@ pr_where ("error"); + tree_evaluator::debug_mode = true; + + tree_evaluator::current_frame = octave_call_stack::current_frame (); + do_keyboard (octave_value_list ()); } } @@ -657,6 +661,10 @@ frame.protect_var (Vdebug_on_warning); Vdebug_on_warning = false; + tree_evaluator::debug_mode = true; + + tree_evaluator::current_frame = octave_call_stack::current_frame (); + do_keyboard (octave_value_list ()); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/file-io.cc --- a/libinterp/corefcn/file-io.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/file-io.cc Sun May 25 10:29:05 2014 -0700 @@ -271,7 +271,7 @@ if (nargin == 1) { - int fid = octave_stream_list::get_file_number (args (0)); + int fid = octave_stream_list::get_file_number (args(0)); octave_stream os = octave_stream_list::lookup (fid, "fclear"); @@ -305,7 +305,7 @@ { // FIXME: any way to avoid special case for stdout? - int fid = octave_stream_list::get_file_number (args (0)); + int fid = octave_stream_list::get_file_number (args(0)); if (fid == 1) { @@ -1338,7 +1338,7 @@ tmp_args (0) = 0.0; for (int i = 0; i < nargin; i++) - tmp_args (i+1) = args (i); + tmp_args(i+1) = args(i); return Ffscanf (tmp_args, nargout); } @@ -1404,9 +1404,13 @@ DEFUN (fread, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {[@var{val}, @var{count}] =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\ -Read binary data of type @var{precision} from the specified file ID\n\ -@var{fid}.\n\ +@deftypefn {Built-in Function} {@var{val} =} fread (@var{fid})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip})\n\ +@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\ +@deftypefnx {Built-in Function} {[@var{val}, @var{count}] =} fread (@dots{})\n\ +Read binary data from the specified file ID @var{fid}.\n\ \n\ The optional argument @var{size} specifies the amount of data to read\n\ and may be one of\n\ @@ -1559,8 +1563,8 @@ IEEE little endian.\n\ @end table\n\ \n\ -The data read from the file is returned in @var{val}, and the number of\n\ -values read is returned in @code{count}\n\ +The output argument @var{val} contains the data read from the file.\n\ +The optional return value @var{count} contains the number of elements read.\n\ @seealso{fwrite, fgets, fgetl, fscanf, fopen}\n\ @end deftypefn") { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/find.cc --- a/libinterp/corefcn/find.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/find.cc Sun May 25 10:29:05 2014 -0700 @@ -61,7 +61,8 @@ case 2: { Array jdx (idx.dims ()); - octave_idx_type n = idx.length (), nr = nda.rows (); + octave_idx_type n = idx.length (); + octave_idx_type nr = nda.rows (); for (octave_idx_type i = 0; i < n; i++) { jdx.xelem (i) = idx.xelem (i) / nr; @@ -165,7 +166,7 @@ // Search for elements to return. Only search the region where there // are elements to be found using the count that we want to find. for (octave_idx_type j = start_nc, cx = 0; j < end_nc; j++) - for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++ ) + for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++) { OCTAVE_QUIT; if (direction < 0 && i < nz - count) @@ -241,7 +242,6 @@ if (n_to_find < 0 || n_to_find >= nc) { start_nc = 0; - n_to_find = nc; count = nc; } else if (direction > 0) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/gcd.cc --- a/libinterp/corefcn/gcd.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/gcd.cc Sun May 25 10:29:05 2014 -0700 @@ -125,8 +125,9 @@ double aa = fabs (a); double bb = fabs (b); - double xx = 0, yy = 1; - double lx = 1, ly = 0; + double xx, lx, yy, ly; + xx = 0, lx = 1; + yy = 1, ly = 0; while (bb != 0) { @@ -161,7 +162,8 @@ (*current_liboctave_error_handler) ("gcd: all complex parts must be integers"); - std::complex aa = a, bb = b; + std::complex aa = a; + std::complex bb = b; bool swapped = false; if (abs (aa) < abs (bb)) { @@ -169,8 +171,9 @@ swapped = true; } - std::complex xx = 0, lx = 1; - std::complex yy = 1, ly = 0; + std::complex xx, lx, yy, ly; + xx = 0, lx = 1; + yy = 1, ly = 0; while (abs(bb) != 0) { @@ -204,8 +207,9 @@ { T aa = a.abs ().value (); T bb = b.abs ().value (); - T xx = 0, lx = 1; - T yy = 1, ly = 0; + T xx, lx, yy, ly; + xx = 0, lx = 1; + yy = 1, ly = 0; while (bb != 0) { @@ -347,7 +351,8 @@ bool incb = bb.numel () != 1; T *gptr = gg.fortran_vec (); - T *xptr = xx.fortran_vec (), *yptr = yy.fortran_vec (); + T *xptr = xx.fortran_vec (); + T *yptr = yy.fortran_vec (); octave_idx_type n = gg.numel (); for (octave_idx_type i = 0; i < n; i++) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/gl-render.cc --- a/libinterp/corefcn/gl-render.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/gl-render.cc Sun May 25 10:29:05 2014 -0700 @@ -37,6 +37,28 @@ #define LIGHT_MODE GL_FRONT_AND_BACK +// Use symbolic names for axes +enum { + X_AXIS, + Y_AXIS, + Z_AXIS +}; + +// Use symbolic names for color mode +enum { + UNIFORM, + FLAT, + INTERP, + TEXTURE +}; + +// Use symbolic names for lighting +enum { + NONE, + //FLAT, // Already declared in anonymous enum for color mode + GOURAUD = 2 +}; + // Win32 API requires the CALLBACK attributes for // GLU callback functions. Define it to empty on // other platforms. @@ -147,7 +169,8 @@ { // FIXME: dim_vectors hold octave_idx_type values. // Should we check for dimensions larger than intmax? - int h = dv(0), w = dv(1), tw, th; + int h, w, tw, th; + h = dv(0), w = dv(1); GLuint id; bool ok = true; @@ -400,7 +423,7 @@ opengl_renderer::patch_tesselator : public opengl_tesselator { public: - patch_tesselator (opengl_renderer *r, int cmode, int lmode, int idx = 0) + patch_tesselator (opengl_renderer *r, int cmode, int lmode, float idx = 0.0) : opengl_tesselator (), renderer (r), color_mode (cmode), light_mode (lmode), index (idx), first (true), tmp_vdata () @@ -412,13 +435,13 @@ //printf ("patch_tesselator::begin (%d)\n", type); first = true; - if (color_mode == 2 || light_mode == 2) + if (color_mode == INTERP || light_mode == GOURAUD) glShadeModel (GL_SMOOTH); else glShadeModel (GL_FLAT); if (is_filled ()) - renderer->set_polygon_offset (true, 1+index); + renderer->set_polygon_offset (true, index); glBegin (type); } @@ -436,12 +459,10 @@ = reinterpret_cast (data); //printf ("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2)); - // FIXME: why did I need to keep the first vertex of the face - // in JHandles? I think it's related to the fact that the - // tessellation process might re-order the vertices, such that - // the first one you get here might not be the first one of the face; - // but I can't figure out the actual reason. - if (color_mode > 0 && (first || color_mode == 2)) + // NOTE: OpenGL can re-order vertices. For "flat" coloring of FaceColor + // the first vertex must be identified in the draw_patch routine. + + if (color_mode == INTERP || (color_mode == FLAT && ! is_filled ())) { Matrix col = v->color; @@ -458,12 +479,12 @@ for (int k = 0; k < 3; k++) buf[k] = (v->diffuse * col(k)); - glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf); + glMaterialfv (LIGHT_MODE, GL_DIFFUSE, buf); } } } - if (light_mode > 0 && (first || light_mode == 2)) + if (light_mode > 0 && (first || light_mode == GOURAUD)) glNormal3dv (v->normal.data ()); glVertex3dv (v->coords.data ()); @@ -471,8 +492,7 @@ first = false; } - void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], - void **out_data) + void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data) { //printf ("patch_tesselator::combine\n"); @@ -530,8 +550,8 @@ patch_tesselator& operator = (const patch_tesselator&); opengl_renderer *renderer; - int color_mode; // 0: uni, 1: flat, 2: interp - int light_mode; // 0: none, 1: flat, 2: gouraud + int color_mode; + int light_mode; int index; bool first; std::list tmp_vdata; @@ -624,7 +644,17 @@ if (enhanced) { glEnable (GL_BLEND); - glEnable (GL_LINE_SMOOTH); + glEnable (GL_MULTISAMPLE); + GLint iMultiSample, iNumSamples; + glGetIntegerv (GL_SAMPLE_BUFFERS, &iMultiSample); + glGetIntegerv (GL_SAMPLES, &iNumSamples); + if (iMultiSample != GL_TRUE || iNumSamples == 0) + { + // MultiSample not implemented. Use old-style anti-aliasing + glDisable (GL_MULTISAMPLE); + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + } } else { @@ -654,7 +684,7 @@ double val = ticks(i); if (lim1 <= val && val <= lim2) { - if (xyz == 0) // X + if (xyz == X_AXIS) { glVertex3d (val, p1N, p2); glVertex3d (val, p1, p2); @@ -664,7 +694,7 @@ glVertex3d (val, p1, p2); } } - else if (xyz == 1) // Y + else if (xyz == Y_AXIS) { glVertex3d (p1N, val, p2); glVertex3d (p1, val, p2); @@ -674,7 +704,7 @@ glVertex3d (p1, val, p2); } } - else if (xyz == 2) // Z + else if (xyz == Z_AXIS) { glVertex3d (p1N, p2, val); glVertex3d (p1, p2, val); @@ -703,7 +733,7 @@ if (lim1 <= val && val <= lim2) { - if (xyz == 0) // X + if (xyz == X_AXIS) { glVertex3d (val, p1, p2); glVertex3d (val, p1+dy, p2+dz); @@ -713,7 +743,7 @@ glVertex3d (val, p1N-dy, p2N-dz); } } - else if (xyz == 1) // Y + else if (xyz == Y_AXIS) { glVertex3d (p1, val, p2); glVertex3d (p1+dx, val, p2+dz); @@ -723,7 +753,7 @@ glVertex3d (p1N-dx, val, p2N-dz); } } - else if (xyz == 2) // Z + else if (xyz == Z_AXIS) { glVertex3d (p1, p2, val); glVertex3d (p1+dx, p2+dy, val); @@ -765,17 +795,17 @@ label.erase (0, label.find_first_not_of (" ")); label = label.substr (0, label.find_last_not_of (" ")+1); - // FIXME: as tick text is transparent, shouldn't it be + // FIXME: As tick text is transparent, shouldn't it be // drawn after axes object, for correct rendering? - if (xyz == 0) // X + if (xyz == X_AXIS) { b = render_text (label, val, p1, p2, ha, va); } - else if (xyz == 1) // Y + else if (xyz == Y_AXIS) { b = render_text (label, p1, val, p2, ha, va); } - else if (xyz == 2) // Z + else if (xyz == Z_AXIS) { b = render_text (label, p1, p2, val, ha, va); } @@ -819,8 +849,6 @@ glClear (GL_DEPTH_BUFFER_BIT); - glDisable (GL_LINE_SMOOTH); - // store axes transformation data xform = props.get_transform (); @@ -829,6 +857,10 @@ void opengl_renderer::draw_axes_planes (const axes::properties& props) { + Matrix axe_color = props.get_color_rgb (); + if (axe_color.numel () == 0 || ! props.is_visible ()) + return; + double xPlane = props.get_xPlane (); double yPlane = props.get_yPlane (); double zPlane = props.get_zPlane (); @@ -837,42 +869,43 @@ double zPlaneN = props.get_zPlaneN (); // Axes planes - Matrix axe_color = props.get_color_rgb (); - if (axe_color.numel () > 0 && props.is_visible ()) - { - set_color (axe_color); - set_polygon_offset (true, 2.5); - - glBegin (GL_QUADS); - - // X plane - glVertex3d (xPlane, yPlaneN, zPlaneN); - glVertex3d (xPlane, yPlane, zPlaneN); - glVertex3d (xPlane, yPlane, zPlane); - glVertex3d (xPlane, yPlaneN, zPlane); - - // Y plane - glVertex3d (xPlaneN, yPlane, zPlaneN); - glVertex3d (xPlane, yPlane, zPlaneN); - glVertex3d (xPlane, yPlane, zPlane); - glVertex3d (xPlaneN, yPlane, zPlane); - - // Z plane - glVertex3d (xPlaneN, yPlaneN, zPlane); - glVertex3d (xPlane, yPlaneN, zPlane); - glVertex3d (xPlane, yPlane, zPlane); - glVertex3d (xPlaneN, yPlane, zPlane); - - glEnd (); - - set_polygon_offset (false); - } + set_color (axe_color); + set_polygon_offset (true, 2.5); + + glBegin (GL_QUADS); + + // X plane + glVertex3d (xPlane, yPlaneN, zPlaneN); + glVertex3d (xPlane, yPlane, zPlaneN); + glVertex3d (xPlane, yPlane, zPlane); + glVertex3d (xPlane, yPlaneN, zPlane); + + // Y plane + glVertex3d (xPlaneN, yPlane, zPlaneN); + glVertex3d (xPlane, yPlane, zPlaneN); + glVertex3d (xPlane, yPlane, zPlane); + glVertex3d (xPlaneN, yPlane, zPlane); + + // Z plane + glVertex3d (xPlaneN, yPlaneN, zPlane); + glVertex3d (xPlane, yPlaneN, zPlane); + glVertex3d (xPlane, yPlane, zPlane); + glVertex3d (xPlaneN, yPlane, zPlane); + + glEnd (); + + set_polygon_offset (false); } void opengl_renderer::draw_axes_boxes (const axes::properties& props) { + if (! props.is_visible ()) + return; + bool xySym = props.get_xySym (); + bool layer2Dtop = props.get_layer2Dtop (); + bool is2d = props.get_is2D (); double xPlane = props.get_xPlane (); double yPlane = props.get_yPlane (); double zPlane = props.get_zPlane (); @@ -893,106 +926,114 @@ set_linestyle ("-", true); set_linewidth (props.get_linewidth ()); - if (props.is_visible ()) + glBegin (GL_LINES); + + if (layer2Dtop) + std::swap (zpTick, zpTickN); + + // X box + set_color (props.get_xcolor_rgb ()); + glVertex3d (xPlaneN, ypTick, zpTick); + glVertex3d (xPlane, ypTick, zpTick); + + if (props.is_box ()) { - glBegin (GL_LINES); - - // X box - set_color (props.get_xcolor_rgb ()); - glVertex3d (xPlaneN, ypTick, zpTick); - glVertex3d (xPlane, ypTick, zpTick); - - if (props.is_box ()) + glVertex3d (xPlaneN, ypTickN, zpTick); + glVertex3d (xPlane, ypTickN, zpTick); + if (! is2d) { - glVertex3d (xPlaneN, ypTickN, zpTick); - glVertex3d (xPlane, ypTickN, zpTick); glVertex3d (xPlaneN, ypTickN, zpTickN); glVertex3d (xPlane, ypTickN, zpTickN); glVertex3d (xPlaneN, ypTick, zpTickN); glVertex3d (xPlane, ypTick, zpTickN); } - - // Y box - set_color (props.get_ycolor_rgb ()); - glVertex3d (xpTick, yPlaneN, zpTick); - glVertex3d (xpTick, yPlane, zpTick); - - if (props.is_box () && ! plotyy) + } + + // Y box + set_color (props.get_ycolor_rgb ()); + glVertex3d (xpTick, yPlaneN, zpTick); + glVertex3d (xpTick, yPlane, zpTick); + + if (props.is_box () && ! plotyy) + { + glVertex3d (xpTickN, yPlaneN, zpTick); + glVertex3d (xpTickN, yPlane, zpTick); + + if (! is2d) { - glVertex3d (xpTickN, yPlaneN, zpTick); - glVertex3d (xpTickN, yPlane, zpTick); glVertex3d (xpTickN, yPlaneN, zpTickN); glVertex3d (xpTickN, yPlane, zpTickN); glVertex3d (xpTick, yPlaneN, zpTickN); glVertex3d (xpTick, yPlane, zpTickN); } - - // Z box - set_color (props.get_zcolor_rgb ()); + } + + // Z box + set_color (props.get_zcolor_rgb ()); + + if (xySym) + { + glVertex3d (xPlaneN, yPlane, zPlaneN); + glVertex3d (xPlaneN, yPlane, zPlane); + } + else + { + glVertex3d (xPlane, yPlaneN, zPlaneN); + glVertex3d (xPlane, yPlaneN, zPlane); + } + + if (props.is_box ()) + { + glVertex3d (xPlane, yPlane, zPlaneN); + glVertex3d (xPlane, yPlane, zPlane); if (xySym) { - glVertex3d (xPlaneN, yPlane, zPlaneN); - glVertex3d (xPlaneN, yPlane, zPlane); - } - else - { glVertex3d (xPlane, yPlaneN, zPlaneN); glVertex3d (xPlane, yPlaneN, zPlane); } - - if (props.is_box ()) + else { - glVertex3d (xPlane, yPlane, zPlaneN); - glVertex3d (xPlane, yPlane, zPlane); - - if (xySym) - { - glVertex3d (xPlane, yPlaneN, zPlaneN); - glVertex3d (xPlane, yPlaneN, zPlane); - } - else - { - glVertex3d (xPlaneN, yPlane, zPlaneN); - glVertex3d (xPlaneN, yPlane, zPlane); - } - - glVertex3d (xPlaneN, yPlaneN, zPlaneN); - glVertex3d (xPlaneN, yPlaneN, zPlane); + glVertex3d (xPlaneN, yPlane, zPlaneN); + glVertex3d (xPlaneN, yPlane, zPlane); } - glEnd (); + glVertex3d (xPlaneN, yPlaneN, zPlaneN); + glVertex3d (xPlaneN, yPlaneN, zPlane); } + + glEnd (); } void opengl_renderer::draw_axes_x_grid (const axes::properties& props) { int xstate = props.get_xstate (); - int zstate = props.get_zstate (); - bool x2Dtop = props.get_x2Dtop (); - bool layer2Dtop = props.get_layer2Dtop (); - bool xyzSym = props.get_xyzSym (); - bool nearhoriz = props.get_nearhoriz (); - double xticklen = props.get_xticklen (); - double xtickoffset = props.get_xtickoffset (); - double fy = props.get_fy (); - double fz = props.get_fz (); - double x_min = props.get_x_min (); - double x_max = props.get_x_max (); - double yPlane = props.get_yPlane (); - double yPlaneN = props.get_yPlaneN (); - double ypTick = props.get_ypTick (); - double ypTickN = props.get_ypTickN (); - double zPlane = props.get_zPlane (); - double zPlaneN = props.get_zPlaneN (); - double zpTick = props.get_zpTick (); - double zpTickN = props.get_zpTickN (); - - // X grid if (props.is_visible () && xstate != AXE_DEPTH_DIR) { + int zstate = props.get_zstate (); + bool x2Dtop = props.get_x2Dtop (); + bool layer2Dtop = props.get_layer2Dtop (); + bool xyzSym = props.get_xyzSym (); + bool nearhoriz = props.get_nearhoriz (); + double xticklen = props.get_xticklen (); + double xtickoffset = props.get_xtickoffset (); + double fy = props.get_fy (); + double fz = props.get_fz (); + double x_min = props.get_x_min (); + double x_max = props.get_x_max (); + double yPlane = props.get_yPlane (); + double yPlaneN = props.get_yPlaneN (); + double ypTick = props.get_ypTick (); + double ypTickN = props.get_ypTickN (); + double zPlane = props.get_zPlane (); + double zPlaneN = props.get_zPlaneN (); + double zpTick = props.get_zpTick (); + double zpTickN = props.get_zpTickN (); + + // X grid + std::string gridstyle = props.get_gridlinestyle (); std::string minorgridstyle = props.get_minorgridlinestyle (); bool do_xgrid = (props.is_xgrid () && (gridstyle != "none")); @@ -1002,7 +1043,8 @@ Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ()); Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ()); string_vector xticklabels = props.get_xticklabel ().all_strings (); - int wmax = 0, hmax = 0; + int wmax = 0; + int hmax = 0; bool tick_along_z = nearhoriz || xisinf (fy); bool mirror = props.is_box () && xstate != AXE_ANY_DIR; @@ -1077,30 +1119,31 @@ opengl_renderer::draw_axes_y_grid (const axes::properties& props) { int ystate = props.get_ystate (); - int zstate = props.get_zstate (); - bool y2Dright = props.get_y2Dright (); - bool layer2Dtop = props.get_layer2Dtop (); - bool xyzSym = props.get_xyzSym (); - bool nearhoriz = props.get_nearhoriz (); - double yticklen = props.get_yticklen (); - double ytickoffset = props.get_ytickoffset (); - double fx = props.get_fx (); - double fz = props.get_fz (); - double xPlane = props.get_xPlane (); - double xPlaneN = props.get_xPlaneN (); - double xpTick = props.get_xpTick (); - double xpTickN = props.get_xpTickN (); - double y_min = props.get_y_min (); - double y_max = props.get_y_max (); - double zPlane = props.get_zPlane (); - double zPlaneN = props.get_zPlaneN (); - double zpTick = props.get_zpTick (); - double zpTickN = props.get_zpTickN (); - - // Y grid if (ystate != AXE_DEPTH_DIR && props.is_visible ()) { + int zstate = props.get_zstate (); + bool y2Dright = props.get_y2Dright (); + bool layer2Dtop = props.get_layer2Dtop (); + bool xyzSym = props.get_xyzSym (); + bool nearhoriz = props.get_nearhoriz (); + double yticklen = props.get_yticklen (); + double ytickoffset = props.get_ytickoffset (); + double fx = props.get_fx (); + double fz = props.get_fz (); + double xPlane = props.get_xPlane (); + double xPlaneN = props.get_xPlaneN (); + double xpTick = props.get_xpTick (); + double xpTickN = props.get_xpTickN (); + double y_min = props.get_y_min (); + double y_max = props.get_y_max (); + double zPlane = props.get_zPlane (); + double zPlaneN = props.get_zPlaneN (); + double zpTick = props.get_zpTick (); + double zpTickN = props.get_zpTickN (); + + // Y grid + std::string gridstyle = props.get_gridlinestyle (); std::string minorgridstyle = props.get_minorgridlinestyle (); bool do_ygrid = (props.is_ygrid () && (gridstyle != "none")); @@ -1110,7 +1153,8 @@ Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ()); Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ()); string_vector yticklabels = props.get_yticklabel ().all_strings (); - int wmax = 0, hmax = 0; + int wmax = 0; + int hmax = 0; bool tick_along_z = nearhoriz || xisinf (fx); bool mirror = props.is_box () && ystate != AXE_ANY_DIR && (! props.has_property ("__plotyy_axes__")); @@ -1183,23 +1227,24 @@ opengl_renderer::draw_axes_z_grid (const axes::properties& props) { int zstate = props.get_zstate (); - bool xySym = props.get_xySym (); - bool zSign = props.get_zSign (); - double zticklen = props.get_zticklen (); - double ztickoffset = props.get_ztickoffset (); - double fx = props.get_fx (); - double fy = props.get_fy (); - double xPlane = props.get_xPlane (); - double xPlaneN = props.get_xPlaneN (); - double yPlane = props.get_yPlane (); - double yPlaneN = props.get_yPlaneN (); - double z_min = props.get_z_min (); - double z_max = props.get_z_max (); - - // Z Grid if (zstate != AXE_DEPTH_DIR && props.is_visible ()) { + bool xySym = props.get_xySym (); + bool zSign = props.get_zSign (); + double zticklen = props.get_zticklen (); + double ztickoffset = props.get_ztickoffset (); + double fx = props.get_fx (); + double fy = props.get_fy (); + double xPlane = props.get_xPlane (); + double xPlaneN = props.get_xPlaneN (); + double yPlane = props.get_yPlane (); + double yPlaneN = props.get_yPlaneN (); + double z_min = props.get_z_min (); + double z_max = props.get_z_max (); + + // Z Grid + std::string gridstyle = props.get_gridlinestyle (); std::string minorgridstyle = props.get_minorgridlinestyle (); bool do_zgrid = (props.is_zgrid () && (gridstyle != "none")); @@ -1209,7 +1254,8 @@ Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ()); Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ()); string_vector zticklabels = props.get_zticklabel ().all_strings (); - int wmax = 0, hmax = 0; + int wmax = 0; + int hmax = 0; bool mirror = props.is_box () && zstate != AXE_ANY_DIR; set_color (props.get_zcolor_rgb ()); @@ -1324,12 +1370,6 @@ { // Children - GLboolean antialias; - glGetBooleanv (GL_LINE_SMOOTH, &antialias); - - if (antialias == GL_TRUE) - glEnable (GL_LINE_SMOOTH); - Matrix children = props.get_all_children (); std::list obj_list; std::list::iterator it; @@ -1337,11 +1377,11 @@ // 1st pass: draw light objects // Start with the last element of the array of child objects to - // display them in the oder they were added to the array. + // display them in the order they were added to the array. for (octave_idx_type i = children.numel () - 1; i >= 0; i--) { - graphics_object go = gh_manager::get_object (children (i)); + graphics_object go = gh_manager::get_object (children(i)); if (go.get_properties ().is_visible ()) { @@ -1407,12 +1447,18 @@ if (x_max > floatmax || y_max > floatmax || z_max > floatmax || x_min < -floatmax || y_min < -floatmax || z_min < -floatmax) { - warning ("gl-render: data values greater than float capacity. (1) Scale data, or (2) Use gnuplot"); + warning ("opengl_renderer: data values greater than float capacity. (1) Scale data, or (2) Use gnuplot"); return; } setup_opengl_transformation (props); + // Disable line smoothing for axes + GLboolean antialias; + glGetBooleanv (GL_LINE_SMOOTH, &antialias); + if (antialias == GL_TRUE) + glDisable (GL_LINE_SMOOTH); + // draw axes object draw_axes_planes (props); @@ -1428,6 +1474,10 @@ set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max); + // Re-enable line smoothing for children + if (antialias == GL_TRUE) + glEnable (GL_LINE_SMOOTH); + draw_axes_children (props); } @@ -1545,7 +1595,7 @@ { if (clip[i] == clip_ok) draw_marker (x(i), y(i), - has_z ? z(i) : static_cast (i) / n, + has_z ? z(i) : 0.0, lc, fc); } @@ -1562,7 +1612,8 @@ const Matrix y = xform.yscale (props.get_ydata ().matrix_value ()); const Matrix z = xform.zscale (props.get_zdata ().matrix_value ()); - int zr = z.rows (), zc = z.columns (); + int zr = z.rows (); + int zc = z.columns (); NDArray c; const NDArray n = props.get_vertexnormals ().array_value (); @@ -1571,7 +1622,7 @@ Matrix a; if (props.facelighting_is ("phong") || props.edgelighting_is ("phong")) - warning ("opengl_renderer::draw: phong light model not supported"); + warning ("opengl_renderer: phong light model not supported"); int fc_mode = (props.facecolor_is_rgb () ? 0 : (props.facecolor_is ("flat") ? 1 : @@ -1589,8 +1640,8 @@ int ea_mode = (props.edgealpha_is_double () ? 0 : (props.edgealpha_is ("flat") ? 1 : 2)); - Matrix fcolor = (fc_mode == 3 ? Matrix (1, 3, 1.0) - : props.get_facecolor_rgb ()); + Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0) + : props.get_facecolor_rgb ()); Matrix ecolor = props.get_edgecolor_rgb (); float as = props.get_ambientstrength (); @@ -1641,16 +1692,16 @@ glMaterialf (LIGHT_MODE, GL_SHININESS, se); } - // FIXME: good candidate for caching, transfering pixel - // data to OpenGL is time consuming. - if (fc_mode == 3) + // FIXME: good candidate for caching, + // transferring pixel data to OpenGL is time consuming. + if (fc_mode == TEXTURE) tex = opengl_texture::create (props.get_color_data ()); if (! props.facecolor_is ("none")) { if (props.get_facealpha_double () == 1) { - if (fc_mode == 0 || fc_mode == 3) + if (fc_mode == UNIFORM || fc_mode == TEXTURE) { glColor3dv (fcolor.data ()); if (fl_mode > 0) @@ -1667,9 +1718,10 @@ if (fl_mode > 0) glEnable (GL_LIGHTING); - glShadeModel ((fc_mode == 2 || fl_mode == 2) ? GL_SMOOTH : GL_FLAT); + glShadeModel ((fc_mode == INTERP || fl_mode == GOURAUD) ? GL_SMOOTH + : GL_FLAT); set_polygon_offset (true, 1); - if (fc_mode == 3) + if (fc_mode == TEXTURE) glEnable (GL_TEXTURE_2D); for (int i = 1; i < zc; i++) @@ -1687,13 +1739,13 @@ || clip(j-1, i) || clip(j, i)) continue; - if (fc_mode == 1) + if (fc_mode == FLAT) { // "flat" only needs color at lower-left vertex if (! xfinite (c(j-1,i-1))) continue; } - else if (fc_mode == 2) + else if (fc_mode == INTERP) { // "interp" needs valid color at all 4 vertices if (! (xfinite (c(j-1, i-1)) && xfinite (c(j, i-1)) @@ -1710,7 +1762,7 @@ glBegin (GL_QUADS); // Vertex 1 - if (fc_mode == 3) + if (fc_mode == TEXTURE) tex.tex_coord (double (i-1) / (zc-1), double (j-1) / (zr-1)); else if (fc_mode > 0) @@ -1743,9 +1795,9 @@ glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1)); // Vertex 2 - if (fc_mode == 3) + if (fc_mode == TEXTURE) tex.tex_coord (double (i) / (zc-1), double (j-1) / (zr-1)); - else if (fc_mode == 2) + else if (fc_mode == INTERP) { for (int k = 0; k < 3; k++) cb[k] = c(j-1, i, k); @@ -1763,7 +1815,7 @@ } } - if (fl_mode == 2) + if (fl_mode == GOURAUD) { d = sqrt (n(j-1,i,0) * n(j-1,i,0) + n(j-1,i,1) * n(j-1,i,1) @@ -1774,9 +1826,9 @@ glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i)); // Vertex 3 - if (fc_mode == 3) + if (fc_mode == TEXTURE) tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1)); - else if (fc_mode == 2) + else if (fc_mode == INTERP) { for (int k = 0; k < 3; k++) cb[k] = c(j, i, k); @@ -1793,7 +1845,7 @@ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); } } - if (fl_mode == 2) + if (fl_mode == GOURAUD) { d = sqrt (n(j,i,0) * n(j,i,0) + n(j,i,1) * n(j,i,1) @@ -1803,9 +1855,9 @@ glVertex3d (x(j2,i), y(j,i2), z(j,i)); // Vertex 4 - if (fc_mode == 3) + if (fc_mode == TEXTURE) tex.tex_coord (double (i-1) / (zc-1), double (j) / (zr-1)); - else if (fc_mode == 2) + else if (fc_mode == INTERP) { for (int k = 0; k < 3; k++) cb[k] = c(j, i-1, k); @@ -1822,7 +1874,7 @@ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); } } - if (fl_mode == 2) + if (fl_mode == GOURAUD) { d = sqrt (n(j,i-1,0) * n(j,i-1,0) + n(j,i-1,1) * n(j,i-1,1) @@ -1836,7 +1888,7 @@ } set_polygon_offset (false); - if (fc_mode == 3) + if (fc_mode == TEXTURE) glDisable (GL_TEXTURE_2D); if (fl_mode > 0) @@ -1852,7 +1904,7 @@ { if (props.get_edgealpha_double () == 1) { - if (ec_mode == 0) + if (ec_mode == UNIFORM) { glColor3dv (ecolor.data ()); if (fl_mode > 0) @@ -1869,7 +1921,8 @@ if (el_mode > 0) glEnable (GL_LIGHTING); - glShadeModel ((ec_mode == 2 || el_mode == 2) ? GL_SMOOTH : GL_FLAT); + glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD) ? GL_SMOOTH + : GL_FLAT); set_linestyle (props.get_linestyle (), false); set_linewidth (props.get_linewidth ()); @@ -1891,13 +1944,13 @@ if (clip(j-1,i) || clip(j,i)) continue; - if (ec_mode == 1) + if (ec_mode == FLAT) { // "flat" only needs color at lower-left vertex if (! xfinite (c(j-1,i))) continue; } - else if (ec_mode == 2) + else if (ec_mode == INTERP) { // "interp" needs valid color at both vertices if (! (xfinite (c(j-1, i)) && xfinite (c(j, i)))) @@ -1940,7 +1993,7 @@ glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i)); // Vertex 2 - if (ec_mode == 2) + if (ec_mode == INTERP) { for (int k = 0; k < 3; k++) cb[k] = c(j, i, k); @@ -1957,7 +2010,7 @@ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); } } - if (el_mode == 2) + if (el_mode == GOURAUD) { d = sqrt (n(j,i,0) * n(j,i,0) + n(j,i,1) * n(j,i,1) @@ -1988,13 +2041,13 @@ if (clip(j,i-1) || clip(j,i)) continue; - if (ec_mode == 1) + if (ec_mode == FLAT) { // "flat" only needs color at lower-left vertex if (! xfinite (c(j,i-1))) continue; } - else if (ec_mode == 2) + else if (ec_mode == INTERP) { // "interp" needs valid color at both vertices if (! (xfinite (c(j, i-1)) && xfinite (c(j, i)))) @@ -2037,7 +2090,7 @@ glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1)); // Vertex 2 - if (ec_mode == 2) + if (ec_mode == INTERP) { for (int k = 0; k < 3; k++) cb[k] = c(j, i, k); @@ -2054,7 +2107,7 @@ glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); } } - if (el_mode == 2) + if (el_mode == GOURAUD) { d = sqrt (n(j,i,0) * n(j,i,0) + n(j,i,1) * n(j,i,1) @@ -2150,8 +2203,8 @@ } } -// FIXME: global optimization (rendering, data structures...), there -// is probably a smarter/faster/less-memory-consuming way to do this. +// FIXME: global optimization (rendering, data structures...), +// there is probably a smarter/faster/less-memory-consuming way to do this. void opengl_renderer::draw_patch (const patch::properties &props) { @@ -2228,13 +2281,13 @@ if (fc_mode > 0) { fcolor = c; - fc_mode = 0; + fc_mode = UNIFORM; } if (ec_mode > 0) { ecolor = c; - ec_mode = 0; + ec_mode = UNIFORM; } c = Matrix (); @@ -2260,7 +2313,7 @@ Matrix vv (1, 3, 0.0); Matrix cc; - Matrix nn(1, 3, 0.0); + Matrix nn (1, 3, 0.0); double aa = 1.0; vv(0) = v(idx,0); vv(1) = v(idx,1); @@ -2284,8 +2337,7 @@ aa = a(idx); } - vdata[i+j*fr] = - vertex_data (vv, cc, nn, aa, as, ds, ss, se); + vdata[i+j*fr] = vertex_data (vv, cc, nn, aa, as, ds, ss, se); } if (fl_mode > 0 || el_mode > 0) @@ -2301,7 +2353,7 @@ // FIXME: adapt to double-radio property if (props.get_facealpha_double () == 1) { - if (fc_mode == 0) + if (fc_mode == UNIFORM) { glColor3dv (fcolor.data ()); if (fl_mode > 0) @@ -2321,8 +2373,11 @@ if (fl_mode > 0) glEnable (GL_LIGHTING); - // FIXME: use __index__ property from patch object - patch_tesselator tess (this, fc_mode, fl_mode, 0); + // NOTE: Push filled part of patch backwards to avoid Z-fighting with + // tesselator outline. A value of 1.0 seems to work fine. Value + // can't be too large or the patch will be pushed below the axes + // planes at +2.5. + patch_tesselator tess (this, fc_mode, fl_mode, 1.0); for (int i = 0; i < nf; i++) { @@ -2332,13 +2387,44 @@ tess.begin_polygon (true); tess.begin_contour (); - for (int j = 0; j < count_f(i); j++) + // Add vertices in reverse order for Matlab compatibility + for (int j = count_f(i)-1; j > 0; j--) { vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep (); tess.add_vertex (vv->coords.fortran_vec (), vv); } + if (count_f(i) > 0) + { + vertex_data::vertex_data_rep *vv = vdata[i].get_rep (); + + if (fc_mode == FLAT) + { + // For "flat" shading, use color of 1st vertex. + Matrix col = vv->color; + + if (col.numel () == 3) + { + glColor3dv (col.data ()); + if (fl_mode > 0) + { + float cb[4] = { 0, 0, 0, 1 }; + + for (int k = 0; k < 3; k++) + cb[k] = (vv->ambient * col(k)); + glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int k = 0; k < 3; k++) + cb[k] = (vv->diffuse * col(k)); + glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + } + } + } + + tess.add_vertex (vv->coords.fortran_vec (), vv); + } + tess.end_contour (); tess.end_polygon (); } @@ -2357,7 +2443,7 @@ // FIXME: adapt to double-radio property if (props.get_edgealpha_double () == 1) { - if (ec_mode == 0) + if (ec_mode == UNIFORM) { glColor3dv (ecolor.data ()); if (el_mode > 0) @@ -2380,16 +2466,18 @@ set_linestyle (props.get_linestyle (), false); set_linewidth (props.get_linewidth ()); - - // FIXME: use __index__ property from patch object; should we - // offset patch contour as well? + // NOTE: patch contour cannot be offset. Offset must occur with the + // filled portion of the patch above. The tesselator uses + // GLU_TESS_BOUNDARY_ONLY to get the outline of the patch and OpenGL + // automatically sets the glType to GL_LINE_LOOP. This primitive is + // not supported by glPolygonOffset which is used to do Z offsets. patch_tesselator tess (this, ec_mode, el_mode); for (int i = 0; i < nf; i++) { if (clip_f(i)) { - // This is an unclosed contour. Draw it as a line + // This is an unclosed contour. Draw it as a line. bool flag = false; for (int j = 0; j < count_f(i); j++) @@ -2421,7 +2509,7 @@ tess.begin_polygon (false); tess.begin_contour (); - for (int j = 0; j < count_f(i); j++) + for (int j = count_f(i)-1; j >= 0; j--) { vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep (); @@ -2552,7 +2640,8 @@ { octave_value cdata = props.get_color_data (); dim_vector dv (cdata.dims ()); - int h = dv(0), w = dv(1); + int h = dv(0); + int w = dv(1); Matrix x = props.get_xdata ().matrix_value (); Matrix y = props.get_ydata ().matrix_value (); @@ -2572,7 +2661,7 @@ if (xisnan (p0(0)) || xisnan (p0(1)) || xisnan (p1(0)) || xisnan (p1(1))) { - warning ("gl-render: image x,y data too large to draw"); + warning ("opengl_renderer: image X,Y data too large to draw"); return; } @@ -2605,13 +2694,12 @@ nor_dy = 1; } - - // OpenGL won't draw the image if it's origin is outside the - // viewport/clipping plane so we must do the clipping - // ourselfes - only draw part of the image - - int j0 = 0, j1 = w; - int i0 = 0, i1 = h; + // OpenGL won't draw any of the image if it's origin is outside the + // viewport/clipping plane so we must do the clipping ourselves. + + int j0, j1, i0, i1; + j0 = 0, j1 = w; + i0 = 0, i1 = h; float im_xmin = x(0) - nor_dx/2; float im_xmax = x(1) + nor_dx/2; @@ -2644,7 +2732,7 @@ glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0); // by default this is 4 - glPixelStorei (GL_UNPACK_ALIGNMENT,1); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // Expect RGB data if (dv.length () == 3 && dv(2) == 3) @@ -2668,6 +2756,44 @@ draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a); } + else if (cdata.is_single_type ()) + { + const FloatNDArray xcdata = cdata.float_array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + a[idx] = xcdata(i,j,0); + a[idx+1] = xcdata(i,j,1); + a[idx+2] = xcdata(i,j,2); + } + } + + draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a); + + } + else if (cdata.is_uint8_type ()) + { + const uint8NDArray xcdata = cdata.uint8_array_value (); + + OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + a[idx] = xcdata(i,j,0); + a[idx+1] = xcdata(i,j,1); + a[idx+2] = xcdata(i,j,2); + } + } + + draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a); + + } else if (cdata.is_uint16_type ()) { const uint16NDArray xcdata = cdata.uint16_array_value (); @@ -2687,29 +2813,11 @@ draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a); } - else if (cdata.is_uint8_type ()) - { - const uint8NDArray xcdata = cdata.uint8_array_value (); - - OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - a[idx] = xcdata(i,j,0); - a[idx+1] = xcdata(i,j,1); - a[idx+2] = xcdata(i,j,2); - } - } - - draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a); - } else - warning ("opengl_texture::draw: invalid image data type (expected double, uint16, or uint8)"); + warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)"); } else - warning ("opengl_texture::draw: invalid image size (expected n*m*3 or n*m)"); + warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)"); glPixelZoom (1, 1); } @@ -2748,13 +2856,13 @@ } void -opengl_renderer::set_polygon_offset (bool on, double offset) +opengl_renderer::set_polygon_offset (bool on, float offset) { if (on) { - glPolygonOffset (offset, offset); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_POLYGON_OFFSET_LINE); + glPolygonOffset (offset, offset); } else { @@ -2934,30 +3042,30 @@ { case '+': glBegin (GL_LINES); - glVertex2f (-sz/2, 0); - glVertex2f (sz/2, 0); - glVertex2f (0, -sz/2); - glVertex2f (0, sz/2); + glVertex2d (-sz/2, 0); + glVertex2d (sz/2, 0); + glVertex2d (0, -sz/2); + glVertex2d (0, sz/2); glEnd (); break; case 'x': glBegin (GL_LINES); - glVertex2f (-sz/2, -sz/2); - glVertex2f (sz/2, sz/2); - glVertex2f (-sz/2, sz/2); - glVertex2f (sz/2, -sz/2); + glVertex2d (-sz/2, -sz/2); + glVertex2d (sz/2, sz/2); + glVertex2d (-sz/2, sz/2); + glVertex2d (sz/2, -sz/2); glEnd (); break; case '*': glBegin (GL_LINES); - glVertex2f (-sz/2, 0); - glVertex2f (sz/2, 0); - glVertex2f (0, -sz/2); - glVertex2f (0, sz/2); - glVertex2f (-tt, -tt); - glVertex2f (+tt, +tt); - glVertex2f (-tt, +tt); - glVertex2f (+tt, -tt); + glVertex2d (-sz/2, 0); + glVertex2d (sz/2, 0); + glVertex2d (0, -sz/2); + glVertex2d (0, sz/2); + glVertex2d (-tt, -tt); + glVertex2d (+tt, +tt); + glVertex2d (-tt, +tt); + glVertex2d (+tt, -tt); glEnd (); break; case '.': @@ -2998,30 +3106,30 @@ break; case 'v': glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP)); - glVertex2f (0, sz/2); - glVertex2f (sz/2, -sz/2); - glVertex2f (-sz/2, -sz/2); + glVertex2d (0, sz/2); + glVertex2d (sz/2, -sz/2); + glVertex2d (-sz/2, -sz/2); glEnd (); break; case '^': glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP)); - glVertex2f (0, -sz/2); - glVertex2f (-sz/2, sz/2); - glVertex2f (sz/2, sz/2); + glVertex2d (0, -sz/2); + glVertex2d (-sz/2, sz/2); + glVertex2d (sz/2, sz/2); glEnd (); break; case '>': glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP)); - glVertex2f (sz/2, 0); - glVertex2f (-sz/2, sz/2); - glVertex2f (-sz/2, -sz/2); + glVertex2d (sz/2, 0); + glVertex2d (-sz/2, sz/2); + glVertex2d (-sz/2, -sz/2); glEnd (); break; case '<': glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP)); - glVertex2f (-sz/2, 0); - glVertex2f (sz/2, -sz/2); - glVertex2f (sz/2, sz/2); + glVertex2d (-sz/2, 0); + glVertex2d (sz/2, -sz/2); + glVertex2d (sz/2, sz/2); glEnd (); break; case 'p': @@ -3057,8 +3165,7 @@ } break; default: - warning ("opengl_renderer: unsupported marker '%s'", - marker.c_str ()); + warning ("opengl_renderer: unsupported marker '%s'", marker.c_str ()); break; } @@ -3106,7 +3213,7 @@ return bbox; #else - ::warning ("render_text: cannot render text, Freetype library not available"); + warning ("opengl_renderer: cannot render text, FreeType library not available"); return Matrix (1, 4, 0.0); #endif } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/gl-render.h --- a/libinterp/corefcn/gl-render.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/gl-render.h Sun May 25 10:29:05 2014 -0700 @@ -93,7 +93,7 @@ virtual void setup_opengl_transformation (const axes::properties& props); virtual void set_color (const Matrix& c); - virtual void set_polygon_offset (bool on, double offset = 0.0); + virtual void set_polygon_offset (bool on, float offset = 0.0); virtual void set_linewidth (float w); virtual void set_linestyle (const std::string& s, bool stipple = false); virtual void set_clipbox (double x1, double x2, double y1, double y2, @@ -200,7 +200,7 @@ ColumnVector camera_pos, camera_dir; #if HAVE_FREETYPE - // freetype render, used for text rendering + // FreeType render, used for text rendering ft_render text_renderer; #endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/gl2ps-renderer.cc --- a/libinterp/corefcn/gl2ps-renderer.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/gl2ps-renderer.cc Sun May 25 10:29:05 2014 -0700 @@ -44,7 +44,8 @@ { in_draw = true; - GLint buffsize = 0, state = GL2PS_OVERFLOW; + GLint buffsize = 0; + GLint state = GL2PS_OVERFLOW; GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); @@ -52,8 +53,8 @@ GLint gl2ps_term; if (term.find ("eps") != std::string::npos) gl2ps_term = GL2PS_EPS; else if (term.find ("pdf") != std::string::npos) gl2ps_term = GL2PS_PDF; + else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS; else if (term.find ("svg") != std::string::npos) gl2ps_term = GL2PS_SVG; - else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS; else if (term.find ("pgf") != std::string::npos) gl2ps_term = GL2PS_PGF; else if (term.find ("tex") != std::string::npos) gl2ps_term = GL2PS_TEX; else @@ -67,7 +68,9 @@ // Default sort order optimizes for 3D plots GLint gl2ps_sort = GL2PS_BSP_SORT; - if (term.find ("is2D") != std::string::npos) gl2ps_sort = GL2PS_NO_SORT; + // For 2D plots we can use a simpler Z-depth sorting algorithm + if (term.find ("is2D") != std::string::npos) + gl2ps_sort = GL2PS_SIMPLE_SORT; while (state == GL2PS_OVERFLOW) { @@ -94,7 +97,7 @@ buffsize += 1024*1024; gl2psBeginPage ("glps_renderer figure", "Octave", viewport, gl2ps_term, gl2ps_sort, - (GL2PS_SILENT | GL2PS_SIMPLE_LINE_OFFSET + (GL2PS_SILENT | GL2PS_NO_BLENDING | GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT | gl2ps_text | GL2PS_NO_PS3_SHADING), @@ -158,7 +161,7 @@ alignment_to_mode (ha, va), rotation); // FIXME? - // We have no way of getting a bounding box from gl2ps, so we use freetype. + // We have no way of getting a bounding box from gl2ps, so we use FreeType. Matrix bbox; uint8NDArray pixels; text_to_pixels (txt, pixels, bbox, 0, 0, rotation); @@ -195,7 +198,7 @@ OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*w*h); // Convert to GL_FLOAT as it is the only type gl2ps accepts. - for (unsigned int i = 0; i < 3*w*h; i++) + for (int i = 0; i < 3*w*h; i++) a[i] = data[i] / maxval; gl2psDrawPixels (w, h, 0, 0, format, GL_FLOAT, a); @@ -225,7 +228,8 @@ set_color (props.get_color_rgb ()); const Matrix pos = get_transform ().scale (props.get_data_position ()); - int halign = 0, valign = 0; + int halign = 0; + int valign = 0; if (props.horizontalalignment_is ("center")) halign = 1; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/graphics.cc Sun May 25 10:29:05 2014 -0700 @@ -58,6 +58,7 @@ #include "toplev.h" #include "txt-eng-ft.h" #include "unwind-prot.h" +#include "octave-default-image.h" // forward declarations static octave_value xget (const graphics_handle& h, const caseless_str& name); @@ -255,6 +256,77 @@ } static Matrix +default_image_cdata (void) +{ + Matrix m (64, 64, 0.0); + int i = 0; + for (int col = 0; col < 64; col++) + for (int row = 0; row < 64; row++) + { + m(col,row) = static_cast (default_im_data[i]); + i++; + } + + return m; +} + +static Matrix +default_surface_xdata (void) +{ + Matrix m (3, 3, 0.0); + for (int col = 0; col < 3; col++) + for (int row = 0; row < 3; row++) + m(row,col) = col+1; + + return m; +} + +static Matrix +default_surface_ydata (void) +{ + Matrix m (3, 3, 0.0); + for (int row = 0; row < 3; row++) + for (int col = 0; col < 3; col++) + m(row,col) = row+1; + + return m; +} + +static Matrix +default_surface_zdata (void) +{ + Matrix m (3, 3, 0.0); + for (int row = 0; row < 3; row++) + m(row,row) = 1.0; + return m; +} + +static Matrix +default_surface_cdata (void) +{ + return default_surface_zdata (); +} + +static Matrix +default_patch_faces (void) +{ + Matrix m (1, 3, 1.0); + m(1) = 2.0; + m(2) = 3.0; + return m; +} + +static Matrix +default_patch_vertices (void) +{ + Matrix m (3, 2, 0); + m(1) = 1.0; + m(3) = 1.0; + m(4) = 1.0; + return m; +} + +static Matrix default_axes_position (void) { Matrix m (1, 4, 0.0); @@ -274,6 +346,14 @@ } static Matrix +default_axes_view (void) +{ + Matrix m (1, 2, 0.0); + m(1) = 90.0; + return m; +} + +static Matrix default_axes_tick (void) { Matrix m (1, 6, 0.0); @@ -668,13 +748,13 @@ } static void -convert_cdata_2 (bool is_scaled, double clim_0, double clim_1, +convert_cdata_2 (bool is_scaled, bool is_real, double clim_0, double clim_1, const double *cmapv, double x, octave_idx_type lda, octave_idx_type nc, octave_idx_type i, double *av) { if (is_scaled) x = xround ((nc - 1) * (x - clim_0) / (clim_1 - clim_0)); - else + else if (is_real) x = xround (x - 1); if (xisnan (x)) @@ -700,12 +780,13 @@ template void -convert_cdata_1 (bool is_scaled, double clim_0, double clim_1, +convert_cdata_1 (bool is_scaled, bool is_real, double clim_0, double clim_1, const double *cmapv, const T *cv, octave_idx_type lda, octave_idx_type nc, double *av) { for (octave_idx_type i = 0; i < lda; i++) - convert_cdata_2 (is_scaled, clim_0, clim_1, cmapv, cv[i], lda, nc, i, av); + convert_cdata_2 (is_scaled, is_real, + clim_0, clim_1, cmapv, cv[i], lda, nc, i, av); } static octave_value @@ -714,6 +795,7 @@ { dim_vector dv (cdata.dims ()); + // TrueColor data doesn't require conversion if (dv.length () == cdim && dv(cdim-1) == 3) return cdata; @@ -758,22 +840,34 @@ double clim_0 = clim(0); double clim_1 = clim(1); -#define CONVERT_CDATA_1(ARRAY_T, VAL_FN) \ + // FIXME: There is a lot of processing time spent just on data conversion + // both here in graphics.cc and again in gl-render.cc. There must + // be room for improvement! Here a macro expands to a templated + // function which in turn calls another function (covert_cdata_2). + // And in gl-render.cc (opengl_renderer::draw_image), only GLfloat + // is supported anyways so there is another double for loop across + // height and width to convert all of the input data to GLfloat. + +#define CONVERT_CDATA_1(ARRAY_T, VAL_FN, IS_REAL) \ do \ { \ ARRAY_T tmp = cdata. VAL_FN ## array_value (); \ \ - convert_cdata_1 (is_scaled, clim_0, clim_1, cmapv, \ + convert_cdata_1 (is_scaled, IS_REAL, clim_0, clim_1, cmapv, \ tmp.data (), lda, nc, av); \ } \ while (0) if (cdata.is_uint8_type ()) - CONVERT_CDATA_1 (uint8NDArray, uint8_); + CONVERT_CDATA_1 (uint8NDArray, uint8_, false); + else if (cdata.is_uint16_type ()) + CONVERT_CDATA_1 (uint16NDArray, uint16_, false); + else if (cdata.is_double_type ()) + CONVERT_CDATA_1 (NDArray, , true); else if (cdata.is_single_type ()) - CONVERT_CDATA_1 (FloatNDArray, float_); - else if (cdata.is_double_type ()) - CONVERT_CDATA_1 (NDArray, ); + CONVERT_CDATA_1 (FloatNDArray, float_, true); + else if (cdata.is_bool_type ()) + CONVERT_CDATA_1 (boolNDArray, bool_, false); else error ("unsupported type for cdata (= %s)", cdata.type_name ().c_str ()); @@ -1012,7 +1106,7 @@ for (std::set::const_iterator it = possible_vals.begin (); it != possible_vals.end (); it++) { - if (retval == "") + if (retval.empty ()) { if (*it == default_value ()) retval = "{" + *it + "}"; @@ -1027,8 +1121,10 @@ retval += " | " + *it; } } - if (retval != "") + + if (! retval.empty ()) retval = "[ " + retval + " ]"; + return retval; } @@ -1044,10 +1140,13 @@ } bool -color_values::str2rgb (std::string str) -{ +color_values::str2rgb (const std::string& str_arg) +{ + bool retval = true; + double tmp_rgb[3] = {0, 0, 0}; - bool retval = true; + + std::string str = str_arg; unsigned int len = str.length (); std::transform (str.begin (), str.end (), str.begin (), tolower); @@ -1232,7 +1331,7 @@ // check dimensional size constraints until a match is found for (std::list::const_iterator it = size_constraints.begin (); - ! xok && it != size_constraints.end (); ++it) + ! xok && it != size_constraints.end ();++it) { dim_vector itdims = (*it); @@ -2772,7 +2871,13 @@ // Remove child from current parent graphics_object old_parent_obj; old_parent_obj = gh_manager::get_object (get_parent ()); - old_parent_obj.remove_child (__myhandle__); + + + if (old_parent_obj.get_handle () != hnp) + old_parent_obj.remove_child (__myhandle__); + else + // Do nothing more + return; // Check new parent's parent is not this child to avoid recursion graphics_object new_parent_obj; @@ -2795,6 +2900,18 @@ error ("set: expecting parent to be a graphics handle"); } +/* +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! hax = gca (); +%! set (hax, "parent", gcf ()) +%! assert (gca (), hax) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect +*/ + void base_properties::mark_modified (void) { @@ -2961,10 +3078,12 @@ if (valid_object ()) { octave_map m = get ().map_value (); + graphics_object obj = gh_manager::get_object (get_handle ()); for (octave_map::const_iterator pa = m.begin (); pa != m.end (); pa++) { - if (pa->first != "children") + if (pa->first != "children" && + ! obj.has_readonly_property (pa->first)) { property p = get_properties ().get_property (pa->first); @@ -2976,7 +3095,8 @@ } } } - if (retval != "") + + if (! retval.empty ()) retval += "\n"; } else @@ -2985,6 +3105,35 @@ return retval; } +std::string +base_graphics_object::value_as_string (const std::string& prop) +{ + std::string retval; + + if (valid_object ()) + { + graphics_object obj = gh_manager::get_object (get_handle ()); + + if (prop != "children" && ! obj.has_readonly_property (prop)) + { + property p = get_properties ().get_property (prop); + + if (p.ok () && ! p.is_hidden ()) + { + if (p.is_radio ()) + retval += p.values_as_string (); + } + } + + if (! retval.empty ()) + retval += "\n"; + } + else + error ("base_graphics_object::value_as_string: invalid graphics object"); + + return retval; +} + octave_scalar_map base_graphics_object::values_as_struct (void) { @@ -2993,11 +3142,13 @@ if (valid_object ()) { octave_scalar_map m = get ().scalar_map_value (); + graphics_object obj = gh_manager::get_object (get_handle ()); for (octave_scalar_map::const_iterator pa = m.begin (); pa != m.end (); pa++) { - if (pa->first != "children") + if (pa->first != "children" + && ! obj.has_readonly_property (pa->first)) { property p = get_properties ().get_property (pa->first); @@ -3017,6 +3168,25 @@ return retval; } +/* +%!test +%! hfig = figure ("visible", "off"); +%! unwind_protect +%! hax = axes (); +%! ret = set (hax, "tightinset"); +%! assert (isempty (ret)); +%! ret = set (hax, "type"); +%! assert (isempty (ret)); +%! ret = set (hfig, "__graphics_toolkit__"); +%! assert (isempty (ret)); +%! ret = set (0, "commandwindowsize"); +%! assert (isempty (ret)); +%! ret = set (0); +%! assert (! isfield (ret, "commandwindowsize")); +%! unwind_protect_cleanup +%! close (hfig); +%! end_unwind_protect +*/ graphics_object graphics_object::get_ancestor (const std::string& obj_type) const { @@ -3038,25 +3208,6 @@ // --------------------------------------------------------------------- void -root_figure::properties::set_currentfigure (const octave_value& v) -{ - graphics_handle val (v); - - if (error_state) - return; - - if (xisnan (val.value ()) || is_handle (val)) - { - currentfigure = val; - - if (val.ok ()) - gh_manager::push_figure (val); - } - else - gripe_set_invalid ("currentfigure"); -} - -void root_figure::properties::set_callbackobject (const octave_value& v) { graphics_handle val (v); @@ -3087,6 +3238,189 @@ } void +root_figure::properties::set_currentfigure (const octave_value& v) +{ + graphics_handle val (v); + + if (error_state) + return; + + if (xisnan (val.value ()) || is_handle (val)) + { + currentfigure = val; + + if (val.ok ()) + gh_manager::push_figure (val); + } + else + gripe_set_invalid ("currentfigure"); +} + +std::string +root_figure::properties::get_diary (void) const +{ + bool is_diary_on = F__diarystate__ ()(0).bool_value (); + if (is_diary_on) + return std::string ("on"); + else + return std::string ("off"); +} + +void +root_figure::properties::set_diary (const octave_value& val) +{ + if (! error_state) + { + // Input checking and abrev. matching + diary.set (val, false); + + if (! error_state) + { + Fdiary (ovl (diary.current_value ())); + + diary.run_listeners (); + } + } +} + +std::string +root_figure::properties::get_diaryfile (void) const +{ + return F__diaryfile__ ()(0).string_value (); +} + +void +root_figure::properties::set_diaryfile (const octave_value& val) +{ + if (! error_state) + { + // Input checking and abrev. matching + diaryfile.set (val, false); + + if (! error_state) + { + Fdiary (ovl (diaryfile.string_value ())); + + diaryfile.run_listeners (); + } + } +} + +std::string +root_figure::properties::get_echo (void) const +{ + bool is_echo_on = F__echostate__ ()(0).bool_value (); + if (is_echo_on) + return std::string ("on"); + else + return std::string ("off"); +} + +void +root_figure::properties::set_echo (const octave_value& val) +{ + if (! error_state) + { + // Input checking and abrev. matching + echo.set (val, false); + + if (! error_state) + { + Fecho (ovl (echo.current_value ())); + + echo.run_listeners (); + } + } +} + +std::string +root_figure::properties::get_errormessage (void) const +{ + return Flasterr ()(0).string_value (); +} + +std::string +root_figure::properties::get_format (void) const +{ + return F__formatstring__ ()(0).string_value (); +} + +void +root_figure::properties::set_format (const octave_value& val) +{ + if (! error_state) + { + // Input checking and abrev. matching + format.set (val, false); + + if (! error_state) + { + Fformat (ovl (format.current_value ())); + + format.run_listeners (); + } + } +} + +std::string +root_figure::properties::get_formatspacing (void) const +{ + bool iscompact = F__compactformat__ ()(0).bool_value (); + if (iscompact) + return std::string ("compact"); + else + return std::string ("loose"); +} + +void +root_figure::properties::set_formatspacing (const octave_value& val) +{ + if (! error_state) + { + // Input checking and abrev. matching + formatspacing.set (val, false); + + if (! error_state) + { + std::string strval = formatspacing.current_value (); + + if (strval == "compact") + F__compactformat__ (ovl (true)); + else + F__compactformat__ (ovl (false)); + + formatspacing.run_listeners (); + } + } +} + + +double +root_figure::properties::get_recursionlimit (void) const +{ + return Fmax_recursion_depth ()(0).double_value (); +} + +void +root_figure::properties::set_recursionlimit (const octave_value& val) +{ + if (! error_state) + { + // Input checking and abrev. matching + recursionlimit.set (val, false); + + if (! error_state) + { + double dval = recursionlimit.double_value (); + + Fmax_recursion_depth (ovl (dval)); + + recursionlimit.run_listeners (); + } + } +} + +void figure::properties::set_integerhandle (const octave_value& val) { if (! error_state) @@ -3409,6 +3743,9 @@ position.run_listeners (POSTSET); mark_modified (); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } } @@ -3628,6 +3965,83 @@ return ret; } + +Matrix +figure::properties::get_auto_paperposition (void) +{ + Matrix pos = get_position ().matrix_value (); + Matrix sz; + + caseless_str funits = get_units (); + caseless_str punits = get_paperunits (); + + // Convert position from figure units to paperunits + if (funits == "normalized" || punits == "normalized") + { + sz = screen_size_pixels (); + pos = convert_position (pos, funits, "inches", sz); + + if (punits == "normalized") + sz = papersize_from_type ("points", get_papertype ()); + + pos = convert_position (pos, "inches", punits, sz); + } + else + pos = convert_position (pos, funits, punits, sz); + + // Center the figure on the page + sz = get_papersize ().matrix_value (); + + pos(0) = sz(0)/2 - pos(2)/2; + pos(1) = sz(1)/2 - pos(3)/2; + + return pos; +} + +/* +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! ## paperpositionmode "auto" converts figure size to paper units +%! set (hf, "units", "inches"); +%! set (hf, "position", [0 0 4 5]); +%! set (hf, "paperunits", "centimeters"); +%! psz = get (hf, "papersize"); +%! fsz = [10.16 12.7]; +%! pos = [(psz/2 .- fsz/2) fsz]; +%! set (hf, "paperpositionmode", "auto"); +%! assert (get (hf, "paperposition"), pos) +%! +%! ## likewise with normalized units +%! set (hf, "paperunits", "normalized"); +%! fsz = [10.16 12.7]./psz; +%! pos = [([0.5 0.5] .- fsz/2) fsz]; +%! assert (get (hf, "paperposition"), pos) +%! +%! ## changing papertype updates paperposition +%! set (hf, "paperunits", "centimeters"); +%! set (hf, "papertype", "a4"); +%! psz = get (hf, "papersize"); +%! fsz = [10.16 12.7]; +%! pos = [(psz/2 .- fsz/2) fsz]; +%! assert (get (hf, "paperposition"), pos) +%! +%! ## lanscape updates paperposition +%! set (hf, "paperorientation", "landscape"); +%! psz = get (hf, "papersize"); +%! fsz = [10.16 12.7]; +%! pos = [(psz/2 .- fsz/2) fsz]; +%! assert (get (hf, "paperposition"), pos) +%! +%! ## back to manual mode +%! set (hf, "paperposition", pos+eps) +%! assert (get (hf, "paperpositionmode"), "manual") +%! assert (get (hf, "paperposition"), pos + eps) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect +*/ + void figure::properties::update_paperunits (const caseless_str& old_paperunits) { @@ -3696,6 +4110,9 @@ // between update_papersize and update_papertype papersize.set (octave_value (sz)); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } void @@ -3828,6 +4245,9 @@ std::swap (sz(0), sz(1)); papersize.set (octave_value (sz)); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } /* @@ -3879,6 +4299,9 @@ papersize.set (octave_value (sz)); paperposition.set (octave_value (pos)); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } /* @@ -4704,7 +5127,8 @@ if (camerapositionmode_is ("auto")) { Matrix tview = get_view ().matrix_value (); - double az = tview(0), el = tview(1); + double az = tview(0); + double el = tview(1); double d = 5 * sqrt (pb(0)*pb(0)+pb(1)*pb(1)+pb(2)*pb(2)); if (el == 90 || el == -90) @@ -4729,7 +5153,8 @@ if (cameraupvectormode_is ("auto")) { Matrix tview = get_view ().matrix_value (); - double az = tview(0), el = tview(1); + double az = tview(0); + double el = tview(1); if (el == 90 || el == -90) { @@ -4791,7 +5216,8 @@ translate (x_view, -0.5, -0.5, -0.5); Matrix x_cube = x_view * unit_cube (); - ColumnVector cmin = x_cube.row_min (), cmax = x_cube.row_max (); + ColumnVector cmin = x_cube.row_min (); + ColumnVector cmax = x_cube.row_max (); double xM = cmax(0)-cmin(0); double yM = cmax(1)-cmin(1); @@ -4897,9 +5323,11 @@ const Matrix xlims = xform.xscale (get_xlim ().matrix_value ()); const Matrix ylims = xform.yscale (get_ylim ().matrix_value ()); const Matrix zlims = xform.zscale (get_zlim ().matrix_value ()); - double x_min = xlims(0), x_max = xlims(1); - double y_min = ylims(0), y_max = ylims(1); - double z_min = zlims(0), z_max = zlims(1); + + double x_min, x_max, y_min, y_max, z_min, z_max; + x_min = xlims(0), x_max = xlims(1); + y_min = ylims(0), y_max = ylims(1); + z_min = zlims(0), z_max = zlims(1); ColumnVector p1, p2, dir (3); @@ -5011,18 +5439,14 @@ { if (xaxislocation_is ("top")) { - double tmp = yPlane; - yPlane = yPlaneN; - yPlaneN = tmp; + std::swap (yPlane, yPlaneN); x2Dtop = true; } ypTick = yPlaneN; ypTickN = yPlane; if (yaxislocation_is ("right")) { - double tmp = xPlane; - xPlane = xPlaneN; - xPlaneN = tmp; + std::swap (xPlane, xPlaneN); y2Dright = true; } xpTick = xPlaneN; @@ -5038,6 +5462,7 @@ Matrix viewmat = get_view ().matrix_value (); nearhoriz = std::abs (viewmat(1)) <= 5; + is2D = viewmat(1) == 90; update_ticklength (); } @@ -5139,7 +5564,9 @@ get_xticklabel ().all_strings (), get_xlim ().matrix_value ()); - double wmax = ext(0), hmax = ext(1), angle = 0; + double wmax = ext(0); + double hmax = ext(1); + double angle = 0; ColumnVector p = graphics_xform::xform_vector ((xpTickN+xpTick)/2, ypTick, zpTick); @@ -5240,7 +5667,9 @@ get_yticklabel ().all_strings (), get_ylim ().matrix_value ()); - double wmax = ext(0)+4, hmax = ext(1), angle = 0; + double wmax = ext(0)+4; + double hmax = ext(1); + double angle = 0; ColumnVector p = graphics_xform::xform_vector (xpTick, (ypTickN+ypTick)/2, zpTick); @@ -5333,7 +5762,9 @@ get_zticklabel ().all_strings (), get_zlim ().matrix_value ()); - double wmax = ext(0), hmax = ext(1), angle = 0; + double wmax = ext(0); + double hmax = ext(1); + double angle = 0; ColumnVector p; if (xySym) @@ -5494,12 +5925,13 @@ s = xmax(s, (limits(1) - limits(0)) / (pbfactor * dafactor)); } -static bool updating_aspectratios = false; +static std::set updating_aspectratios; void axes::properties::update_aspectratios (void) { - if (updating_aspectratios) + if (updating_aspectratios.find (get___myhandle__ ().value ()) != + updating_aspectratios.end ()) return; Matrix xlimits = get_xlim ().matrix_value (); @@ -5565,7 +5997,7 @@ unwind_protect frame; frame.protect_var (updating_aspectratios); - updating_aspectratios = true; + updating_aspectratios.insert (get___myhandle__ ().value ()); dx = pba(0) *da(0); dy = pba(1) *da(1); @@ -6248,11 +6680,7 @@ double tmp; // FIXME: should this be checked for somewhere else? (i.e. set{x,y,z}lim) if (hi < lo) - { - tmp = hi; - hi = lo; - lo = tmp; - } + std::swap (hi, lo); if (is_logscale) { @@ -6269,15 +6697,17 @@ } } - double tick_sep = calc_tick_sep (lo , hi); - - if (is_logscale && ! (xisinf (hi) || xisinf (lo))) - { - // FIXME: what if (hi-lo) < tick_sep? - // ex: loglog ([1 1.1]) - tick_sep = std::max (tick_sep, 1.); - tick_sep = std::ceil (tick_sep); - } + double tick_sep; + + if (is_logscale) + { + if (! (xisinf (hi) || xisinf (lo))) + tick_sep = 1; // Tick is every order of magnitude (bug #39449) + else + tick_sep = 0; + } + else + tick_sep = calc_tick_sep (lo , hi); int i1 = static_cast (gnulib::floor (lo / tick_sep)); int i2 = static_cast (std::ceil (hi / tick_sep)); @@ -6402,7 +6832,8 @@ #endif Matrix ext (1, 2, 0.0); - double wmax = 0., hmax = 0.; + double wmax, hmax; + wmax = hmax = 0.; int n = std::min (ticklabels.numel (), ticks.numel ()); for (int i = 0; i < n; i++) { @@ -6514,13 +6945,14 @@ } } -static bool updating_axis_limits = false; +static std::set updating_axis_limits; void axes::update_axis_limits (const std::string& axis_type, const graphics_handle& h) { - if (updating_axis_limits) + if (updating_axis_limits.find (get_handle ().value ()) != + updating_axis_limits.end ()) return; Matrix kids = Matrix (1, 1, h.value ()); @@ -6679,7 +7111,7 @@ unwind_protect frame; frame.protect_var (updating_axis_limits); - updating_axis_limits = true; + updating_axis_limits.insert (get_handle ().value ()); switch (update_type) { @@ -6722,7 +7154,10 @@ void axes::update_axis_limits (const std::string& axis_type) { - if (updating_axis_limits || updating_aspectratios) + if ((updating_axis_limits.find (get_handle ().value ()) != + updating_axis_limits.end ()) || + (updating_aspectratios.find (get_handle ().value ()) != + updating_aspectratios.end ())) return; Matrix kids = xproperties.get_children (); @@ -6838,7 +7273,7 @@ unwind_protect frame; frame.protect_var (updating_axis_limits); - updating_axis_limits = true; + updating_axis_limits.insert (get_handle ().value ()); switch (update_type) { @@ -6878,14 +7313,14 @@ } inline -double force_in_range (const double x, const double lower, const double upper) +double force_in_range (double x, double lower, double upper) { if (x < lower) - { return lower; } + return lower; else if (x > upper) - { return upper; } - else - { return x; } + return upper; + else + return x; } static Matrix @@ -7225,7 +7660,8 @@ { #ifdef HAVE_FREETYPE - int halign = 0, valign = 0; + int halign = 0; + int valign = 0; if (horizontalalignment_is ("center")) halign = 1; @@ -7368,9 +7804,11 @@ Matrix z = get_zdata ().matrix_value (); - int p = z.columns (), q = z.rows (); - int i1 = 0, i2 = 0, i3 = 0; - int j1 = 0, j2 = 0, j3 = 0; + int p = z.columns (); + int q = z.rows (); + int i1, i2, i3, j1, j2, j3; + i1 = i2 = i3 = 0; + j1 = j2 = j3 = 0; bool x_mat = (x.rows () == q); bool y_mat = (y.columns () == p); @@ -8144,9 +8582,9 @@ // No copying! - function_event (const function_event &); - - function_event & operator = (const function_event &); + function_event (const function_event&); + + function_event & operator = (const function_event&); }; class @@ -8348,7 +8786,7 @@ } void -gh_manager::do_post_callback (const graphics_handle& h, const std::string name, +gh_manager::do_post_callback (const graphics_handle& h, const std::string& name, const octave_value& data) { gh_manager::auto_lock guard; @@ -8398,7 +8836,7 @@ } void -gh_manager::do_post_set (const graphics_handle& h, const std::string name, +gh_manager::do_post_set (const graphics_handle& h, const std::string& name, const octave_value& value, bool notify_toolkit) { gh_manager::auto_lock guard; @@ -8628,9 +9066,11 @@ @deftypefn {Built-in Function} {} set (@var{h}, @var{property}, @var{value}, @dots{})\n\ @deftypefnx {Built-in Function} {} set (@var{h}, @var{properties}, @var{values})\n\ @deftypefnx {Built-in Function} {} set (@var{h}, @var{pv})\n\ +@deftypefnx {Built-in Function} {@var{value_list} =} set (@var{h}, @var{property})\n\ +@deftypefnx {Built-in Function} {@var{all_value_list} =} set (@var{h})\n\ Set named property values for the graphics handle (or vector of graphics\n\ handles) @var{h}.\n\ -There are three ways how to give the property names and values:\n\ +There are three ways to give the property names and values:\n\ \n\ @itemize\n\ @item as a comma separated list of @var{property}, @var{value} pairs\n\ @@ -8656,6 +9096,32 @@ elements of @var{pv} will be set in all handles in @var{h} independent of\n\ the dimensions of @var{pv}.\n\ @end itemize\n\ +\n\ +@code{set} is also used to query the list of values a named property will\n\ +take. @code{@var{clist} = set (@var{h}, \"property\")} will return the list\n\ +of possible values for @qcode{\"property\"} in the cell list @var{clist}.\n\ +If no output variable is used then the list is formatted and printed to the\n\ +screen.\n\ +\n\ +If no property is specified (@code{@var{slist} = set (@var{h})}) then a\n\ +structure @var{slist} is returned where the fieldnames are the properties of\n\ +the object @var{h} and the fields are the list of possible values for each\n\ +property. If no output variable is used then the list is formatted and\n\ +printed to the screen.\n\ +\n\ +For example,\n\ +\n\ +@example\n\ +@group\n\ +hf = figure ();\n\ +set (hf, \"paperorientation\")\n\ +@result{} paperorientation: [ landscape | @{portrait@} | rotated ]\n\ +@end group\n\ +@end example\n\ +\n\ +@noindent\n\ +shows the paperorientation property can take three values with the default\n\ +being @qcode{\"portrait\"}.\n\ @seealso{get}\n\ @end deftypefn") { @@ -8706,6 +9172,35 @@ { obj.set (args(1).map_value ()); } + else if (nargin == 2 && args(1).is_string ()) + { + std::string property = args(1).string_value (); + + octave_map pmap = obj.values_as_struct (); + + if (obj.has_readonly_property (property)) + if (nargout != 0) + retval = Matrix (); + else + octave_stdout << "set: " << property + <<" is read-only" << std::endl; + else if (pmap.isfield (property)) + { + if (nargout != 0) + retval = pmap.getfield (property)(0); + else + { + std::string s = obj.value_as_string (property); + if (! error_state) + octave_stdout << s; + } + } + else + { + error ("set: unknown property"); + break; + } + } else if (nargin == 1) { if (nargout != 0) @@ -8748,7 +9243,7 @@ } static std::string -get_graphics_object_type (const double val) +get_graphics_object_type (double val) { std::string retval; @@ -9380,7 +9875,7 @@ { graphics_handle h = octave_NaN; - const NDArray vals = args (0).array_value (); + const NDArray vals = args(0).array_value (); if (! error_state) { @@ -9657,12 +10152,13 @@ while (pa != available_toolkits.end ()) { - std::string name = *pa++; - - if (name == "qt" - || (name == "fltk" - && available_toolkits.find ("qt") == available_toolkits.end ())) - dtk = name; + std::string tk_name = *pa++; + + if (tk_name == "qt" + || (tk_name == "fltk" + && available_toolkits.find ("qt") + == available_toolkits.end ())) + dtk = tk_name; } } } @@ -10206,7 +10702,7 @@ static bool compare_property_values (const octave_value& o1, const octave_value& o2) { - octave_value_list args (2); + octave_value_list args(2); args(0) = o1; args(1) = o2; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/graphics.in.h Sun May 25 10:29:05 2014 -0700 @@ -296,7 +296,7 @@ graphics_handle get_parent (void) const { return parent; } - void set_parent (const graphics_handle &h) { parent = h; } + void set_parent (const graphics_handle& h) { parent = h; } bool is_hidden (void) const { return hidden; } @@ -1028,7 +1028,7 @@ validate (); } - color_values (std::string str) + color_values (const std::string& str) : xrgb (1, 3) { if (! str2rgb (str)) @@ -1076,7 +1076,7 @@ private: Matrix xrgb; - OCTINTERP_API bool str2rgb (std::string str); + OCTINTERP_API bool str2rgb (const std::string& str); }; class color_property : public base_property @@ -1631,7 +1631,7 @@ } children_property (const std::string& nm, const graphics_handle& h, - const Matrix &val) + const Matrix& val) : base_property (nm, h), children_list () { do_init_children (val); @@ -1651,12 +1651,12 @@ base_property* clone (void) const { return new children_property (*this); } - bool remove_child (const double &val) + bool remove_child (double val) { return do_remove_child (val); } - void adopt (const double &val) + void adopt (double val) { do_adopt_child (val); } @@ -1759,14 +1759,14 @@ } private: - void do_init_children (const Matrix &val) + void do_init_children (const Matrix& val) { children_list.clear (); for (octave_idx_type i = 0; i < val.numel (); i++) children_list.push_front (val.xelem (i)); } - void do_init_children (const std::list &val) + void do_init_children (const std::list& val) { children_list.clear (); for (const_children_list_iterator p = val.begin (); p != val.end (); p++) @@ -1800,7 +1800,7 @@ return false; } - void do_adopt_child (const double &val) + void do_adopt_child (double val) { children_list.push_front (val); } @@ -2594,7 +2594,7 @@ protected: struct cmp_caseless_str { - bool operator () (const caseless_str &a, const caseless_str &b) const + bool operator () (const caseless_str& a, const caseless_str& b) const { std::string a1 = a; std::transform (a1.begin (), a1.end (), a1.begin (), tolower); @@ -2698,8 +2698,15 @@ return octave_value (); } + virtual bool has_readonly_property (const caseless_str& pname) const + { + return base_properties::has_readonly_property (pname); + } + virtual std::string values_as_string (void); + virtual std::string value_as_string (const std::string& prop); + virtual octave_scalar_map values_as_struct (void); virtual graphics_handle get_parent (void) const @@ -2969,8 +2976,18 @@ return rep->get_factory_defaults (); } + bool has_readonly_property (const caseless_str& pname) const + { + return rep->has_readonly_property (pname); + } + std::string values_as_string (void) { return rep->values_as_string (); } + std::string value_as_string (const std::string& prop) + { + return rep->value_as_string (prop); + } + octave_map values_as_struct (void) { return rep->values_as_struct (); } graphics_handle get_parent (void) const { return rep->get_parent (); } @@ -3090,20 +3107,10 @@ // See the genprops.awk script for an explanation of the // properties declarations. - // FIXME: it seems strange to me that the diary, diaryfile, - // echo, errormessage, format, formatspacing, language, and - // recursionlimit properties are here. - // WTF do they have to do with graphics? - // Also note that these properties (and the monitorpositions, - // pointerlocation, and pointerwindow properties) are not yet used - // by Octave, so setting them will have no effect, and changes - // made elswhere (say, the diary or format functions) will not - // cause these properties to be updated. - // ANSWER: Matlab defines these properties and uses them in - // the same way that Octave uses an internal static variable to - // keep track of state. set (0, "echo", "on") is equivalent - // to Octave's echo ("on"). Maybe someday we can connect callbacks - // that actually call Octave's own functions for this. + // FIXME: Properties that still dont have callbacks are: + // language, monitorpositions, pointerlocation, pointerwindow. + // Note that these properties are not yet used by Octave, so setting + // them will have no effect. // Programming note: Keep property list sorted if new ones are added. @@ -3111,18 +3118,18 @@ handle_property callbackobject Sr , graphics_handle () array_property commandwindowsize r , Matrix (1, 2, 0) handle_property currentfigure S , graphics_handle () - bool_property diary , "off" - string_property diaryfile , "diary" - bool_property echo , "off" - string_property errormessage , "" + bool_property diary GS , "off" + string_property diaryfile GS , "diary" + bool_property echo GS , "off" + string_property errormessage Gr , "" string_property fixedwidthfontname , "Courier" - radio_property format , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rational|{short}|shorte|shorteng|shortg" - radio_property formatspacing , "compact|{loose}" + radio_property format GS , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rat|{short}|shorte|shorteng|shortg" + radio_property formatspacing GS , "compact|{loose}" string_property language , "ascii" array_property monitorpositions , Matrix (1, 4, 0) array_property pointerlocation , Matrix (1, 2, 0) double_property pointerwindow r , 0.0 - double_property recursionlimit , 256.0 + double_property recursionlimit GS , 256.0 double_property screendepth r , default_screendepth () double_property screenpixelsperinch r , default_screenpixelsperinch () array_property screensize r , default_screensize () @@ -3132,6 +3139,7 @@ private: std::list cbo_stack; + }; private: @@ -3224,6 +3232,14 @@ bool valid_object (void) const { return true; } void reset_default_properties (void); + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } private: property_list default_properties; @@ -3333,8 +3349,8 @@ bool_property numbertitle , "on" array_property outerposition s , Matrix (1, 4, -1.0) radio_property paperorientation U , "{portrait}|landscape|rotated" - array_property paperposition , default_figure_paperposition () - radio_property paperpositionmode , "auto|{manual}" + array_property paperposition m , default_figure_paperposition () + radio_property paperpositionmode au , "auto|{manual}" array_property papersize U , default_figure_papersize () radio_property papertype SU , "{usletter}|uslegal|a0|a1|a2|a3|a4|a5|b0|b1|b2|b3|b4|b5|arch-a|arch-b|arch-c|arch-d|arch-e|a|b|c|d|e|tabloid|" radio_property paperunits Su , "{inches}|centimeters|normalized|points" @@ -3381,7 +3397,15 @@ position.add_constraint (dim_vector (1, 4)); } - private: + private: + Matrix get_auto_paperposition (void); + + void update_paperpositionmode (void) + { + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); + } + mutable graphics_toolkit toolkit; }; @@ -3448,6 +3472,14 @@ bool valid_object (void) const { return true; } void reset_default_properties (void); + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } private: property_list default_properties; @@ -3633,6 +3665,7 @@ bool get_x2Dtop (void) const { return x2Dtop; } bool get_y2Dright (void) const { return y2Dright; } bool get_layer2Dtop (void) const { return layer2Dtop; } + bool get_is2D (void) const { return is2D; } bool get_xySym (void) const { return xySym; } bool get_xyzSym (void) const { return xyzSym; } bool get_zSign (void) const { return zSign; } @@ -3671,11 +3704,11 @@ double fx, fy, fz; double xticklen, yticklen, zticklen; double xtickoffset, ytickoffset, ztickoffset; - bool x2Dtop, y2Dright, layer2Dtop; + bool x2Dtop, y2Dright, layer2Dtop, is2D; bool xySym, xyzSym, zSign, nearhoriz; #if HAVE_FREETYPE - // freetype renderer, used for calculation of text (tick labels) size + // FreeType renderer, used for calculation of text (tick labels) size ft_render text_renderer; #endif @@ -3698,7 +3731,7 @@ radio_property camerapositionmode , "{auto}|manual" array_property cameratarget m , Matrix (1, 3, 0.0) radio_property cameratargetmode , "{auto}|manual" - array_property cameraupvector m , Matrix () + array_property cameraupvector m , Matrix (1, 3, 0.0) radio_property cameraupvectormode , "{auto}|manual" double_property cameraviewangle m , 10.0 radio_property cameraviewanglemode , "{auto}|manual" @@ -3737,7 +3770,7 @@ handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false) // FIXME: uicontextmenu should be moved here. radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters" - array_property view u , Matrix () + array_property view u , default_axes_view () radio_property xaxislocation u , "{bottom}|top|zero" color_property xcolor , color_values (0, 0, 0) radio_property xdir u , "{normal}|reverse" @@ -4133,7 +4166,6 @@ void set_defaults (const std::string& mode) { - remove_all_listeners (); xproperties.set_defaults (*this, mode); } @@ -4170,6 +4202,14 @@ void reset_default_properties (void); + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + protected: void initialize (const graphics_object& go); @@ -4250,6 +4290,14 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } }; // --------------------------------------------------------------------- @@ -4307,7 +4355,7 @@ radio_property interpreter u , "{tex}|none|latex" radio_property linestyle , "{-}|--|:|-.|none" double_property linewidth , 0.5 - double_property margin , 1 + double_property margin , 2 array_property position smu , Matrix (1, 3, 0.0) double_property rotation mu , 0 text_label_property string u , "" @@ -4333,7 +4381,7 @@ Matrix get_extent_matrix (void) const; const uint8NDArray& get_pixels (void) const { return pixels; } #if HAVE_FREETYPE - // freetype renderer, used for calculation of text size + // FreeType renderer, used for calculation of text size ft_render renderer; #endif @@ -4415,6 +4463,14 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } }; // --------------------------------------------------------------------- @@ -4442,10 +4498,11 @@ // Programming note: Keep property list sorted if new ones are added. BEGIN_PROPERTIES (image) - array_property alphadata u , Matrix () - radio_property alphadatamapping al , "none|direct|{scaled}" - array_property cdata u , Matrix () + array_property alphadata u , Matrix (1, 1, 1.0) + radio_property alphadatamapping al , "{none}|direct|scaled" + array_property cdata u , default_image_cdata () radio_property cdatamapping al , "scaled|{direct}" + string_property displayname , "" radio_property erasemode , "{normal}|none|xor|background" row_vector_property xdata u , Matrix () row_vector_property ydata u , Matrix () @@ -4562,6 +4619,14 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } }; // --------------------------------------------------------------------- @@ -4603,7 +4668,7 @@ double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp")) color_property facecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp")) radio_property facelighting , "{none}|flat|gouraud|phong" - array_property faces , Matrix () + array_property faces , default_patch_faces () array_property facevertexalphadata , Matrix () array_property facevertexcdata , Matrix () // FIXME: interpreter is not a property of a Matlab patch. @@ -4618,9 +4683,9 @@ radio_property normalmode , "{auto}|manual" double_property specularcolorreflectance , 1.0 double_property specularexponent , 10.0 - double_property specularstrength , 0.6 + double_property specularstrength , 0.9 array_property vertexnormals , Matrix () - array_property vertices , Matrix () + array_property vertices , default_patch_vertices () array_property xdata u , Matrix () array_property ydata u , Matrix () array_property zdata u , Matrix () @@ -4686,6 +4751,14 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } }; // --------------------------------------------------------------------- @@ -4713,11 +4786,11 @@ // Programming note: Keep property list sorted if new ones are added. BEGIN_PROPERTIES (surface) - array_property alphadata u , Matrix () + array_property alphadata u , Matrix (1, 1, 1.0) radio_property alphadatamapping l , "none|direct|{scaled}" double_property ambientstrength , 0.3 radio_property backfacelighting , "unlit|lit|{reverselit}" - array_property cdata u , Matrix () + array_property cdata u , default_surface_cdata () radio_property cdatamapping al , "{scaled}|direct" string_property cdatasource , "" double_property diffusestrength , 0.6 @@ -4744,11 +4817,11 @@ double_property specularexponent , 10 double_property specularstrength , 0.9 array_property vertexnormals u , Matrix () - array_property xdata u , Matrix () + array_property xdata u , default_surface_xdata () string_property xdatasource , "" - array_property ydata u , Matrix () + array_property ydata u , default_surface_ydata () string_property ydatasource , "" - array_property zdata u , Matrix () + array_property zdata u , default_surface_zdata () string_property zdatasource , "" // hidden properties for limit computation @@ -4778,6 +4851,7 @@ alphadata.add_constraint ("uint8"); alphadata.add_constraint (dim_vector (-1, -1)); vertexnormals.add_constraint (dim_vector (-1, -1, 3)); + vertexnormals.add_constraint (dim_vector (0, 0)); } private: @@ -4841,6 +4915,14 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } }; // --------------------------------------------------------------------- @@ -4919,6 +5001,14 @@ void update_axis_limits (const std::string& axis_type, const graphics_handle& h); + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + }; // --------------------------------------------------------------------- @@ -4980,6 +5070,14 @@ bool valid_object (void) const { return true; } + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + }; // --------------------------------------------------------------------- @@ -5027,6 +5125,14 @@ bool valid_object (void) const { return true; } + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + }; // --------------------------------------------------------------------- @@ -5119,6 +5225,14 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } }; // --------------------------------------------------------------------- @@ -5186,6 +5300,14 @@ const base_properties& get_properties (void) const { return xproperties; } bool valid_object (void) const { return true; } + + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } }; // --------------------------------------------------------------------- @@ -5273,6 +5395,14 @@ void reset_default_properties (void); + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + private: property_list default_properties; }; @@ -5325,6 +5455,14 @@ bool valid_object (void) const { return true; } + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + }; // --------------------------------------------------------------------- @@ -5378,16 +5516,24 @@ bool valid_object (void) const { return true; } + bool has_readonly_property (const caseless_str& pname) const + { + bool retval = xproperties.has_readonly_property (pname); + if (! retval) + retval = base_properties::has_readonly_property (pname); + return retval; + } + }; // --------------------------------------------------------------------- octave_value -get_property_from_handle (double handle, const std::string &property, - const std::string &func); +get_property_from_handle (double handle, const std::string& property, + const std::string& func); bool -set_property_in_handle (double handle, const std::string &property, - const octave_value &arg, const std::string &func); +set_property_in_handle (double handle, const std::string& property, + const octave_value& arg, const std::string& func); // --------------------------------------------------------------------- @@ -5858,12 +6004,12 @@ void do_execute_callback (const graphics_handle& h, const octave_value& cb, const octave_value& data); - void do_post_callback (const graphics_handle& h, const std::string name, + void do_post_callback (const graphics_handle& h, const std::string& name, const octave_value& data); void do_post_function (graphics_event::event_fcn fcn, void* fcn_data); - void do_post_set (const graphics_handle& h, const std::string name, + void do_post_set (const graphics_handle& h, const std::string& name, const octave_value& value, bool notify_toolkit = true); int do_process_events (bool force = false); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/help.cc --- a/libinterp/corefcn/help.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/help.cc Sun May 25 10:29:05 2014 -0700 @@ -230,7 +230,7 @@ pair_type (")", "-*- texinfo -*-\n\ -@deftypefn {Operator} {} )\n\ +@deftypefn {Operator} {})\n\ Array index or function argument delimiter.\n\ @end deftypefn"), @@ -1078,7 +1078,7 @@ if (args.length () == 1) { - const std::string name = args (0).string_value (); + const std::string name = args(0).string_value (); if (! error_state) { @@ -1367,7 +1367,7 @@ retval = Cell (ffl.append (afl)); else { - std::string dir = args (0).string_value (); + std::string dir = args(0).string_value (); if (! error_state) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/input.cc --- a/libinterp/corefcn/input.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/input.cc Sun May 25 10:29:05 2014 -0700 @@ -750,10 +750,10 @@ @noindent\n\ and waits for the user to enter a value. The string entered by the user\n\ is evaluated as an expression, so it may be a literal constant, a\n\ -variable name, or any other valid expression.\n\ +variable name, or any other valid Octave code.\n\ \n\ -Currently, @code{input} only returns one value, regardless of the number\n\ -of values produced by the evaluation of the expression.\n\ +The number of return arguments, their size, and their class depend on the\n\ +expression entered.\n\ \n\ If you are only interested in getting a literal string value, you can\n\ call @code{input} with the character string @qcode{\"s\"} as the second\n\ @@ -772,7 +772,7 @@ int nargin = args.length (); if (nargin == 1 || nargin == 2) - retval = get_user_input (args, nargout); + retval = get_user_input (args, std::max (nargout, 1)); else print_usage (); @@ -1005,6 +1005,15 @@ return retval; } +DEFUN (__echostate__, , , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{state} =} __echostate__ ()\n\ +Undocumented internal function\n\ +@end deftypefn") +{ + return ovl (Vecho_executing_commands == ECHO_SCRIPTS); +} + DEFUN (completion_matches, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} completion_matches (@var{hint})\n\ @@ -1410,11 +1419,12 @@ DEFUN (filemarker, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} filemarker ()\n\ -@deftypefnx {Built-in Function} {} filemarker (@var{new_val})\n\ +@deftypefnx {Built-in Function} {@var{old_val} =} filemarker (@var{new_val})\n\ @deftypefnx {Built-in Function} {} filemarker (@var{new_val}, \"local\")\n\ -Query or set the character used to separate filename from the\n\ -the subfunction names contained within the file. This can be used in\n\ -a generic manner to interact with subfunctions. For example,\n\ +Query or set the character used to separate the filename from the subfunction\n\ +names contained within the file. By default this is the character @samp{>}.\n\ +This can be used in a generic manner to interact with subfunctions.\n\ +For example,\n\ \n\ @example\n\ help ([\"myfunc\", filemarker, \"mysubfunc\"])\n\ @@ -1422,8 +1432,10 @@ \n\ @noindent\n\ returns the help string associated with the subfunction @code{mysubfunc}\n\ -of the function @code{myfunc}. Another use of @code{filemarker} is when\n\ -debugging it allows easier placement of breakpoints within subfunctions.\n\ +located in the file @file{myfunc.m}.\n\ +\n\ +@code{filemarker} is also useful during debugging for placing breakpoints\n\ +within subfunctions or nested functions.\n\ For example,\n\ \n\ @example\n\ @@ -1434,7 +1446,7 @@ will set a breakpoint at the first line of the subfunction @code{mysubfunc}.\n\ \n\ When called from inside a function with the @qcode{\"local\"} option, the\n\ -variable is changed locally for the function and any subroutines it calls. \n\ +variable is changed locally for the function and any subroutines it calls.\n\ The original variable value is restored when exiting the function.\n\ @end deftypefn") { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/inv.cc diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/jit-typeinfo.cc Sun May 25 10:29:05 2014 -0700 @@ -1247,6 +1247,8 @@ destroy_fn.add_overload (create_identity(index)); destroy_fn.add_overload (create_identity(complex)); + // -------------------- scalar related operations -------------------- + // now for binary scalar operations add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd); add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub); @@ -1335,6 +1337,7 @@ val = builder.CreateFMul (val, mone); fn.do_return (builder, val); } + unary_ops[octave_value::op_uminus].add_overload (fn); fn = create_identity (scalar); unary_ops[octave_value::op_uplus].add_overload (fn); @@ -1842,7 +1845,7 @@ register_generic ("cos", matrix, matrix); add_builtin ("exp"); - register_intrinsic ("exp", llvm::Intrinsic::cos, scalar, scalar); + register_intrinsic ("exp", llvm::Intrinsic::exp, scalar, scalar); register_generic ("exp", matrix, matrix); add_builtin ("balance"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/kron.cc --- a/libinterp/corefcn/kron.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/kron.cc Sun May 25 10:29:05 2014 -0700 @@ -55,8 +55,10 @@ assert (a.ndims () == 2); assert (b.ndims () == 2); - octave_idx_type nra = a.rows (), nrb = b.rows (); - octave_idx_type nca = a.cols (), ncb = b.cols (); + octave_idx_type nra = a.rows (); + octave_idx_type nrb = b.rows (); + octave_idx_type nca = a.cols (); + octave_idx_type ncb = b.cols (); MArray c (dim_vector (nra*nrb, nca*ncb)); T *cv = c.fortran_vec (); @@ -79,8 +81,11 @@ { assert (b.ndims () == 2); - octave_idx_type nra = a.rows (), nrb = b.rows (), dla = a.diag_length (); - octave_idx_type nca = a.cols (), ncb = b.cols (); + octave_idx_type nra = a.rows (); + octave_idx_type nrb = b.rows (); + octave_idx_type dla = a.diag_length (); + octave_idx_type nca = a.cols (); + octave_idx_type ncb = b.cols (); MArray c (dim_vector (nra*nrb, nca*ncb), T ()); @@ -129,12 +134,15 @@ static PermMatrix kron (const PermMatrix& a, const PermMatrix& b) { - octave_idx_type na = a.rows (), nb = b.rows (); - const octave_idx_type *pa = a.data (), *pb = b.data (); + octave_idx_type na = a.rows (); + octave_idx_type nb = b.rows (); + const octave_idx_type *pa = a.data (); + const octave_idx_type *pb = b.data (); PermMatrix c(na*nb); // Row permutation. octave_idx_type *pc = c.fortran_vec (); - bool cola = a.is_col_perm (), colb = b.is_col_perm (); + bool cola = a.is_col_perm (); + bool colb = b.is_col_perm (); if (cola && colb) { for (octave_idx_type i = 0; i < na; i++) @@ -282,7 +290,8 @@ if (nargin >= 2) { - octave_value a = args(0), b = args(1); + octave_value a = args(0); + octave_value b = args(1); retval = dispatch_kron (a, b); for (octave_idx_type i = 2; i < nargin; i++) retval = dispatch_kron (retval, args(i)); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/load-path.cc --- a/libinterp/corefcn/load-path.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/load-path.cc Sun May 25 10:29:05 2014 -0700 @@ -38,6 +38,7 @@ #include "defun.h" #include "input.h" #include "load-path.h" +#include "ov-usr-fcn.h" #include "pager.h" #include "parse.h" #include "toplev.h" @@ -120,6 +121,7 @@ if (fs) { method_file_map.clear (); + package_dir_map.clear (); dir_mtime = fs.mtime (); dir_time_last_checked = octave_time (); @@ -181,6 +183,8 @@ get_private_file_map (full_name); else if (fname[0] == '@') get_method_file_map (full_name, fname.substr (1)); + else if (fname[0] == '+') + get_package_dir (full_name, fname.substr (1)); } else { @@ -286,6 +290,13 @@ method_file_map[class_name].private_file_map = get_fcn_files (pd); } +void +load_path::dir_info::get_package_dir (const std::string& d, + const std::string& package_name) +{ + package_dir_map[package_name] = dir_info (d); +} + bool load_path::instance_ok (void) { @@ -373,8 +384,8 @@ } void -load_path::move_fcn_map (const std::string& dir_name, - const string_vector& fcn_files, bool at_end) +load_path::loader::move_fcn_map (const std::string& dir_name, + const string_vector& fcn_files, bool at_end) { octave_idx_type len = fcn_files.length (); @@ -422,7 +433,7 @@ } void -load_path::move_method_map (const std::string& dir_name, bool at_end) +load_path::loader::move_method_map (const std::string& dir_name, bool at_end) { for (method_map_iterator i = method_map.begin (); i != method_map.end (); @@ -466,7 +477,7 @@ } void -load_path::move (dir_info_list_iterator i, bool at_end) +load_path::do_move (dir_info_list_iterator i, bool at_end) { if (dir_info_list.size () > 1) { @@ -479,16 +490,56 @@ else dir_info_list.push_front (di); - std::string dir_name = di.dir_name; - - move_fcn_map (dir_name, di.fcn_files, at_end); - - // No need to move elements of private function map. - - move_method_map (dir_name, at_end); + move (di, at_end); + } +} + +void +load_path::move (const dir_info& di, bool at_end, const std::string& pname) +{ + loader& l = get_loader (pname); + + l.move (di, at_end); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + move (p->second, at_end, full_name); } } +void +load_path::loader::move (const dir_info& di, bool at_end) +{ + std::string dir_name = di.dir_name; + + std::list::iterator s = + std::find (dir_list.begin (), dir_list.end (), dir_name); + + if (s != dir_list.end ()) + { + dir_list.erase (s); + + if (at_end) + dir_list.push_back (dir_name); + else + dir_list.push_front (dir_name); + } + + move_fcn_map (dir_name, di.fcn_files, at_end); + + // No need to move elements of private function map. + + move_method_map (dir_name, at_end); +} + static void maybe_add_path_elts (std::string& path, const std::string& dir) { @@ -544,9 +595,10 @@ load_path::do_clear (void) { dir_info_list.clear (); - fcn_map.clear (); - private_fcn_map.clear (); - method_map.clear (); + + default_loader.clear (); + + loader_map.clear (); } static std::list @@ -683,7 +735,7 @@ dir_info_list_iterator i = find_dir_info (dir); if (i != dir_info_list.end ()) - move (i, at_end); + do_move (i, at_end); else { file_stat fs (dir); @@ -701,11 +753,7 @@ else dir_info_list.push_front (di); - add_to_fcn_map (di, at_end); - - add_to_private_fcn_map (di); - - add_to_method_map (di, at_end); + add (di, at_end); if (add_hook) add_hook (dir); @@ -726,12 +774,12 @@ i = find_dir_info ("."); if (i != dir_info_list.end ()) - move (i, false); + do_move (i, false); } void -load_path::remove_fcn_map (const std::string& dir, - const string_vector& fcn_files) +load_path::loader::remove_fcn_map (const std::string& dir, + const string_vector& fcn_files) { octave_idx_type len = fcn_files.length (); @@ -770,7 +818,7 @@ } void -load_path::remove_private_fcn_map (const std::string& dir) +load_path::loader::remove_private_fcn_map (const std::string& dir) { private_fcn_map_iterator p = private_fcn_map.find (dir); @@ -779,7 +827,7 @@ } void -load_path::remove_method_map (const std::string& dir) +load_path::loader::remove_method_map (const std::string& dir) { for (method_map_iterator i = method_map.begin (); i != method_map.end (); @@ -847,15 +895,11 @@ if (remove_hook) remove_hook (dir); - string_vector fcn_files = i->fcn_files; + dir_info& di = *i; + + remove (di); dir_info_list.erase (i); - - remove_fcn_map (dir, fcn_files); - - remove_private_fcn_map (dir); - - remove_method_map (dir); } } } @@ -864,17 +908,52 @@ } void +load_path::remove (const dir_info& di, const std::string& pname) +{ + loader& l = get_loader (pname); + + l.remove (di); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + remove (p->second, full_name); + } +} + +void +load_path::loader::remove (const dir_info& di) +{ + std::string dir = di.dir_name; + + string_vector fcn_files = di.fcn_files; + + dir_list.remove (dir); + + remove_fcn_map (dir, fcn_files); + + remove_private_fcn_map (dir); + + remove_method_map (dir); +} + +void load_path::do_update (void) const { // I don't see a better way to do this because we need to // preserve the correct directory ordering for new files that // have appeared. - fcn_map.clear (); - - private_fcn_map.clear (); - - method_map.clear (); + default_loader.clear (); + + loader_map.clear (); for (dir_info_list_iterator p = dir_info_list.begin (); p != dir_info_list.end (); @@ -884,11 +963,7 @@ di.update (); - add_to_fcn_map (di, true); - - add_to_private_fcn_map (di); - - add_to_method_map (di, true); + add (di, true); } } @@ -987,8 +1062,8 @@ } std::string -load_path::do_find_fcn (const std::string& fcn, std::string& dir_name, - int type) const +load_path::loader::find_fcn (const std::string& fcn, std::string& dir_name, + int type) const { std::string retval; @@ -1003,7 +1078,7 @@ std::string class_name = fcn.substr (1, pos-1); std::string meth = fcn.substr (pos+1); - retval = do_find_method (class_name, meth, dir_name); + retval = find_method (class_name, meth, dir_name); } else retval = std::string (); @@ -1042,8 +1117,8 @@ } std::string -load_path::do_find_private_fcn (const std::string& dir, - const std::string& fcn, int type) const +load_path::loader::find_private_fcn (const std::string& dir, + const std::string& fcn, int type) const { std::string retval; @@ -1072,9 +1147,9 @@ } std::string -load_path::do_find_method (const std::string& class_name, - const std::string& meth, - std::string& dir_name, int type) const +load_path::loader::find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, int type) const { std::string retval; @@ -1120,7 +1195,7 @@ } std::list -load_path::do_methods (const std::string& class_name) const +load_path::loader::methods (const std::string& class_name) const { std::list retval; @@ -1149,13 +1224,63 @@ // update (); + default_loader.overloads (meth, retval); + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + l->second.overloads (meth, retval); + + return retval; +} + +void +load_path::loader::overloads (const std::string& meth, + std::list& l) const +{ for (const_method_map_iterator q = method_map.begin (); q != method_map.end (); q++) { const fcn_map_type& m = q->second; if (m.find (meth) != m.end ()) - retval.push_back (q->first); + { + std::string class_name = q->first; + + if (! prefix.empty ()) + class_name = prefix + "." + class_name; + + l.push_back (class_name); + } + } +} + +// Should we cache all files in private directories, or is it OK to just +// look them up each time as needed? + +std::string +find_private_file (const std::string& fname) +{ + std::string retval; + + // Look in private directory corresponding to current function (if + // any). + + octave_user_function *curr_fcn = symbol_table::get_curr_fcn (); + + if (curr_fcn && ! curr_fcn->is_private_function ()) + { + std::string dir_name = curr_fcn->dir_name (); + + if (! dir_name.empty ()) + { + std::string pfname = dir_name + file_ops::dir_sep_str () + + "private" + file_ops::dir_sep_str () + fname; + + file_stat fs (pfname); + + if (fs.exists () && fs.is_reg ()) + retval = pfname; + } } return retval; @@ -1166,33 +1291,43 @@ { std::string retval; + if (octave_env::absolute_pathname (file) + || octave_env::rooted_relative_pathname (file)) + { + file_stat fs (file); + + if (fs.exists ()) + return file; + } + else + { + std::string tfile = find_private_file (file); + + if (! tfile.empty ()) + return tfile; + } + if (file.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos) { - if (octave_env::absolute_pathname (file) - || octave_env::rooted_relative_pathname (file)) + // Given name has a directory separator, so append it to each + // element of the load path in turn. + + for (const_dir_info_list_iterator p = dir_info_list.begin (); + p != dir_info_list.end (); + p++) { - file_stat fs (file); + std::string tfile = file_ops::concat (p->dir_name, file); + + file_stat fs (tfile); if (fs.exists ()) - return file; - } - else - { - for (const_dir_info_list_iterator p = dir_info_list.begin (); - p != dir_info_list.end (); - p++) - { - std::string tfile = file_ops::concat (p->dir_name, file); - - file_stat fs (tfile); - - if (fs.exists ()) - return tfile; - } + return tfile; } } else { + // Look in cache. + for (const_dir_info_list_iterator p = dir_info_list.begin (); p != dir_info_list.end (); p++) @@ -1515,6 +1650,12 @@ string_vector load_path::do_fcn_names (void) const { + return default_loader.fcn_names (); +} + +string_vector +load_path::loader::fcn_names (void) const +{ size_t len = fcn_map.size (); string_vector retval (len); @@ -1657,69 +1798,11 @@ } } - for (const_private_fcn_map_iterator i = private_fcn_map.begin (); - i != private_fcn_map.end (); i++) - { - os << "\n*** private functions in " - << file_ops::concat (i->first, "private") << ":\n\n"; - - print_fcn_list (os, i->second); - } - -#if defined (DEBUG_LOAD_PATH) - - for (const_fcn_map_iterator i = fcn_map.begin (); - i != fcn_map.end (); - i++) - { - os << i->first << ":\n"; - - const file_info_list_type& file_info_list = i->second; - - for (const_file_info_list_iterator p = file_info_list.begin (); - p != file_info_list.end (); - p++) - { - os << " " << p->dir_name << " ("; - - print_types (os, p->types); - - os << ")\n"; - } - } - - for (const_method_map_iterator i = method_map.begin (); - i != method_map.end (); - i++) - { - os << "CLASS " << i->first << ":\n"; - - const fcn_map_type& fm = i->second; - - for (const_fcn_map_iterator q = fm.begin (); - q != fm.end (); - q++) - { - os << " " << q->first << ":\n"; - - const file_info_list_type& file_info_list = q->second; - - for (const_file_info_list_iterator p = file_info_list.begin (); - p != file_info_list.end (); - p++) - { - os << " " << p->dir_name << " ("; - - print_types (os, p->types); - - os << ")\n"; - } - } - } - - os << "\n"; - -#endif + default_loader.display (os); + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + l->second.display (os); } // True if a path is contained in a path list separated by path_sep_char @@ -1743,7 +1826,29 @@ } void -load_path::add_to_fcn_map (const dir_info& di, bool at_end) const +load_path::add (const dir_info& di, bool at_end, + const std::string& pname) const +{ + loader& l = get_loader (pname); + + l.add (di, at_end); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin (); + p != package_dir_map.end (); ++p) + { + std::string full_name = p->first; + + if (! pname.empty ()) + full_name = pname + "." + full_name; + + add (p->second, at_end, full_name); + } +} + +void +load_path::loader::add_to_fcn_map (const dir_info& di, bool at_end) { std::string dir_name = di.dir_name; @@ -1839,7 +1944,7 @@ } void -load_path::add_to_private_fcn_map (const dir_info& di) const +load_path::loader::add_to_private_fcn_map (const dir_info& di) { dir_info::fcn_file_map_type private_file_map = di.private_file_map; @@ -1848,7 +1953,7 @@ } void -load_path::add_to_method_map (const dir_info& di, bool at_end) const +load_path::loader::add_to_method_map (const dir_info& di, bool at_end) { std::string dir_name = di.dir_name; @@ -1918,6 +2023,81 @@ } } +void +load_path::loader::display (std::ostream& os) const +{ + os << "*** loader: " << (prefix.empty () ? "" : prefix) << "\n\n"; + + for (std::list::const_iterator s = dir_list.begin (); + s != dir_list.end (); ++s) + os << *s << "\n"; + os << "\n"; + + for (const_private_fcn_map_iterator i = private_fcn_map.begin (); + i != private_fcn_map.end (); i++) + { + os << "\n*** private functions in " + << file_ops::concat (i->first, "private") << ":\n\n"; + + print_fcn_list (os, i->second); + } + +#if defined (DEBUG_LOAD_PATH) + + for (const_fcn_map_iterator i = fcn_map.begin (); + i != fcn_map.end (); + i++) + { + os << i->first << ":\n"; + + const file_info_list_type& file_info_list = i->second; + + for (const_file_info_list_iterator p = file_info_list.begin (); + p != file_info_list.end (); + p++) + { + os << " " << p->dir_name << " ("; + + print_types (os, p->types); + + os << ")\n"; + } + } + + for (const_method_map_iterator i = method_map.begin (); + i != method_map.end (); + i++) + { + os << "CLASS " << i->first << ":\n"; + + const fcn_map_type& fm = i->second; + + for (const_fcn_map_iterator q = fm.begin (); + q != fm.end (); + q++) + { + os << " " << q->first << ":\n"; + + const file_info_list_type& file_info_list = q->second; + + for (const_file_info_list_iterator p = file_info_list.begin (); + p != file_info_list.end (); + p++) + { + os << " " << p->dir_name << " ("; + + print_types (os, p->types); + + os << ")\n"; + } + } + } + + os << "\n"; + +#endif +} + std::string genpath (const std::string& dirname, const string_vector& skip) { @@ -1929,7 +2109,7 @@ { retval = dirname; - string_vector dirlist = dir.read (); + string_vector dirlist = dir.read ().sort (false); octave_idx_type len = dirlist.length (); @@ -1937,7 +2117,8 @@ { std::string elt = dirlist[i]; - bool skip_p = (elt == "." || elt == ".." || elt[0] == '@'); + bool skip_p = (elt == "." || elt == ".." || elt[0] == '@' + || elt[0] == '+'); if (! skip_p) { @@ -1964,6 +2145,21 @@ return retval; } +std::list +load_path::do_get_all_package_names (bool only_top_level) const +{ + std::list retval; + + for (const_loader_map_iterator l = loader_map.begin (); + l != loader_map.end (); ++l) + { + if (! only_top_level || l->first.find ('.') == std::string::npos) + retval.push_back (l->first); + } + + return retval; +} + static void execute_pkg_add_or_del (const std::string& dir, const std::string& script_file) @@ -2339,3 +2535,10 @@ return retval; } + +DEFUN (__dump_load_path__, , , "") +{ + load_path::display (octave_stdout); + + return octave_value_list (); +} diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/load-path.h --- a/libinterp/corefcn/load-path.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/load-path.h Sun May 25 10:29:05 2014 -0700 @@ -39,8 +39,7 @@ protected: load_path (void) - : dir_info_list (), fcn_map (), private_fcn_map (), method_map (), - init_dirs () { } + : loader_map (), default_loader (), dir_info_list (), init_dirs () { } public: @@ -96,24 +95,29 @@ static std::string find_method (const std::string& class_name, const std::string& meth, - std::string& dir_name) + std::string& dir_name, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_find_method (class_name, meth, dir_name) - : std::string (); + ? instance->get_loader (pack_name).find_method (class_name, meth, + dir_name) + : std::string (); } static std::string find_method (const std::string& class_name, - const std::string& meth) + const std::string& meth, + const std::string& pack_name = std::string ()) { std::string dir_name; - return find_method (class_name, meth, dir_name); + return find_method (class_name, meth, dir_name, pack_name); } - static std::list methods (const std::string& class_name) + static std::list methods (const std::string& class_name, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_methods (class_name) : std::list (); + ? instance->get_loader(pack_name).methods (class_name) + : std::list (); } static std::list overloads (const std::string& meth) @@ -122,47 +126,72 @@ ? instance->do_overloads (meth) : std::list (); } - static std::string find_fcn (const std::string& fcn, std::string& dir_name) + static bool find_package (const std::string& package_name) + { + return instance_ok () + ? instance->do_find_package (package_name) : false; + } + + static std::list + get_all_package_names (bool only_top_level = true) { return instance_ok () - ? instance->do_find_fcn (fcn, dir_name) : std::string (); + ? instance->do_get_all_package_names (only_top_level) + : std::list (); } - static std::string find_fcn (const std::string& fcn) + static std::string find_fcn (const std::string& fcn, std::string& dir_name, + const std::string& pack_name = std::string ()) + { + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name) + : std::string (); + } + + static std::string find_fcn (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return find_fcn (fcn, dir_name); + return find_fcn (fcn, dir_name, pack_name); } static std::string find_private_fcn (const std::string& dir, - const std::string& fcn) + const std::string& fcn, + const std::string& pack_name = std::string ()) { return instance_ok () - ? instance->do_find_private_fcn (dir, fcn) : std::string (); + ? instance->get_loader (pack_name).find_private_fcn (dir, fcn) + : std::string (); } - static std::string find_fcn_file (const std::string& fcn) + static std::string find_fcn_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, M_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } - static std::string find_oct_file (const std::string& fcn) + static std::string find_oct_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, OCT_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } - static std::string find_mex_file (const std::string& fcn) + static std::string find_mex_file (const std::string& fcn, + const std::string& pack_name = std::string ()) { std::string dir_name; - return instance_ok () ? - instance->do_find_fcn (fcn, dir_name, MEX_FILE) : std::string (); + return instance_ok () + ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE) + : std::string (); } static std::string find_file (const std::string& file) @@ -297,19 +326,27 @@ typedef method_file_map_type::const_iterator const_method_file_map_iterator; typedef method_file_map_type::iterator method_file_map_iterator; + // + typedef std::map package_dir_map_type; + + typedef package_dir_map_type::const_iterator const_package_dir_map_iterator; + typedef package_dir_map_type::iterator package_dir_map_iterator; + // This default constructor is only provided so we can create a // std::map of dir_info objects. You should not use this // constructor for any other purpose. dir_info (void) : dir_name (), abs_dir_name (), is_relative (false), dir_mtime (), dir_time_last_checked (), - all_files (), fcn_files (), private_file_map (), method_file_map () + all_files (), fcn_files (), private_file_map (), method_file_map (), + package_dir_map () { } dir_info (const std::string& d) : dir_name (d), abs_dir_name (), is_relative (false), dir_mtime (), dir_time_last_checked (), - all_files (), fcn_files (), private_file_map (), method_file_map () + all_files (), fcn_files (), private_file_map (), method_file_map (), + package_dir_map () { initialize (); } @@ -321,7 +358,8 @@ dir_time_last_checked (di.dir_time_last_checked), all_files (di.all_files), fcn_files (di.fcn_files), private_file_map (di.private_file_map), - method_file_map (di.method_file_map) { } + method_file_map (di.method_file_map), + package_dir_map (di.package_dir_map) { } ~dir_info (void) { } @@ -338,6 +376,7 @@ fcn_files = di.fcn_files; private_file_map = di.private_file_map; method_file_map = di.method_file_map; + package_dir_map = di.package_dir_map; } return *this; @@ -354,6 +393,7 @@ string_vector fcn_files; fcn_file_map_type private_file_map; method_file_map_type method_file_map; + package_dir_map_type package_dir_map; private: @@ -366,6 +406,9 @@ void get_method_file_map (const std::string& d, const std::string& class_name); + void get_package_dir (const std::string& d, + const std::string& package_name); + friend fcn_file_map_type get_fcn_files (const std::string& d); }; @@ -442,13 +485,125 @@ typedef method_map_type::const_iterator const_method_map_iterator; typedef method_map_type::iterator method_map_iterator; - mutable dir_info_list_type dir_info_list; + class loader + { + public: + loader (const std::string& pfx = std::string ()) + : prefix (pfx), dir_list (), fcn_map (), private_fcn_map (), + method_map () { } + + loader (const loader& l) + : prefix (l.prefix), dir_list (l.dir_list), + private_fcn_map (l.private_fcn_map), method_map (l.method_map) { } + + ~loader (void) { } + + loader& operator = (const loader& l) + { + if (&l != this) + { + prefix = l.prefix; + dir_list = l.dir_list; + fcn_map = l.fcn_map; + private_fcn_map = l.private_fcn_map; + method_map = l.method_map; + } + + return *this; + } - mutable fcn_map_type fcn_map; + void add (const dir_info& di, bool at_end) + { + if (at_end) + dir_list.push_back (di.dir_name); + else + dir_list.push_front (di.dir_name); + + add_to_fcn_map (di, at_end); + + add_to_private_fcn_map (di); + + add_to_method_map (di, at_end); + } + + void move (const dir_info& di, bool at_end); + + void remove (const dir_info& di); + + void clear (void) + { + dir_list.clear (); + + fcn_map.clear (); + + private_fcn_map.clear (); + + method_map.clear (); + } + + void display (std::ostream& out) const; - mutable private_fcn_map_type private_fcn_map; + std::string find_fcn (const std::string& fcn, + std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string find_private_fcn (const std::string& dir, + const std::string& fcn, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::list methods (const std::string& class_name) const; + + void overloads (const std::string& meth, std::list& l) const; + + string_vector fcn_names (void) const; + + private: + void add_to_fcn_map (const dir_info& di, bool at_end); + + void add_to_private_fcn_map (const dir_info& di); + + void add_to_method_map (const dir_info& di, bool at_end); + + void move_fcn_map (const std::string& dir, + const string_vector& fcn_files, bool at_end); + + void move_method_map (const std::string& dir, bool at_end); - mutable method_map_type method_map; + void remove_fcn_map (const std::string& dir, + const string_vector& fcn_files); + + void remove_private_fcn_map (const std::string& dir); + + void remove_method_map (const std::string& dir); + + private: + std::string prefix; + + std::list dir_list; + + fcn_map_type fcn_map; + + private_fcn_map_type private_fcn_map; + + method_map_type method_map; + }; + + // + typedef std::map loader_map_type; + + typedef loader_map_type::const_iterator const_loader_map_iterator; + typedef loader_map_type::iterator loader_map_iterator; + + mutable loader_map_type loader_map; + + mutable loader default_loader; + + mutable dir_info_list_type dir_info_list; mutable std::set init_dirs; @@ -475,12 +630,13 @@ bool do_contains_canonical (const std::string& dir) const; - void move_fcn_map (const std::string& dir, - const string_vector& fcn_files, bool at_end); + void do_move (dir_info_list_iterator i, bool at_end); - void move_method_map (const std::string& dir, bool at_end); + void move (const dir_info& di, bool at_end, + const std::string& pname = std::string ()); - void move (std::list::iterator i, bool at_end); + void remove (const dir_info& di, + const std::string& pname = std::string ()); void do_initialize (bool set_initial_path); @@ -494,12 +650,6 @@ void do_add (const std::string& dir, bool at_end, bool warn); - void remove_fcn_map (const std::string& dir, const string_vector& fcn_files); - - void remove_private_fcn_map (const std::string& dir); - - void remove_method_map (const std::string& dir); - bool do_remove (const std::string& dir); void do_update (void) const; @@ -508,23 +658,31 @@ check_file_type (std::string& fname, int type, int possible_types, const std::string& fcn, const char *who); - std::string do_find_fcn (const std::string& fcn, - std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + loader& get_loader (const std::string& name) const + { + if (! name.empty ()) + { + loader_map_iterator l = loader_map.find (name); - std::string do_find_private_fcn (const std::string& dir, - const std::string& fcn, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + if (l == loader_map.end ()) + l = loader_map.insert (loader_map.end (), + loader_map_type::value_type (name, loader (name))); - std::string do_find_method (const std::string& class_name, - const std::string& meth, - std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + return l->second; + } - std::list do_methods (const std::string& class_name) const; + return default_loader; + } std::list do_overloads (const std::string& meth) const; + bool do_find_package (const std::string& package_name) const + { + return (loader_map.find (package_name) != loader_map.end ()); + } + + std::list do_get_all_package_names (bool only_top_level) const; + std::string do_find_file (const std::string& file) const; std::string do_find_dir (const std::string& dir) const; @@ -559,11 +717,8 @@ std::string do_get_command_line_path (void) const { return command_line_path; } - void add_to_fcn_map (const dir_info& di, bool at_end) const; - - void add_to_private_fcn_map (const dir_info& di) const; - - void add_to_method_map (const dir_info& di, bool at_end) const; + void add (const dir_info& di, bool at_end, + const std::string& pname = std::string ()) const; friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d); }; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/load-save.cc --- a/libinterp/corefcn/load-save.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/load-save.cc Sun May 25 10:29:05 2014 -0700 @@ -502,17 +502,24 @@ if (! (octave_env::absolute_pathname (fname) || octave_env::rooted_relative_pathname (fname))) { + // Load path will also search "." first, but we don't want to + // issue a warning if the file is found in the current directory, + // so do an explicit check for that. + file_stat fs (fname); if (! (fs.exists () && fs.is_reg ())) { + // Not directly found; search load path. + std::string tmp = octave_env::make_absolute (load_path::find_file (fname)); if (! tmp.empty ()) { warning_with_id ("Octave:load-file-in-path", - "load: file found in load path"); + "load: file found in load path: %s", + tmp.c_str ()); fname = tmp; } } @@ -1065,7 +1072,8 @@ string_vector retval; int argc = argv.length (); - bool do_double = false, do_tabs = false; + bool do_double = false; + bool do_tabs = false; for (int i = 0; i < argc; i++) { @@ -1615,8 +1623,6 @@ { octave_value_list retval; - int argc = args.length (); - string_vector argv = args.make_argv (); if (error_state) @@ -1640,7 +1646,7 @@ // override from command line argv = parse_save_options (argv, format, append, save_as_floats, use_zlib); - argc = argv.length (); + int argc = argv.length (); int i = 0; if (error_state) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/lookup.cc --- a/libinterp/corefcn/lookup.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/lookup.cc Sun May 25 10:29:05 2014 -0700 @@ -115,7 +115,8 @@ octave_value retval; Array idx = array.lookup (values); - octave_idx_type n = array.numel (), nval = values.numel (); + octave_idx_type n = array.numel (); + octave_idx_type nval = values.numel (); // Post-process. if (match_bool) @@ -246,7 +247,8 @@ return retval; } - octave_value table = args(0), y = args(1); + octave_value table = args(0); + octave_value y = args(1); if (table.ndims () > 2 || (table.columns () > 1 && table.rows () > 1)) warning ("lookup: table is not a vector"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/ls-hdf5.cc --- a/libinterp/corefcn/ls-hdf5.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/ls-hdf5.cc Sun May 25 10:29:05 2014 -0700 @@ -263,7 +263,7 @@ // Allow identifiers as all digits so we can load lists saved by // earlier versions of Octave. - if (! ident_valid ) + if (! ident_valid) { // fix the identifier, replacing invalid chars with underscores vname = make_valid_identifier (vname); @@ -528,6 +528,7 @@ { warning ("load: can't read '%s' (unknown datatype)", name); retval = 0; // unknown datatype; skip + return retval; } // check for OCTAVE_GLOBAL attribute: @@ -615,7 +616,7 @@ len = H5Gget_objname_by_idx (hs.file_id, hs.current_item, 0, 0); var_name.resize (len+1); - H5Gget_objname_by_idx( hs.file_id, hs.current_item, &var_name[0], len+1); + H5Gget_objname_by_idx (hs.file_id, hs.current_item, &var_name[0], len+1); for (int i = argv_idx; i < argc; i++) { @@ -738,7 +739,8 @@ hsize_t sz = d.length (); OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz); bool empty = false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid = -1; + hid_t data_hid = -1; int retval; for (hsize_t i = 0; i < sz; i++) { @@ -865,7 +867,9 @@ bool mark_as_global, bool save_as_floats) { hsize_t dims[3]; - hid_t type_id = -1, space_id = -1, data_id = -1, data_type_id = -1; + hid_t type_id, space_id, data_id, data_type_id; + type_id = space_id = data_id = data_type_id = -1; + bool retval = false; octave_value val = tc; // FIXME: diagonal & permutation matrices currently don't know how to save diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/ls-mat4.cc --- a/libinterp/corefcn/ls-mat4.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/ls-mat4.cc Sun May 25 10:29:05 2014 -0700 @@ -461,7 +461,6 @@ len = nr * nc; } - // LEN includes the terminating character, and the file is also // supposed to include it. @@ -489,7 +488,10 @@ for (octave_idx_type j = 0; j < ncol; j++) buf[j*nrow+i] = static_cast (*s++ & 0x00FF); } - os.write (reinterpret_cast (buf), nrow*ncol*sizeof (double)); + std::streamsize n_bytes = static_cast (nrow) * + static_cast (ncol) * + sizeof (double); + os.write (reinterpret_cast (buf), n_bytes); } else if (tc.is_range ()) { @@ -518,7 +520,8 @@ for (octave_idx_type i = 0; i < len; i++) dtmp[i] = m.ridx (i) + 1; - os.write (reinterpret_cast (dtmp), 8 * len); + std::streamsize n_bytes = 8 * static_cast (len); + os.write (reinterpret_cast (dtmp), n_bytes); ds = nr; os.write (reinterpret_cast (&ds), 8); @@ -526,19 +529,19 @@ for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) dtmp[ii++] = j + 1; - os.write (reinterpret_cast (dtmp), 8 * len); + os.write (reinterpret_cast (dtmp), n_bytes); ds = nc; os.write (reinterpret_cast (&ds), 8); for (octave_idx_type i = 0; i < len; i++) dtmp[i] = std::real (m.data (i)); - os.write (reinterpret_cast (dtmp), 8 * len); + os.write (reinterpret_cast (dtmp), n_bytes); ds = 0.; os.write (reinterpret_cast (&ds), 8); for (octave_idx_type i = 0; i < len; i++) dtmp[i] = std::imag (m.data (i)); - os.write (reinterpret_cast (dtmp), 8 * len); + os.write (reinterpret_cast (dtmp), n_bytes); os.write (reinterpret_cast (&ds), 8); } else @@ -547,7 +550,8 @@ for (octave_idx_type i = 0; i < len; i++) dtmp[i] = m.ridx (i) + 1; - os.write (reinterpret_cast (dtmp), 8 * len); + std::streamsize n_bytes = 8 * static_cast (len); + os.write (reinterpret_cast (dtmp), n_bytes); ds = nr; os.write (reinterpret_cast (&ds), 8); @@ -555,11 +559,11 @@ for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) dtmp[ii++] = j + 1; - os.write (reinterpret_cast (dtmp), 8 * len); + os.write (reinterpret_cast (dtmp), n_bytes); ds = nc; os.write (reinterpret_cast (&ds), 8); - os.write (reinterpret_cast (m.data ()), 8 * len); + os.write (reinterpret_cast (m.data ()), n_bytes); ds = 0.; os.write (reinterpret_cast (&ds), 8); } @@ -567,7 +571,8 @@ else if (tc.is_real_matrix ()) { Matrix m = tc.matrix_value (); - os.write (reinterpret_cast (m.data ()), 8 * len); + std::streamsize n_bytes = 8 * static_cast (len); + os.write (reinterpret_cast (m.data ()), n_bytes); } else if (tc.is_complex_scalar ()) { @@ -578,9 +583,10 @@ { ComplexMatrix m_cmplx = tc.complex_matrix_value (); Matrix m = ::real (m_cmplx); - os.write (reinterpret_cast (m.data ()), 8 * len); + std::streamsize n_bytes = 8 * static_cast (len); + os.write (reinterpret_cast (m.data ()), n_bytes); m = ::imag (m_cmplx); - os.write (reinterpret_cast (m.data ()), 8 * len); + os.write (reinterpret_cast (m.data ()), n_bytes); } else gripe_wrong_type_arg ("save", tc, false); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/ls-mat5.cc --- a/libinterp/corefcn/ls-mat5.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/ls-mat5.cc Sun May 25 10:29:05 2014 -0700 @@ -264,7 +264,8 @@ if (len > 0) \ { \ OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \ - stream.read (reinterpret_cast (ptr), size * len); \ + std::streamsize n_bytes = size * static_cast (len); \ + stream.read (reinterpret_cast (ptr), n_bytes); \ if (swap) \ swap_bytes< size > (ptr, len); \ for (octave_idx_type i = 0; i < len; i++) \ @@ -439,7 +440,7 @@ unsigned int upper; int32_t temp; - if (! is.read (reinterpret_cast (&temp), 4 )) + if (! is.read (reinterpret_cast (&temp), 4)) goto data_read_error; if (swap) @@ -456,7 +457,7 @@ } else { - if (! is.read (reinterpret_cast (&temp), 4 )) + if (! is.read (reinterpret_cast (&temp), 4)) goto data_read_error; if (swap) swap_bytes<4> (&temp); @@ -701,7 +702,7 @@ if (len) { - if (! is.read (name, len )) + if (! is.read (name, len)) goto data_read_error; is.seekg (tmp_pos + static_cast @@ -929,7 +930,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (str, dir_name, "", fname); + = load_fcn_from_file (str, dir_name, "", "", fname); if (fcn) { @@ -958,7 +959,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (str, dir_name, "", fname); + = load_fcn_from_file (str, dir_name, "", "", fname); if (fcn) { @@ -983,7 +984,7 @@ std::string dir_name = fpath.substr (0, xpos); octave_function *fcn - = load_fcn_from_file (fpath, dir_name, "", fname); + = load_fcn_from_file (fpath, dir_name, "", "", fname); if (fcn) { @@ -1163,7 +1164,7 @@ if (len) { - if (! is.read (name, len )) + if (! is.read (name, len)) goto data_read_error; is.seekg (tmp_pos + static_cast @@ -1193,7 +1194,7 @@ goto data_read_error; } - if (! is.read (reinterpret_cast (&field_name_length), fn_len )) + if (! is.read (reinterpret_cast (&field_name_length), fn_len)) goto data_read_error; if (swap) @@ -1560,7 +1561,8 @@ read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet, const std::string& filename) { - int16_t version=0, magic=0; + int16_t version = 0; + int16_t magic = 0; uint64_t subsys_offset; is.seekg (116, std::ios::beg); @@ -1666,7 +1668,8 @@ OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \ for (octave_idx_type i = 0; i < count; i++) \ ptr[i] = static_cast (data[i]); \ - stream.write (reinterpret_cast (ptr), count * sizeof (TYPE)); \ + std::streamsize n_bytes = sizeof (TYPE) * static_cast (count); \ + stream.write (reinterpret_cast (ptr), n_bytes); \ } \ while (0) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/lu.cc --- a/libinterp/corefcn/lu.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/lu.cc Sun May 25 10:29:05 2014 -0700 @@ -158,11 +158,11 @@ int n = 1; while (n < nargin && ! error_state) { - if (args (n).is_string ()) + if (args(n).is_string ()) { std::string tmp = args(n++).string_value (); - if (! error_state ) + if (! error_state) { if (tmp.compare ("vector") == 0) vecout = true; @@ -174,7 +174,7 @@ { Matrix tmp = args(n++).matrix_value (); - if (! error_state ) + if (! error_state) { if (!issparse) error ("lu: can not define pivoting threshold THRES for full matrices"); @@ -211,7 +211,7 @@ SparseMatrix m = arg.sparse_matrix_value (); - if ( nargout < 4 ) + if (nargout < 4) { ColumnVector Qinit; @@ -220,7 +220,7 @@ Qinit (i) = i; SparseLU fact (m, Qinit, thres, false, true); - if ( nargout < 2 ) + if (nargout < 2) retval(0) = fact.Y (); else { @@ -233,15 +233,15 @@ PermMatrix P = fact.Pr_mat (); SparseMatrix L = fact.L (); - if ( nargout < 3 ) + if (nargout < 3) retval(0) - = octave_value ( P.transpose () * L, + = octave_value (P.transpose () * L, MatrixType (MatrixType::Permuted_Lower, nr, fact.row_perm ())); else { retval(0) = L; - if ( vecout ) + if (vecout) retval(2) = fact.Pr_vec(); else retval(2) = P; @@ -279,7 +279,7 @@ { SparseComplexMatrix m = arg.sparse_complex_matrix_value (); - if ( nargout < 4 ) + if (nargout < 4) { ColumnVector Qinit; @@ -288,7 +288,7 @@ Qinit (i) = i; SparseComplexLU fact (m, Qinit, thres, false, true); - if ( nargout < 2 ) + if (nargout < 2) retval(0) = fact.Y (); @@ -303,15 +303,15 @@ PermMatrix P = fact.Pr_mat (); SparseComplexMatrix L = fact.L (); - if ( nargout < 3 ) + if (nargout < 3) retval(0) - = octave_value ( P.transpose () * L, + = octave_value (P.transpose () * L, MatrixType (MatrixType::Permuted_Lower, nr, fact.row_perm ())); else { retval(0) = L; - if ( vecout ) + if (vecout) retval(2) = fact.Pr_vec(); else retval(2) = P; @@ -592,7 +592,9 @@ bool check_lu_dims (const octave_value& l, const octave_value& u, const octave_value& p) { - octave_idx_type m = l.rows (), k = u.rows (), n = u.columns (); + octave_idx_type m = l.rows (); + octave_idx_type k = u.rows (); + octave_idx_type n = u.columns (); return ((l.ndims () == 2 && u.ndims () == 2 && k == l.columns ()) && k == std::min (m, n) && (p.is_undefined () || p.rows () == m)); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/luinc.cc --- a/libinterp/corefcn/luinc.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/luinc.cc Sun May 25 10:29:05 2014 -0700 @@ -177,7 +177,7 @@ { std::string tmp = args(2).string_value (); - if (! error_state ) + if (! error_state) { if (tmp.compare ("vector") == 0) vecout = true; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/mappers.cc --- a/libinterp/corefcn/mappers.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/mappers.cc Sun May 25 10:29:05 2014 -0700 @@ -2156,8 +2156,17 @@ %!assert (tolower ({"ABC", "DEF", {"GHI", {"JKL"}}}), {"abc", "def", {"ghi", {"jkl"}}}) %!assert (tolower (["ABC"; "DEF"]), ["abc"; "def"]) %!assert (tolower ({["ABC"; "DEF"]}), {["abc";"def"]}) -%!assert (tolower (68), "d") -%!assert (tolower ({[68, 68; 68, 68]}), {["dd";"dd"]}) +%!assert (tolower (68), 68) +%!assert (tolower ({[68, 68; 68, 68]}), {[68, 68; 68, 68]}) +%!test +%! classes = {@char, @double, @single, ... +%! @int8, @int16, @int32, @int64, ... +%! @uint8, @uint16, @uint32, @uint64}; +%! for i = 1:numel (classes) +%! cls = classes{i}; +%! assert (class (tolower (cls (97))), class (cls (97))); +%! assert (class (tolower (cls ([98, 99]))), class (cls ([98, 99]))); +%! endfor %!test %! a(3,3,3,3) = "D"; %! assert (tolower (a)(3,3,3,3), "d"); @@ -2207,8 +2216,17 @@ %!assert (toupper ({"abc", "def", {"ghi", {"jkl"}}}), {"ABC", "DEF", {"GHI", {"JKL"}}}) %!assert (toupper (["abc"; "def"]), ["ABC"; "DEF"]) %!assert (toupper ({["abc"; "def"]}), {["ABC";"DEF"]}) -%!assert (toupper (100), "D") -%!assert (toupper ({[100, 100; 100, 100]}), {["DD";"DD"]}) +%!assert (toupper (100), 100) +%!assert (toupper ({[100, 100; 100, 100]}), {[100, 100; 100, 100]}) +%!test +%! classes = {@char, @double, @single, ... +%! @int8, @int16, @int32, @int64, ... +%! @uint8, @uint16, @uint32, @uint64}; +%! for i = 1:numel (classes) +%! cls = classes{i}; +%! assert (class (toupper (cls (97))), class (cls (97))); +%! assert (class (toupper (cls ([98, 99]))), class (cls ([98, 99]))); +%! endfor %!test %! a(3,3,3,3) = "d"; %! assert (toupper (a)(3,3,3,3), "D"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/matrix_type.cc --- a/libinterp/corefcn/matrix_type.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/matrix_type.cc Sun May 25 10:29:05 2014 -0700 @@ -148,7 +148,7 @@ { mattyp = args(0).matrix_type (); - if (mattyp.is_unknown () && autocomp ) + if (mattyp.is_unknown () && autocomp) { SparseComplexMatrix m = args(0).sparse_complex_matrix_value (); @@ -281,7 +281,7 @@ && (str_typ == "upper" || str_typ == "lower")) { const ColumnVector perm = - ColumnVector (args (2).vector_value ()); + ColumnVector (args(2).vector_value ()); if (error_state) error ("matrix_type: Invalid permutation vector PERM"); @@ -454,7 +454,7 @@ || str_typ == "lower")) { const ColumnVector perm = - ColumnVector (args (2).vector_value ()); + ColumnVector (args(2).vector_value ()); if (error_state) error ("matrix_type: Invalid permutation vector PERM"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/max.cc --- a/libinterp/corefcn/max.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/max.cc Sun May 25 10:29:05 2014 -0700 @@ -354,8 +354,10 @@ } else if (nargin == 2) { - octave_value argx = args(0), argy = args(1); - builtin_type_t xtyp = argx.builtin_type (), ytyp = argy.builtin_type (); + octave_value argx = args(0); + octave_value argy = args(1); + builtin_type_t xtyp = argx.builtin_type (); + builtin_type_t ytyp = argy.builtin_type (); builtin_type_t rtyp; if (xtyp == btyp_char && ytyp == btyp_char) rtyp = btyp_char; @@ -560,6 +562,10 @@ %! assert (ndims(i), 2); %! assert (i, [1, 1; 1, 1]); +## Test for bug #40743 +%!assert (max (zeros (1,0), ones (1,1)), zeros (1,0)) +%!assert (max (sparse (zeros (1,0)), sparse (ones (1,1))), sparse (zeros (1,0))) + %!error max () %!error max (1, 2, 3, 4) */ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/module.mk Sun May 25 10:29:05 2014 -0700 @@ -91,6 +91,7 @@ corefcn/oct-stream.h \ corefcn/oct-strstrm.h \ corefcn/oct.h \ + corefcn/octave-default-image.h \ corefcn/octave-link.h \ corefcn/pager.h \ corefcn/pr-output.h \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/oct-map.cc --- a/libinterp/corefcn/oct-map.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/oct-map.cc Sun May 25 10:29:05 2014 -0700 @@ -117,7 +117,8 @@ { bool retval = true; - iterator p = begin (), q = other.begin (); + iterator p = begin (); + iterator q = other.begin (); for (; p != end () && q != other.end (); p++, q++) { if (p->first == q->first) @@ -251,15 +252,6 @@ } } -octave_map::octave_map (const Octave_map& m) - : xkeys (m.keys ()), xvals (m.nfields ()), dimensions (m.dims ()) -{ - for (iterator p = begin (); p != end (); p++) - contents(p) = m.contents (key (p)); - - optimize_dimensions (); -} - Cell octave_map::getfield (const std::string& k) const { @@ -819,9 +811,9 @@ %! sr = [s,s]; %! sc = [s;s]; %! sm = [s,s;s,s]; -%! assert (nfields (sr), 0); -%! assert (nfields (sc), 0); -%! assert (nfields (sm), 0); +%! assert (numfields (sr), 0); +%! assert (numfields (sc), 0); +%! assert (numfields (sm), 0); %! assert (size (sr), [1, 2]); %! assert (size (sc), [2, 1]); %! assert (size (sm), [2, 2]); @@ -1314,470 +1306,3 @@ } -Octave_map::Octave_map (const dim_vector& dv, const Cell& key_vals) - : map (), key_list (), dimensions (dv) -{ - Cell c (dv); - - if (key_vals.is_cellstr ()) - { - for (octave_idx_type i = 0; i < key_vals.numel (); i++) - { - std::string k = key_vals(i).string_value (); - map[k] = c; - key_list.push_back (k); - } - } - else - error ("Octave_map: expecting keys to be cellstr"); -} - -Octave_map::Octave_map (const octave_map& m) - : map (), key_list (), dimensions (m.dims ()) -{ - for (octave_map::const_iterator p = m.begin (); p != m.end (); p++) - map[m.key (p)] = m.contents (p); - const string_vector mkeys = m.fieldnames (); - for (octave_idx_type i = 0; i < mkeys.numel (); i++) - key_list.push_back (mkeys(i)); -} - -Octave_map -Octave_map::squeeze (void) const -{ - Octave_map retval (dims ().squeeze ()); - - for (const_iterator pa = begin (); pa != end (); pa++) - { - Cell tmp = contents (pa).squeeze (); - - if (error_state) - break; - - retval.assign (key (pa), tmp); - } - - // Preserve order of keys. - retval.key_list = key_list; - - return retval; -} - -Octave_map -Octave_map::permute (const Array& vec, bool inv) const -{ - Octave_map retval (dims ()); - - for (const_iterator pa = begin (); pa != end (); pa++) - { - Cell tmp = contents (pa).permute (vec, inv); - - if (error_state) - break; - - retval.assign (key (pa), tmp); - } - - // Preserve order of keys. - retval.key_list = key_list; - - return retval; -} - -Cell& -Octave_map::contents (const std::string& k) -{ - maybe_add_to_key_list (k); - - return map[k]; -} - -Cell -Octave_map::contents (const std::string& k) const -{ - const_iterator p = seek (k); - - return p != end () ? p->second : Cell (); -} - -int -Octave_map::intfield (const std::string& k, int def_val) const -{ - int retval = def_val; - - Cell c = contents (k); - - if (! c.is_empty ()) - retval = c(0).int_value (); - - return retval; -} - -std::string -Octave_map::stringfield (const std::string& k, - const std::string& def_val) const -{ - std::string retval = def_val; - - Cell c = contents (k); - - if (! c.is_empty ()) - retval = c(0).string_value (); - - return retval; -} - -string_vector -Octave_map::keys (void) const -{ - assert (static_cast(nfields ()) == key_list.size ()); - - return string_vector (key_list); -} - -Octave_map -Octave_map::transpose (void) const -{ - assert (ndims () == 2); - - dim_vector dv = dims (); - - octave_idx_type nr = dv(0); - octave_idx_type nc = dv(1); - - dim_vector new_dims (nc, nr); - - Octave_map retval (new_dims); - - for (const_iterator p = begin (); p != end (); p++) - retval.assign (key(p), Cell (contents(p).transpose ())); - - // Preserve order of keys. - retval.key_list = key_list; - - return retval; -} - -Octave_map -Octave_map::reshape (const dim_vector& new_dims) const -{ - Octave_map retval; - - if (new_dims != dims ()) - { - for (const_iterator p = begin (); p != end (); p++) - retval.assign (key(p), contents(p).reshape (new_dims)); - - retval.dimensions = new_dims; - - // Preserve order of keys. - retval.key_list = key_list; - } - else - retval = *this; - - return retval; -} - -void -Octave_map::resize (const dim_vector& dv, bool fill) -{ - if (dv != dims ()) - { - if (nfields () == 0) - dimensions = dv; - else - { - for (const_iterator p = begin (); p != end (); p++) - { - Cell tmp = contents(p); - - if (fill) - tmp.resize (dv, Matrix ()); - else - tmp.resize (dv); - - dimensions = dv; - - assign (key(p), tmp); - } - } - } -} - -Octave_map -Octave_map::concat (const Octave_map& rb, const Array& ra_idx) -{ - Octave_map retval; - - if (nfields () == rb.nfields ()) - { - for (const_iterator pa = begin (); pa != end (); pa++) - { - const_iterator pb = rb.seek (key(pa)); - - if (pb == rb.end ()) - { - error ("field name mismatch in structure concatenation"); - break; - } - - retval.assign (key(pa), - contents(pa).insert (rb.contents(pb), ra_idx)); - } - - // Preserve order of keys. - retval.key_list = key_list; - } - else - { - dim_vector dv = dims (); - - if (dv.all_zero ()) - retval = rb; - else - { - dv = rb.dims (); - - if (dv.all_zero ()) - retval = *this; - else - error ("invalid structure concatenation"); - } - } - - return retval; -} - -static bool -keys_ok (const Octave_map& a, const Octave_map& b, string_vector& keys) -{ - bool retval = false; - - keys = string_vector (); - - if (a.nfields () == 0) - { - keys = b.keys (); - retval = true; - } - else - { - string_vector a_keys = a.keys ().sort (); - string_vector b_keys = b.keys ().sort (); - - octave_idx_type a_len = a_keys.length (); - octave_idx_type b_len = b_keys.length (); - - if (a_len == b_len) - { - for (octave_idx_type i = 0; i < a_len; i++) - { - if (a_keys[i] != b_keys[i]) - goto done; - } - - keys = a_keys; - retval = true; - } - } - -done: - return retval; -} - -Octave_map& -Octave_map::maybe_delete_elements (const octave_value_list& idx) -{ - string_vector t_keys = keys (); - octave_idx_type len = t_keys.length (); - - if (len > 0) - { - for (octave_idx_type i = 0; i < len; i++) - { - std::string k = t_keys[i]; - - contents(k).delete_elements (idx); - - if (error_state) - break; - } - - if (!error_state) - dimensions = contents(t_keys[0]).dims (); - } - - return *this; -} - -Octave_map& -Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs) -{ - string_vector t_keys; - - if (keys_ok (*this, rhs, t_keys)) - { - octave_idx_type len = t_keys.length (); - - if (len == 0) - { - Cell tmp_lhs (dims ()); - Cell tmp_rhs (rhs.dims ()); - - tmp_lhs.assign (idx, tmp_rhs, Matrix ()); - - if (! error_state) - resize (tmp_lhs.dims ()); - else - error ("size mismatch in structure assignment"); - } - else - { - for (octave_idx_type i = 0; i < len; i++) - { - std::string k = t_keys[i]; - - Cell t_rhs = rhs.contents (k); - - assign (idx, k, t_rhs); - - if (error_state) - break; - } - } - } - else - error ("field name mismatch in structure assignment"); - - return *this; -} - -Octave_map& -Octave_map::assign (const octave_value_list& idx, const std::string& k, - const Cell& rhs) -{ - Cell tmp; - - if (contains (k)) - tmp = map[k]; - else - tmp = Cell (dimensions); - - tmp.assign (idx, rhs); - - if (! error_state) - { - dim_vector tmp_dims = tmp.dims (); - - if (tmp_dims != dimensions) - { - for (iterator p = begin (); p != end (); p++) - contents(p).resize (tmp_dims, Matrix ()); - - dimensions = tmp_dims; - } - - maybe_add_to_key_list (k); - - map[k] = tmp; - } - - return *this; -} - -Octave_map& -Octave_map::assign (const std::string& k, const octave_value& rhs) -{ - if (nfields () == 0) - { - maybe_add_to_key_list (k); - - map[k] = Cell (rhs); - - dimensions = dim_vector (1, 1); - } - else - { - dim_vector dv = dims (); - - if (dv.all_ones ()) - { - maybe_add_to_key_list (k); - - map[k] = Cell (rhs); - } - else - error ("invalid structure assignment"); - } - - return *this; -} - -Octave_map& -Octave_map::assign (const std::string& k, const Cell& rhs) -{ - if (nfields () == 0) - { - maybe_add_to_key_list (k); - - map[k] = rhs; - - dimensions = rhs.dims (); - } - else - { - if (dims () == rhs.dims ()) - { - maybe_add_to_key_list (k); - - map[k] = rhs; - } - else - error ("invalid structure assignment"); - } - - return *this; -} - -Octave_map -Octave_map::index (const octave_value_list& idx, bool resize_ok) const -{ - Octave_map retval; - - octave_idx_type n_idx = idx.length (); - - if (n_idx > 0) - { - Array ra_idx (dim_vector (n_idx, 1)); - - for (octave_idx_type i = 0; i < n_idx; i++) - { - ra_idx(i) = idx(i).index_vector (); - if (error_state) - break; - } - - if (! error_state) - { - for (const_iterator p = begin (); p != end (); p++) - { - Cell tmp = contents (p); - - tmp = tmp.Array::index (ra_idx, resize_ok); - - if (error_state) - break; - - retval.assign (key(p), tmp); - } - - // Preserve order of keys. - retval.key_list = key_list; - } - } - else - retval = *this; - - return retval; -} diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/oct-map.h --- a/libinterp/corefcn/oct-map.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/oct-map.h Sun May 25 10:29:05 2014 -0700 @@ -287,8 +287,6 @@ octave_map (const octave_scalar_map& m); - octave_map (const Octave_map& m); - octave_map& operator = (const octave_map& m) { xkeys = m.xkeys; @@ -475,189 +473,4 @@ inline octave_map octave_value_extract (const octave_value& v) { return v.map_value (); } -// The original Octave_map object which is now deprecated. -// It was fully deprecated in version 3.8 and should be removed in 3.12. -// Octave_map and octave_map are convertible to each other. - -class -OCTINTERP_API -Octave_map -{ -public: - - typedef std::map::iterator iterator; - typedef std::map::const_iterator const_iterator; - - typedef std::list::iterator key_list_iterator; - typedef std::list::const_iterator const_key_list_iterator; - - // Warning! You should always use at least two dimensions. - - Octave_map (const dim_vector& dv = dim_vector (0, 0), - const Cell& key_vals = Cell ()); - - Octave_map (const std::string& k, const octave_value& value) - : map (), key_list (), dimensions (1, 1) - { - map[k] = value; - key_list.push_back (k); - } - - Octave_map (const string_vector& sv, - const dim_vector& dv = dim_vector (0, 0)) - : map (), key_list (), dimensions (dv) - { - for (octave_idx_type i = 0; i < sv.length (); i++) - { - std::string k = sv[i]; - map[k] = Cell (dv); - key_list.push_back (k); - } - } - - Octave_map (const std::string& k, const Cell& vals) - : map (), key_list (), dimensions (vals.dims ()) - { - map[k] = vals; - key_list.push_back (k); - } - - Octave_map (const std::string& k, const octave_value_list& val_list) - : map (), key_list (), dimensions (1, val_list.length ()) - { - map[k] = val_list; - key_list.push_back (k); - } - - Octave_map (const Octave_map& m) - : map (m.map), key_list (m.key_list), dimensions (m.dimensions) { } - - Octave_map (const octave_map& m); - - Octave_map& operator = (const Octave_map& m) - { - if (this != &m) - { - map = m.map; - key_list = m.key_list; - dimensions = m.dimensions; - } - - return *this; - } - - ~Octave_map (void) { } - - Octave_map squeeze (void) const; - - Octave_map permute (const Array& vec, bool inv = false) const; - - // This is the number of keys. - octave_idx_type nfields (void) const { return map.size (); } - - void del (const std::string& k) - { - iterator p = map.find (k); - - if (p != map.end ()) - { - map.erase (p); - - key_list_iterator q - = std::find (key_list.begin (), key_list.end (), k); - - assert (q != key_list.end ()); - - key_list.erase (q); - } - } - - iterator begin (void) { return iterator (map.begin ()); } - const_iterator begin (void) const { return const_iterator (map.begin ()); } - - iterator end (void) { return iterator (map.end ()); } - const_iterator end (void) const { return const_iterator (map.end ()); } - - std::string key (const_iterator p) const { return p->first; } - - Cell& contents (const std::string& k); - Cell contents (const std::string& k) const; - - Cell& contents (iterator p) - { return p->second; } - - Cell contents (const_iterator p) const - { return p->second; } - - int intfield (const std::string& k, int def_val = 0) const; - - std::string stringfield (const std::string& k, - const std::string& def_val = std::string ()) const; - - iterator seek (const std::string& k) { return map.find (k); } - const_iterator seek (const std::string& k) const { return map.find (k); } - - bool contains (const std::string& k) const - { return (seek (k) != map.end ()); } - - void clear (void) - { - map.clear (); - key_list.clear (); - } - - string_vector keys (void) const; - - octave_idx_type rows (void) const { return dimensions(0); } - - octave_idx_type columns (void) const { return dimensions(1); } - - dim_vector dims (void) const { return dimensions; } - - int ndims (void) const { return dimensions.length (); } - - Octave_map transpose (void) const; - - Octave_map reshape (const dim_vector& new_dims) const; - - void resize (const dim_vector& dv, bool fill = false); - - octave_idx_type numel (void) const { return dimensions.numel (); } - - Octave_map concat (const Octave_map& rb, - const Array& ra_idx); - - Octave_map& maybe_delete_elements (const octave_value_list& idx); - - Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs); - - Octave_map& assign (const octave_value_list& idx, const std::string& k, - const Cell& rhs); - - Octave_map& assign (const std::string& k, const octave_value& rhs); - - Octave_map& assign (const std::string& k, const Cell& rhs); - - Octave_map index (const octave_value_list& idx, - bool resize_ok = false) const; - -private: - - // The map of names to values. - std::map map; - - // An extra list of keys, so we can keep track of the order the keys - // are added for compatibility with you know what. - std::list key_list; - - // The current size. - mutable dim_vector dimensions; - - void maybe_add_to_key_list (const std::string& k) - { - if (! contains (k)) - key_list.push_back (k); - } -} GCC_ATTR_DEPRECATED; - #endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/oct-obj.cc --- a/libinterp/corefcn/oct-obj.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/oct-obj.cc Sun May 25 10:29:05 2014 -0700 @@ -35,7 +35,8 @@ octave_value_list::octave_value_list (const std::list& lst) { - octave_idx_type n = 0, nel = 0; + octave_idx_type n = 0; + octave_idx_type nel = 0; // Determine number. for (std::list::const_iterator p = lst.begin (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/oct-obj.h --- a/libinterp/corefcn/oct-obj.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/oct-obj.h Sun May 25 10:29:05 2014 -0700 @@ -107,10 +107,16 @@ octave_value_list slice (octave_idx_type offset, octave_idx_type len, bool tags = false) const { - octave_value_list retval (data.linear_slice (offset, offset + len)); + // linear_slice uses begin/end indices instead of offset and + // length. Avoid calling with upper bound out of range. + // linear_slice handles the case of len < 0. + + octave_value_list retval + = data.linear_slice (offset, std::min (offset + len, length ())); + if (tags && len > 0 && names.length () > 0) - retval.names = names.linear_slice (offset, - std::min (len, names.length ())); + retval.names = names.linear_slice (offset, std::min (offset + len, + names.length ())); return retval; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/oct-stream.cc Sun May 25 10:29:05 2014 -0700 @@ -785,11 +785,14 @@ if (i < n) { + // Accept and record modifier, but don't place it in the format + // item text. All integer conversions are handled as 64-bit + // integers. + switch (s[i]) { case 'h': case 'l': case 'L': - modifier = s[i]; - *buf << s[i++]; + modifier = s[i++]; break; default: @@ -1053,7 +1056,8 @@ { std::istream& is = *isp; - int c = 0, lastc = -1; + int c = 0; + int lastc = -1; cnt = 0; while (is && (c = is.get ()) != EOF) @@ -2159,7 +2163,7 @@ printf_value_cache (const octave_value_list& args, const std::string& who) : values (args), val_idx (0), elt_idx (0), - n_vals (values.length ()), n_elts (0), data (0), + n_vals (values.length ()), n_elts (0), have_data (false), curr_state (ok) { for (octave_idx_type i = 0; i < values.length (); i++) @@ -2177,7 +2181,7 @@ ~printf_value_cache (void) { } // Get the current value as a double and advance the internal pointer. - double double_value (void); + octave_value get_next_value (void); // Get the current value as an int and advance the internal pointer. int int_value (void); @@ -2196,8 +2200,8 @@ int elt_idx; int n_vals; int n_elts; - const double *data; - NDArray curr_val; + bool have_data; + octave_value curr_val; state curr_state; // Must create value cache with values! @@ -2211,29 +2215,27 @@ printf_value_cache& operator = (const printf_value_cache&); }; -double -printf_value_cache::double_value (void) +octave_value +printf_value_cache::get_next_value (void) { - double retval = 0.0; + octave_value retval; if (exhausted ()) curr_state = conversion_error; while (! exhausted ()) { - if (! data) + if (! have_data) { - octave_value tmp_val = values (val_idx); + curr_val = values (val_idx); // Force string conversion here for compatibility. - curr_val = tmp_val.array_value (true); - if (! error_state) { elt_idx = 0; - n_elts = curr_val.length (); - data = curr_val.data (); + n_elts = curr_val.numel (); + have_data = true; } else { @@ -2244,13 +2246,13 @@ if (elt_idx < n_elts) { - retval = data[elt_idx++]; + retval = curr_val.fast_elem_extract (elt_idx++); if (elt_idx >= n_elts) { elt_idx = 0; val_idx++; - data = 0; + have_data = false; } break; @@ -2258,7 +2260,7 @@ else { val_idx++; - data = 0; + have_data = false; if (n_elts == 0 && exhausted ()) curr_state = conversion_error; @@ -2275,14 +2277,19 @@ { int retval = 0; - double dval = double_value (); + octave_value val = get_next_value (); if (! error_state) { - if (D_NINT (dval) == dval) - retval = NINT (dval); - else - curr_state = conversion_error; + double dval = val.double_value (); + + if (! error_state) + { + if (D_NINT (dval) == dval) + retval = NINT (dval); + else + curr_state = conversion_error; + } } return retval; @@ -2357,27 +2364,202 @@ return retval; } -#define DO_DOUBLE_CONV(TQUAL) \ - do \ - { \ - if (val > std::numeric_limits::max () \ - || val < std::numeric_limits::min ()) \ - { \ - std::string tfmt = fmt; \ - \ - tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \ - \ - if (elt->modifier == 'l') \ - tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \ - \ - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \ - val, who); \ - } \ - else \ - retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \ - static_cast (val), who); \ - } \ - while (0) +static bool +is_nan_or_inf (const octave_value& val) +{ + octave_value ov_isnan = val.isnan (); + octave_value ov_isinf = val.isinf (); + + return (ov_isnan.is_true () || ov_isinf.is_true ()); +} + +static bool +ok_for_signed_int_conv (const octave_value& val) +{ + uint64_t limit = std::numeric_limits::max (); + + if (val.is_integer_type ()) + { + if (val.is_uint64_type ()) + { + octave_uint64 ival = val.uint64_scalar_value (); + + if (ival.value () <= limit) + return true; + } + else + return true; + } + else + { + double dval = val.double_value (); + + if (dval == xround (dval) && dval <= limit) + return true; + } + + return false; +} + +static bool +ok_for_unsigned_int_conv (const octave_value& val) +{ + if (val.is_integer_type ()) + { + // Easier than dispatching here... + + octave_value ov_is_ge_zero + = do_binary_op (octave_value::op_ge, val, octave_value (0.0)); + + return ov_is_ge_zero.is_true (); + } + else + { + double dval = val.double_value (); + + uint64_t limit = std::numeric_limits::max (); + + if (dval == xround (dval) && dval >= 0 && dval <= limit) + return true; + } + + return false; +} + +static std::string +switch_to_g_format (const printf_format_elt *elt) +{ + std::string tfmt = elt->text; + + tfmt.replace (tfmt.rfind (elt->type), 1, "g"); + + return tfmt; +} + +int +octave_base_stream::do_numeric_printf_conv (std::ostream& os, + const printf_format_elt *elt, + int nsa, int sa_1, int sa_2, + const octave_value& val, + const std::string& who) +{ + int retval = 0; + + const char *fmt = elt->text; + + if (is_nan_or_inf (val)) + { + double dval = val.double_value (); + + std::string tfmt = fmt; + std::string::size_type i1, i2; + + tfmt.replace ((i1 = tfmt.rfind (elt->type)), + 1, 1, 's'); + + if ((i2 = tfmt.rfind ('.')) != std::string::npos + && i2 < i1) + { + tfmt.erase (i2, i1-i2); + if (elt->prec < 0) + nsa--; + } + + const char *tval; + if (lo_ieee_isinf (dval)) + { + if (elt->flags.find ('+') != std::string::npos) + tval = (dval < 0 ? "-Inf" : "+Inf"); + else + tval = (dval < 0 ? "-Inf" : "Inf"); + } + else + { + if (elt->flags.find ('+') != std::string::npos) + tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN"); + else + tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN"); + } + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, who); + } + else + { + static std::string llmod + = sizeof (long) == sizeof (int64_t) ? "l" : "ll"; + + char type = elt->type; + + switch (type) + { + case 'd': case 'i': case 'c': + if (ok_for_signed_int_conv (val)) + { + octave_int64 tval = val.int64_scalar_value (); + + // Insert "long" modifier. + std::string tfmt = fmt; + tfmt.replace (tfmt.rfind (type), 1, llmod + type); + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, + tval.value (), who); + } + else + { + std::string tfmt = switch_to_g_format (elt); + + double dval = val.double_value (); + + if (! error_state) + retval += do_printf_conv (os, tfmt.c_str (), nsa, + sa_1, sa_2, dval, who); + } + break; + + case 'o': case 'x': case 'X': case 'u': + if (ok_for_unsigned_int_conv (val)) + { + octave_uint64 tval = val.uint64_scalar_value (); + + // Insert "long" modifier. + std::string tfmt = fmt; + tfmt.replace (tfmt.rfind (type), 1, llmod + type); + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, + tval.value (), who); + } + else + { + std::string tfmt = switch_to_g_format (elt); + + double dval = val.double_value (); + + if (! error_state) + retval += do_printf_conv (os, tfmt.c_str (), nsa, + sa_1, sa_2, dval, who); + } + break; + + case 'f': case 'e': case 'E': + case 'g': case 'G': + { + double dval = val.double_value (); + + if (! error_state) + retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, dval, who); + } + break; + + default: + error ("%s: invalid format specifier", + who.c_str ()); + return -1; + break; + } + } + + return retval; +} int octave_base_stream::do_printf (printf_format_list& fmt_list, @@ -2432,8 +2614,6 @@ } } - const char *fmt = elt->text; - if (elt->type == '%') { os << "%"; @@ -2449,77 +2629,18 @@ std::string val = val_cache.string_value (); if (val_cache) - retval += do_printf_conv (os, fmt, nsa, sa_1, + retval += do_printf_conv (os, elt->text, nsa, sa_1, sa_2, val.c_str (), who); else break; } else { - double val = val_cache.double_value (); + octave_value val = val_cache.get_next_value (); if (val_cache) - { - if (lo_ieee_isnan (val) || xisinf (val)) - { - std::string tfmt = fmt; - std::string::size_type i1, i2; - - tfmt.replace ((i1 = tfmt.rfind (elt->type)), - 1, 1, 's'); - - if ((i2 = tfmt.rfind ('.')) != std::string::npos - && i2 < i1) - { - tfmt.erase (i2, i1-i2); - if (elt->prec < 0) - nsa--; - } - - const char *tval; - if (xisinf (val)) - if (elt->flags.find ('+') != std::string::npos) - tval = (val < 0 ? "-Inf" : "+Inf"); - else - tval = (val < 0 ? "-Inf" : "Inf"); - else - if (elt->flags.find ('+') != std::string::npos) - tval = (lo_ieee_is_NA (val) ? "+NA" : "+NaN"); - else - tval = (lo_ieee_is_NA (val) ? "NA" : "NaN"); - - retval += do_printf_conv (os, tfmt.c_str (), - nsa, sa_1, sa_2, - tval, who); - } - else - { - char type = elt->type; - - switch (type) - { - case 'd': case 'i': case 'c': - DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG); - break; - - case 'o': case 'x': case 'X': case 'u': - DO_DOUBLE_CONV (unsigned); - break; - - case 'f': case 'e': case 'E': - case 'g': case 'G': - retval += do_printf_conv (os, fmt, nsa, - sa_1, sa_2, val, who); - break; - - default: - error ("%s: invalid format specifier", - who.c_str ()); - return -1; - break; - } - } - } + retval += do_numeric_printf_conv (os, elt, nsa, sa_1, + sa_2, val, who); else break; } @@ -3191,8 +3312,7 @@ if (! error_state) { - octave_idx_type elts_to_read - = std::numeric_limits::max (); + octave_idx_type elts_to_read; if (one_elt_size_spec) { @@ -3221,7 +3341,9 @@ nr = nc = 0; } - // FIXME: ensure that this does not overflow. + // FIXME: Ensure that this does not overflow. + // Maybe try comparing nr * nc computed in double with + // std::numeric_limits::max (); elts_to_read = nr * nc; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/oct-stream.h --- a/libinterp/corefcn/oct-stream.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/oct-stream.h Sun May 25 10:29:05 2014 -0700 @@ -479,6 +479,11 @@ int flush (void); + int do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt, + int nsa, int sa_1, int sa_2, + const octave_value& val, + const std::string& who); + int do_printf (printf_format_list& fmt_list, const octave_value_list& args, const std::string& who /* = "printf" */); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/octave-default-image.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/octave-default-image.h Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,281 @@ +/* + +Copyright (C) 2014 Pantxo Diribarne + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +static char default_im_data[] = { + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,20,20,20,20,20,20,21,21,21,21, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,20,20,20,20,20,20,20,20,20,20,20,21,21, + 21,21,21,21,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21, + 21,21,21,21,21,21,21,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 21,21,21,21,21,21,21,21,21,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,21,21,21,21,21,21,21,21,21,21,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 20,20,21,21,21,21,21,21,21,21,21,21,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,31,31,31,31, + 31,31,31,31,31,31,21,21,21,21,21,21,21,21,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,21,21,21,21,21,21,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,20, + 20,20,20,20,20,20,20,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,21,21,21,21,21, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,20,20,20,20,20,20,20, + 20,20,20,20,20,20,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,21, + 21,21,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,20, + 20,20,20,20,20,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,63, + 49,49,49,49,49,49,49,49,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,20, + 20,20,20,20,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 48,48,48,48,48,48,48,49,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,20,20,20,20,20,20,20,20,20, + 20,20,20,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,19,20,20,20,20,20,20,20,20, + 20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,20,19,20,20,20,20,20,20,20, + 20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,19,19,19,19,20,20,20,20,20,20, + 20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,19,19,19,19,19,20,20,20,20,20, + 20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,19,19,19,19,19,19,19,20,20,20, + 19,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 48,47,47,47,47,47,48,48,63,31,31,31,31,31,31,31, + 31,31,31,31,31,31,19,19,19,19,19,19,20,19,20,20, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49, + 49,48,48,48,48,48,48,48,21,31,31,31,31,31,31,31, + 31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,20, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,21,21,21,31,31,31,31,31,31, + 31,31,31,31,31,20,20,20,20,20,20,20,20,20,20,20, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,21,21,31,31,31,31,31,31, + 31,31,49,49,49,49,49,49,49,49,49,49,49,49,49,49, + 49,49,49,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,21,21,31,31,31,31,31, + 31,49,48,48,48,48,48,48,48,48,48,48,48,48,48,48, + 48,48,48,49,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,21,21,21,31,31,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,21,21,21,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,21,21,21,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,20,21,31, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,21, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,20,21,21, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,21, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20, + 49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20, + 31,49,48,47,47,47,47,47,47,47,47,47,47,47,47,47, + 47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20, + 31,49,49,48,48,48,48,48,48,48,48,48,48,48,48,48, + 48,48,49,63,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20, + 31,31,31,49,49,49,49,49,49,47,63,63,63,63,63,63, + 63,63,20,19,19,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20, + 31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,19, + 19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20, + 31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,19, + 19,19,19,19,19,19,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20, + 31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,19, + 19,19,19,19,19,19,19,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20, + 31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,19, + 19,19,19,19,19,19,19,19,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20, + 31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,19, + 19,19,19,19,19,19,19,19,19,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,49,49,49,49,49,47,63,63,63,21,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,19, + 19,19,19,19,19,19,19,19,19,19,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,49,49,48,48,48,48,48,48,48,48,48,48,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,19, + 19,19,19,19,19,19,19,19,19,19,19,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,49,48,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,19, + 19,19,19,19,19,19,19,19,19,19,19,19,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,48, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 19,19,19,19,19,19,19,19,19,19,19,19,19,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31, + 31,19,20,49,47,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,20,20,49,47,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,18,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,20,49,47,47,47,47,47,47,47,47,47,47,48,48, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,20,20,49,48,47,47,47,47,47,47,47,47,47,48,49, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,19,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,20,63,48,48,48,48,48,48,48,48,48,48,49,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,20,21,63,63,63,48,49,49,49,49,49,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,20,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, + 19,19,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31, + 31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,31, + 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 +}; + diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/octave-link.cc --- a/libinterp/corefcn/octave-link.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/octave-link.cc Sun May 25 10:29:05 2014 -0700 @@ -225,7 +225,7 @@ std::string multi_on = args(4).string_value (); // on, off, create std::string pathname = args(5).string_value (); - octave_idx_type nel = flist.numel (); + octave_idx_type nel; octave_link::filter_list filter_lst; for (octave_idx_type i = 0; i < flist.rows (); i++) @@ -432,7 +432,7 @@ DEFUN (__octave_link_show_doc__, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} __octave_link_show_doc__ ( @var{filename} )\n\ +@deftypefn {Built-in Function} {} __octave_link_show_doc__ (@var{filename})\n\ Undocumented internal function.\n\ @end deftypefn") { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/pager.cc --- a/libinterp/corefcn/pager.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/pager.cc Sun May 25 10:29:05 2014 -0700 @@ -52,7 +52,7 @@ static bool write_to_diary_file = false; // The name of the current diary file. -static std::string diary_file; +static std::string diary_file ("diary"); // The diary file. static std::ofstream external_diary_file; @@ -589,6 +589,24 @@ return retval; } +DEFUN (__diaryfile__, , , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{fname} =} __diaryfile__ ()\n\ +Undocumented internal function\n\ +@end deftypefn") +{ + return ovl (diary_file); +} + +DEFUN (__diarystate__, , , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{state} =} __diarystate__ ()\n\ +Undocumented internal function\n\ +@end deftypefn") +{ + return ovl (write_to_diary_file); +} + DEFUN (more, args, , "-*- texinfo -*-\n\ @deftypefn {Command} {} more\n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/pinv.cc --- a/libinterp/corefcn/pinv.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/pinv.cc Sun May 25 10:29:05 2014 -0700 @@ -76,22 +76,45 @@ if (arg.is_diag_matrix ()) { - if (nargin == 2) - warning ("pinv: tol is ignored for diagonal matrices"); - - if (arg.is_complex_type ()) + if (isfloat) { - if (isfloat) - retval = arg.float_complex_diag_matrix_value ().pseudo_inverse (); + float tol = 0.0; + if (nargin == 2) + tol = args(1).float_value (); + + if (error_state) + return retval; + + if (tol < 0.0) + { + error ("pinv: TOL must be greater than zero"); + return retval; + } + + if (arg.is_real_type ()) + retval = arg.float_diag_matrix_value ().pseudo_inverse (tol); else - retval = arg.complex_diag_matrix_value ().pseudo_inverse (); + retval = arg.float_complex_diag_matrix_value ().pseudo_inverse (tol); } else { - if (isfloat) - retval = arg.float_diag_matrix_value ().pseudo_inverse (); + double tol = 0.0; + if (nargin == 2) + tol = args(1).double_value (); + + if (error_state) + return retval; + + if (tol < 0.0) + { + error ("pinv: TOL must be greater than zero"); + return retval; + } + + if (arg.is_real_type ()) + retval = arg.diag_matrix_value ().pseudo_inverse (tol); else - retval = arg.diag_matrix_value ().pseudo_inverse (); + retval = arg.complex_diag_matrix_value ().pseudo_inverse (tol); } } else if (arg.is_perm_matrix ()) @@ -189,4 +212,20 @@ %!assert (y*x*y, y, -hitol) %!assert ((x*y)', x*y, hitol) %!assert ((y*x)', y*x, hitol) + +## Clear shared variables +%!shared + +## Test pinv for Diagonal matrices +%!test +%! x = diag ([3 2 1 0 -0.5]); +%! y = pinv (x); +%! assert (typeinfo (y)(1:8), "diagonal"); +%! assert (isa (y, "double")); +%! assert (diag (y), [1/3, 1/2, 1, 0 1/-0.5]'); +%! y = pinv (x, 1); +%! assert (diag (y), [1/3 1/2 1 0 0]'); +%! y = pinv (x, 2); +%! assert (diag (y), [1/3 1/2 0 0 0]'); + */ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/pr-output.cc --- a/libinterp/corefcn/pr-output.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/pr-output.cc Sun May 25 10:29:05 2014 -0700 @@ -581,13 +581,11 @@ { ld = digits; rd = prec > digits ? prec - digits : prec; - digits++; } else { ld = 1; rd = prec > digits ? prec - digits : prec; - digits = -digits + 1; } fw = 1 + ld + 1 + rd; @@ -3387,8 +3385,7 @@ } void -octave_print_internal (std::ostream&, const octave_value&, - bool pr_as_read_syntax) +octave_print_internal (std::ostream&, const octave_value&, bool) { panic_impossible (); } @@ -3439,7 +3436,7 @@ rat_format = true; std::ostringstream buf; - args(0).print (buf); + arg.print (buf); std::string s = buf.str (); std::list lst; @@ -3501,11 +3498,12 @@ if (nargin == 1 && nargout < 2) { + octave_value arg = args(0); + if (nargout == 0) - args(0).print (octave_stdout); + arg.print (octave_stdout); else { - octave_value arg = args(0); std::ostringstream buf; arg.print (buf); retval = octave_value (buf.str (), arg.is_dq_string () ? '"' : '\''); @@ -3542,7 +3540,7 @@ if (nargin == 2) { - int fid = octave_stream_list::get_file_number (args (0)); + int fid = octave_stream_list::get_file_number (args(0)); octave_stream os = octave_stream_list::lookup (fid, "fdisp"); @@ -3550,8 +3548,10 @@ { std::ostream *osp = os.output_stream (); + octave_value arg = args(1); + if (osp) - args(1).print (*osp); + arg.print (*osp); else error ("fdisp: stream FID not open for writing"); } @@ -3612,20 +3612,25 @@ Voutput_max_field_width = fw; } +static std::string format_string ("short"); + static void set_format_style (int argc, const string_vector& argv) { int idx = 1; + std::string format; if (--argc > 0) { std::string arg = argv[idx++]; + format = arg; if (arg == "short") { if (--argc > 0) { arg = argv[idx++]; + format.append (arg); if (arg == "e") { @@ -3666,11 +3671,44 @@ set_output_prec_and_fw (5, 10); } + else if (arg == "shorte") + { + init_format_state (); + print_e = true; + set_output_prec_and_fw (5, 10); + } + else if (arg == "shortE") + { + init_format_state (); + print_e = true; + print_big_e = true; + set_output_prec_and_fw (5, 10); + } + else if (arg == "shortg") + { + init_format_state (); + print_g = true; + set_output_prec_and_fw (5, 10); + } + else if (arg == "shortG") + { + init_format_state (); + print_g = true; + print_big_e = true; + set_output_prec_and_fw (5, 10); + } + else if (arg == "shortEng") + { + init_format_state (); + print_eng = true; + set_output_prec_and_fw (5, 10); + } else if (arg == "long") { if (--argc > 0) { arg = argv[idx++]; + format.append (arg); if (arg == "e") { @@ -3711,6 +3749,38 @@ set_output_prec_and_fw (15, 20); } + else if (arg == "longe") + { + init_format_state (); + print_e = true; + set_output_prec_and_fw (15, 20); + } + else if (arg == "longE") + { + init_format_state (); + print_e = true; + print_big_e = true; + set_output_prec_and_fw (15, 20); + } + else if (arg == "longg") + { + init_format_state (); + print_g = true; + set_output_prec_and_fw (15, 20); + } + else if (arg == "longG") + { + init_format_state (); + print_g = true; + print_big_e = true; + set_output_prec_and_fw (15, 20); + } + else if (arg == "longEng") + { + init_format_state (); + print_eng = true; + set_output_prec_and_fw (15, 20); + } else if (arg == "hex") { init_format_state (); @@ -3736,6 +3806,7 @@ if (--argc > 0) { arg = argv[idx++]; + format.append (arg); if (arg.length () == 3) plus_format_chars = arg; @@ -3774,21 +3845,30 @@ else if (arg == "compact") { Vcompact_format = true; + return; } else if (arg == "loose") { Vcompact_format = false; + return; } else - error ("format: unrecognized format state '%s'", arg.c_str ()); + { + error ("format: unrecognized format state '%s'", arg.c_str ()); + return; + } } else { init_format_state (); set_output_prec_and_fw (5, 10); + format = std::string ("short"); } + + format_string = format; } + DEFUN (format, args, , "-*- texinfo -*-\n\ @deftypefn {Command} {} format\n\ @@ -3973,6 +4053,25 @@ return retval; } +DEFUN (__compactformat__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{val} =} __compactformat__ ()\n\ +@deftypefnx {Built-in Function} {} __compactformat__ (@var{TRUE|FALSE})\n\ +Undocumented internal function\n\ +@end deftypefn") +{ + return SET_INTERNAL_VARIABLE (compact_format); +} + +DEFUN (__formatstring__, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{val} =} __formatstring__ ()\n\ +Undocumented internal function\n\ +@end deftypefn") +{ + return ovl (format_string); +} + DEFUN (fixed_point_format, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} fixed_point_format ()\n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/pt-jit.cc --- a/libinterp/corefcn/pt-jit.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/pt-jit.cc Sun May 25 10:29:05 2014 -0700 @@ -46,6 +46,8 @@ static int Vjit_startcnt = 1000; +static int Vjit_failure_count = 0; + #include #include #include @@ -164,7 +166,7 @@ if (expr) { jit_variable *retvar = get_variable ("#return"); - jit_value *retval; + jit_value *retval = 0; try { retval = visit (expr); @@ -230,13 +232,13 @@ void jit_convert::visit_anon_fcn_handle (tree_anon_fcn_handle&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_anon_fcn_handle implementation"); } void jit_convert::visit_argument_list (tree_argument_list&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_argument_list implementation"); } void @@ -337,25 +339,25 @@ void jit_convert::visit_global_command (tree_global_command&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_global_command implemenation"); } void jit_convert::visit_persistent_command (tree_persistent_command&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_persistent_command implementation"); } void jit_convert::visit_decl_elt (tree_decl_elt&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_decl_elt implementation"); } void jit_convert::visit_decl_init_list (tree_decl_init_list&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_decl_init_list implementation"); } void @@ -464,37 +466,37 @@ void jit_convert::visit_complex_for_command (tree_complex_for_command&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_complex_for_command implementation"); } void jit_convert::visit_octave_user_script (octave_user_script&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_octave_user_script implementation"); } void jit_convert::visit_octave_user_function (octave_user_function&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_octave_user_function implementation"); } void jit_convert::visit_octave_user_function_header (octave_user_function&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_octave_user_function_header implementation"); } void jit_convert::visit_octave_user_function_trailer (octave_user_function&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_octave_user_function_trailer implementation"); } void jit_convert::visit_function_def (tree_function_def&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_function_def implementation"); } void @@ -518,7 +520,7 @@ void jit_convert::visit_if_clause (tree_if_clause&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_if_clause implementation"); } void @@ -539,7 +541,6 @@ // the condition check for the ith clause. For the else, it is simple the // else body. If there is no else body, then it is padded with the tail std::vector entry_blocks (lst.size () + 1 - last_else); - std::vector branch_blocks (lst.size (), 0); // final blocks entry_blocks[0] = block; // we need to construct blocks first, because they have jumps to eachother @@ -630,25 +631,25 @@ void jit_convert::visit_matrix (tree_matrix&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_matrix implementation"); } void jit_convert::visit_cell (tree_cell&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_cell implementation"); } void jit_convert::visit_multi_assignment (tree_multi_assignment&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_multi_assignment implementation"); } void jit_convert::visit_no_op_command (tree_no_op_command&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_no_op_command implementation"); } void @@ -679,13 +680,19 @@ void jit_convert::visit_fcn_handle (tree_fcn_handle&) { + throw jit_fail_exception ("No visit_fcn_handle implementation"); +} + +void +jit_convert::visit_funcall (tree_funcall&) +{ throw jit_fail_exception (); } void jit_convert::visit_parameter_list (tree_parameter_list&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_parameter_list implementation"); } void @@ -721,13 +728,13 @@ void jit_convert::visit_return_command (tree_return_command&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_return_command implementation"); } void jit_convert::visit_return_list (tree_return_list&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_return_list implementation"); } void @@ -805,31 +812,132 @@ void jit_convert::visit_switch_case (tree_switch_case&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_switch_case implementation"); } void jit_convert::visit_switch_case_list (tree_switch_case_list&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_switch_case_list implementation"); } void -jit_convert::visit_switch_command (tree_switch_command&) +jit_convert::visit_switch_command (tree_switch_command& cmd) { - throw jit_fail_exception (); + tree_switch_case_list *lst = cmd.case_list (); + + // always visit switch expression + tree_expression *expr = cmd.switch_value (); + assert (expr && "Switch value can not be null"); + jit_value *value = visit (expr); + assert (value); + + size_t case_blocks_num = lst->size (); + + if (! case_blocks_num) // there's nothing to do + return; + + // check for otherwise, it's interpreted as last 'else' condition + size_t has_otherwise = 0; + tree_switch_case *last = lst->back (); + if (last->is_default_case ()) + has_otherwise = 1; + + std::vector entry_blocks (case_blocks_num + 1 - has_otherwise); + + // the first entry point is always the actual block. afterward new blocks + // are created for every case and the otherwise branch + entry_blocks[0] = block; + for (size_t i = 1; i < case_blocks_num; ++i) + entry_blocks[i] = factory.create ("case_cond"); + + jit_block *tail = factory.create ("switch_tail"); + + // if there's no otherwise branch, the the 'else' of the last branch + // has to point to the tail + if (! has_otherwise) + entry_blocks[entry_blocks.size()-1] = tail; + + // each branch in the case statement will have different breaks/continues + block_list current_breaks = breaks; + block_list current_continues = continues; + breaks.clear (); + continues.clear (); + + size_t num_incomming = 0; // number of incomming blocks to our tail + + tree_switch_case_list::iterator iter = lst->begin (); + for (size_t i = 0; i < case_blocks_num; ++iter, ++i) + { + tree_switch_case *twc = *iter; + block = entry_blocks[i]; // case_cond + assert (block); + + if (i) + blocks.push_back (entry_blocks[i]); // first block already pushed + + if (! twc->is_default_case ()) + { + // compare result of switch expression with actual case label + tree_expression *te = twc->case_label (); + jit_value *label = visit (te); + assert(label); + + const jit_operation& fn = jit_typeinfo::binary_op (octave_value::op_eq); + jit_value *cond = create_checked (fn, value, label); + assert(cond); + + jit_call *check = create_checked (&jit_typeinfo::logically_true, + cond); + + jit_block *body = factory.create ("case_body"); + blocks.push_back (body); + + block->append (factory.create (check, body, + entry_blocks[i+1])); + block = body; // case_body + } + + tree_statement_list *stmt_lst = twc->commands (); + assert(stmt_lst); + + try + { + stmt_lst->accept (*this); + num_incomming++; + block->append (factory.create (tail)); + } + catch (const jit_break_exception&) + { } + + // each branch in the case statement will have different breaks/continues + current_breaks.splice (current_breaks.end (), breaks); + current_continues.splice (current_continues.end (), continues); + } + + // each branch in the case statement will have different breaks/continues + breaks.splice (breaks.end (), current_breaks); + continues.splice (continues.end (), current_continues); + + if (num_incomming || ! has_otherwise) + { + blocks.push_back (tail); + block = tail; // switch_tail + } + else + throw jit_break_exception (); // every branch broke } void jit_convert::visit_try_catch_command (tree_try_catch_command&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_try_catch_command implementation"); } void jit_convert::visit_unwind_protect_command (tree_unwind_protect_command&) { - throw jit_fail_exception (); + throw jit_fail_exception ("No visit_unwind_protect_command implementation"); } void @@ -895,9 +1003,66 @@ } void -jit_convert::visit_do_until_command (tree_do_until_command&) +jit_convert::visit_do_until_command (tree_do_until_command& duc) { - throw jit_fail_exception (); + unwind_protect prot; + prot.protect_var (breaks); + prot.protect_var (continues); + breaks.clear (); + continues.clear (); + + jit_block *body = factory.create ("do_until_body"); + jit_block *cond_check = factory.create ("do_until_cond_check"); + jit_block *tail = factory.create ("do_until_tail"); + + block->append (factory.create (body)); + blocks.push_back (body); + block = body; + + tree_statement_list *loop_body = duc.body (); + bool all_breaking = false; + if (loop_body) + { + try + { + loop_body->accept (*this); + } + catch (const jit_break_exception&) + { + all_breaking = true; + } + } + + finish_breaks (tail, breaks); + + if (! all_breaking || continues.size ()) + { + jit_block *interrupt_check + = factory.create ("interrupt_check"); + blocks.push_back (interrupt_check); + finish_breaks (interrupt_check, continues); + if (! all_breaking) + block->append (factory.create (interrupt_check)); + + block = interrupt_check; + jit_error_check *ec + = factory.create (jit_error_check::var_interrupt, + cond_check, final_block); + block->append (ec); + + blocks.push_back (cond_check); + block = cond_check; + + tree_expression *expr = duc.condition (); + assert (expr && "Do-Until expression can not be null"); + jit_value *check = visit (expr); + check = create_checked (&jit_typeinfo::logically_true, check); + + block->append (factory.create (check, tail, body)); + } + + blocks.push_back (tail); + block = tail; } void @@ -2123,6 +2288,8 @@ std::cout << "jit fail: " << e.what () << std::endl; } + Vjit_failure_count++; + wrapper.erase (); raw_fn.erase (); } @@ -2279,6 +2446,9 @@ if (e.known ()) std::cout << "jit fail: " << e.what () << std::endl; } + + Vjit_failure_count++; + } if (llvm_function) @@ -2314,6 +2484,29 @@ #endif + +DEFUN (jit_failure_count, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{val} =} jit_failure_count ()\n\ +@deftypefnx {Built-in Function} {@var{old_val} =} jit_failure_count (@var{new_val})\n\ +@deftypefnx {Built-in Function} {} jit_failure_count (@var{new_val}, \"local\")\n\ +Query or set the internal variable that counts the number of\n\ +JIT fail exceptions for Octave's JIT compiler.\n\ +\n\ +When called from inside a function with the @qcode{\"local\"} option, the\n\ +variable is changed locally for the function and any subroutines it calls. \n\ +The original variable value is restored when exiting the function.\n\ +@seealso{jit_enable, jit_startcnt, debug_jit}\n\ +@end deftypefn") +{ +#if defined (HAVE_LLVM) + return SET_INTERNAL_VARIABLE (jit_failure_count); +#else + warning ("jit_failure_count: JIT compiling not available in this version of Octave"); + return octave_value (); +#endif +} + DEFUN (debug_jit, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} debug_jit ()\n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/pt-jit.h --- a/libinterp/corefcn/pt-jit.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/pt-jit.h Sun May 25 10:29:05 2014 -0700 @@ -129,6 +129,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/qz.cc --- a/libinterp/corefcn/qz.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/qz.cc Sun May 25 10:29:05 2014 -0700 @@ -928,7 +928,7 @@ std::cout << " single gen eig:" << std::endl; std::cout << " alphar(" << jj << ") = " << aa(jj,jj) << std::endl; - std::cout << " betar( " << jj << ") = " << bb(jj,jj) + std::cout << " betar(" << jj << ") = " << bb(jj,jj) << std::endl; std::cout << " alphai(" << jj << ") = 0" << std::endl; #endif @@ -1277,9 +1277,9 @@ %! [aa, bb, q, z, v, w, lambda] = qz (a, b); %! sz = length (lambda); %! observed = (b * v * diag ([lambda;0])) (:, 1:sz); -%! assert ( (a*v) (:, 1:sz), observed, norm (observed) * 1e-14); +%! assert ((a*v)(:, 1:sz), observed, norm (observed) * 1e-14); %! observed = (diag ([lambda;0]) * w' * b) (1:sz, :); -%! assert ( (w'*a) (1:sz, :) , observed, norm (observed) * 1e-13); +%! assert ((w'*a)(1:sz, :) , observed, norm (observed) * 1e-13); %! assert (q * a * z, aa, norm (aa) * 1e-14); %! assert (q * b * z, bb, norm (bb) * 1e-14); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/rand.cc --- a/libinterp/corefcn/rand.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/rand.cc Sun May 25 10:29:05 2014 -0700 @@ -577,7 +577,7 @@ Reference: G. Marsaglia and W.W. Tsang,\n\ @cite{Ziggurat Method for Generating Random Variables},\n\ J. Statistical Software, vol 5, 2000,\n\ -@url{http://www.jstatsoft.org/v05/i08/})\n\ +@url{http://www.jstatsoft.org/v05/i08/}\n\ \n\ @seealso{rand, rande, randg, randp}\n\ @end deftypefn") @@ -648,7 +648,7 @@ Reference: G. Marsaglia and W.W. Tsang,\n\ @cite{Ziggurat Method for Generating Random Variables},\n\ J. Statistical Software, vol 5, 2000,\n\ -@url{http://www.jstatsoft.org/v05/i08/})\n\ +@url{http://www.jstatsoft.org/v05/i08/}\n\ \n\ @seealso{rand, randn, randg, randp}\n\ @end deftypefn") diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/sparse-xdiv.cc --- a/libinterp/corefcn/sparse-xdiv.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/sparse-xdiv.cc Sun May 25 10:29:05 2014 -0700 @@ -302,7 +302,7 @@ using std::min; const octave_idx_type nc = min (d_nr, a_nc); - if ( ! mx_div_conform (a, d)) + if (! mx_div_conform (a, d)) return RT (); const octave_idx_type nz = a.nnz (); @@ -569,7 +569,7 @@ using std::min; const octave_idx_type nr = min (d_nc, a_nr); - if ( ! mx_leftdiv_conform (d, a)) + if (! mx_leftdiv_conform (d, a)) return RT (); const octave_idx_type nz = a.nnz (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/sparse.cc --- a/libinterp/corefcn/sparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/sparse.cc Sun May 25 10:29:05 2014 -0700 @@ -113,7 +113,7 @@ if (nargin == 1) { - octave_value arg = args (0); + octave_value arg = args(0); if (arg.is_bool_type ()) retval = arg.sparse_bool_matrix_value (); else if (arg.is_complex_type ()) @@ -156,7 +156,8 @@ if (! error_state) { - octave_idx_type m = -1, n = -1, nzmax = -1; + octave_idx_type m, n, nzmax; + m = n = nzmax = -1; if (nargin == 6) { nzmax = args(5).idx_type_value (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/sqrtm.cc --- a/libinterp/corefcn/sqrtm.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/sqrtm.cc Sun May 25 10:29:05 2014 -0700 @@ -101,7 +101,8 @@ typedef typename Matrix::element_type real_type; - real_type cutoff = 0, one = 1; + real_type cutoff = 0; + real_type one = 1; real_type eps = std::numeric_limits::epsilon (); if (! iscomplex) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/str2double.cc --- a/libinterp/corefcn/str2double.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/str2double.cc Sun May 25 10:29:05 2014 -0700 @@ -45,7 +45,7 @@ static double single_num (std::istringstream& is) { - double num; + double num = 0.0; char c = is.peek (); @@ -60,7 +60,8 @@ { // It's infinity. is.get (); - char c1 = is.get (), c2 = is.get (); + char c1 = is.get (); + char c2 = is.get (); if (std::tolower (c1) == 'n' && std::tolower (c2) == 'f') { num = octave_Inf; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/strfind.cc --- a/libinterp/corefcn/strfind.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/strfind.cc Sun May 25 10:29:05 2014 -0700 @@ -209,7 +209,8 @@ if (nargin == 2) { - octave_value argstr = args(0), argpat = args(1); + octave_value argstr = args(0); + octave_value argpat = args(1); if (argpat.is_string ()) { Array needle = argpat.char_array_value (); @@ -279,7 +280,9 @@ { Array ret = str; - octave_idx_type siz = str.numel (), psiz = pat.numel (), rsiz = rep.numel (); + octave_idx_type siz = str.numel (); + octave_idx_type psiz = pat.numel (); + octave_idx_type rsiz = rep.numel (); if (psiz != 0) { @@ -311,21 +314,27 @@ else retsiz = siz + nidx * (rsiz - psiz); - ret.clear (dim_vector (1, retsiz)); - const char *src = str.data (), *reps = rep.data (); - char *dest = ret.fortran_vec (); - - octave_idx_type k = 0; - for (octave_idx_type i = 0; i < nidx; i++) + if (retsiz == 0) + ret.clear (dim_vector (0, 0)); + else { - octave_idx_type j = idx(i); - if (j >= k) - dest = std::copy (src + k, src + j, dest); - dest = std::copy (reps, reps + rsiz, dest); - k = j + psiz; + ret.clear (dim_vector (1, retsiz)); + const char *src = str.data (); + const char *reps = rep.data (); + char *dest = ret.fortran_vec (); + + octave_idx_type k = 0; + for (octave_idx_type i = 0; i < nidx; i++) + { + octave_idx_type j = idx(i); + if (j >= k) + dest = std::copy (src + k, src + j, dest); + dest = std::copy (reps, reps + rsiz, dest); + k = j + psiz; + } + + std::copy (src + k, src + siz, dest); } - - std::copy (src + k, src + siz, dest); } } @@ -380,7 +389,9 @@ if (nargin == 3) { - octave_value argstr = args(0), argpat = args(1), argrep = args(2); + octave_value argstr = args(0); + octave_value argpat = args(1); + octave_value argrep = args(2); if (argpat.is_string () && argrep.is_string ()) { const Array pat = argpat.char_array_value (); @@ -433,6 +444,8 @@ %!assert (strrep ("abababc", "abab", "xyz"), "xyzxyzc") %!assert (strrep ("abababc", "abab", "xyz", "overlaps", false), "xyzabc") +%!assert (size (strrep ("a", "a", "")), [0 0]) + %!error strrep () %!error strrep ("foo", "bar", 3, 4) */ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/strfns.cc --- a/libinterp/corefcn/strfns.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/strfns.cc Sun May 25 10:29:05 2014 -0700 @@ -585,7 +585,7 @@ if (args.length () == 2) { - retval = do_strcmp_fun (args (0), args (1), 0, + retval = do_strcmp_fun (args(0), args(1), 0, "strcmp", strcmp_array_op, strcmp_str_op); } else @@ -647,7 +647,8 @@ strncmp_array_op (const charNDArray& s1, const charNDArray& s2, octave_idx_type n) { - octave_idx_type l1 = s1.numel (), l2 = s2.numel (); + octave_idx_type l1 = s1.numel (); + octave_idx_type l2 = s2.numel (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data ())); } @@ -658,7 +659,8 @@ static bool strncmp_str_op (const std::string& s1, const std::string& s2, octave_idx_type n) { - octave_idx_type l1 = s1.length (), l2 = s2.length (); + octave_idx_type l1 = s1.length (); + octave_idx_type l2 = s2.length (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data ())); } @@ -781,7 +783,7 @@ if (args.length () == 2) { - retval = do_strcmp_fun (args (0), args (1), 0, + retval = do_strcmp_fun (args(0), args(1), 0, "strcmpi", strcmpi_array_op, strcmpi_str_op); } else @@ -799,7 +801,8 @@ strncmpi_array_op (const charNDArray& s1, const charNDArray& s2, octave_idx_type n) { - octave_idx_type l1 = s1.numel (), l2 = s2.numel (); + octave_idx_type l1 = s1.numel (); + octave_idx_type l2 = s2.numel (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data (), icmp_char_eq ())); @@ -810,7 +813,8 @@ strncmpi_str_op (const std::string& s1, const std::string& s2, octave_idx_type n) { - octave_idx_type l1 = s1.length (), l2 = s2.length (); + octave_idx_type l1 = s1.length (); + octave_idx_type l2 = s2.length (); return (n > 0 && n <= l1 && n <= l2 && std::equal (s1.data (), s1.data () + n, s2.data (), icmp_char_eq ())); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/symtab.cc --- a/libinterp/corefcn/symtab.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/symtab.cc Sun May 25 10:29:05 2014 -0700 @@ -38,6 +38,7 @@ #include "dirfns.h" #include "input.h" #include "load-path.h" +#include "ov-classdef.h" #include "ov-fcn.h" #include "ov-usr-fcn.h" #include "pager.h" @@ -149,6 +150,24 @@ return retval; } +static void +split_name_with_package (const std::string& name, std::string& fname, + std::string& pname) +{ + size_t pos = name.rfind ('.'); + + fname.clear (); + pname.clear (); + + if (pos != std::string::npos) + { + fname = name.substr (pos + 1); + pname = name.substr (0, pos); + } + else + fname = name; +} + // Check the load path to see if file that defined this is still // visible. If the file is no longer visible, then erase the // definition and move on. If the file is visible, then we also @@ -165,11 +184,13 @@ static inline bool load_out_of_date_fcn (const std::string& ff, const std::string& dir_name, octave_value& function, - const std::string& dispatch_type = std::string ()) + const std::string& dispatch_type = std::string (), + const std::string& package_name = std::string ()) { bool retval = false; - octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type); + octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type, + package_name); if (fcn) { @@ -206,11 +227,13 @@ bool relative = check_relative && fcn->is_relative (); - if (tc < Vlast_prompt_time + if (tc <= Vlast_prompt_time || (relative && tc < Vlast_chdir_time)) { bool clear_breakpoints = false; std::string nm = fcn->name (); + std::string pack = fcn->package_name (); + std::string canonical_nm = fcn->canonical_name (); bool is_same_file = false; @@ -235,10 +258,13 @@ if (! dispatch_type.empty ()) { file = load_path::find_method (dispatch_type, nm, - dir_name); + dir_name, pack); if (file.empty ()) { + std::string s_name; + std::string s_pack; + const std::list& plist = symbol_table::parent_classes (dispatch_type); std::list::const_iterator it @@ -246,10 +272,17 @@ while (it != plist.end ()) { + split_name_with_package (*it, s_name, + s_pack); + file = load_path::find_method (*it, nm, - dir_name); + dir_name, + s_pack); if (! file.empty ()) - break; + { + pack = s_pack; + break; + } it++; } @@ -261,7 +294,7 @@ file = lookup_autoload (nm); if (file.empty ()) - file = load_path::find_fcn (nm, dir_name); + file = load_path::find_fcn (nm, dir_name, pack); } if (! file.empty ()) @@ -303,7 +336,8 @@ { retval = load_out_of_date_fcn (ff, dir_name, function, - dispatch_type); + dispatch_type, + pack); clear_breakpoints = true; } @@ -322,7 +356,7 @@ // place of the old. retval = load_out_of_date_fcn (file, dir_name, function, - dispatch_type); + dispatch_type, pack); clear_breakpoints = true; } @@ -330,7 +364,8 @@ // If the function has been replaced then clear any // breakpoints associated with it if (clear_breakpoints) - bp_table::remove_all_breakpoints_in_file (nm, true); + bp_table::remove_all_breakpoints_in_file (canonical_nm, + true); } } } @@ -383,11 +418,13 @@ std::string dir_name; - std::string file_name = load_path::find_method (name, name, dir_name); + std::string file_name = load_path::find_method (name, name, dir_name, + package_name); if (! file_name.empty ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name, name); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, name, + package_name); if (fcn) { @@ -396,6 +433,31 @@ class_constructors[name] = retval; } } + else + { + // Classdef constructors can be defined anywhere in the path, not + // necessarily in @-folders. Look for a normal function and load it. + // If the loaded function is a classdef constructor, store it as such + // and restore function_on_path to its previous value. + + octave_value old_function_on_path = function_on_path; + + octave_value maybe_cdef_ctor = find_user_function (); + + if (maybe_cdef_ctor.is_defined ()) + { + octave_function *fcn = maybe_cdef_ctor.function_value (true); + + if (fcn && fcn->is_classdef_constructor ()) + { + retval = maybe_cdef_ctor; + + class_constructors[name] = retval; + + function_on_path = old_function_on_path; + } + } + } return retval; } @@ -406,47 +468,57 @@ { octave_value retval; - if (name == dispatch_type) + if (full_name () == dispatch_type) retval = load_class_constructor (); else { - std::string dir_name; + octave_function *cm = cdef_manager::find_method_symbol (name, + dispatch_type); - std::string file_name = load_path::find_method (dispatch_type, name, - dir_name); + if (cm) + retval = octave_value (cm); - if (! file_name.empty ()) + if (! retval.is_defined ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name, - dispatch_type); + std::string dir_name; - if (fcn) + std::string file_name = load_path::find_method (dispatch_type, name, + dir_name); + + if (! file_name.empty ()) { - retval = octave_value (fcn); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, + dispatch_type); - class_methods[dispatch_type] = retval; - } - } + if (fcn) + { + retval = octave_value (fcn); - if (retval.is_undefined ()) - { - // Search parent classes + class_methods[dispatch_type] = retval; + } + } - const std::list& plist = parent_classes (dispatch_type); - - std::list::const_iterator it = plist.begin (); - - while (it != plist.end ()) + if (retval.is_undefined ()) { - retval = find_method (*it); + // Search parent classes - if (retval.is_defined ()) + const std::list& plist = + parent_classes (dispatch_type); + + std::list::const_iterator it = plist.begin (); + + while (it != plist.end ()) { - class_methods[dispatch_type] = retval; - break; + retval = find_method (*it); + + if (retval.is_defined ()) + { + class_methods[dispatch_type] = retval; + break; + } + + it++; } - - it++; } } } @@ -787,6 +859,13 @@ if (fcn.is_defined ()) return fcn; + // Package + + fcn = find_package (); + + if (fcn.is_defined ()) + return fcn; + // Built-in function (might be undefined). return built_in_function; @@ -975,7 +1054,7 @@ std::string dir_name = file_name.substr (0, pos); - octave_function *fcn = load_fcn_from_file (file_name, dir_name, + octave_function *fcn = load_fcn_from_file (file_name, dir_name, "", "", name, true); if (fcn) @@ -998,11 +1077,13 @@ { std::string dir_name; - std::string file_name = load_path::find_fcn (name, dir_name); + std::string file_name = load_path::find_fcn (name, dir_name, + package_name); if (! file_name.empty ()) { - octave_function *fcn = load_fcn_from_file (file_name, dir_name); + octave_function *fcn = load_fcn_from_file (file_name, dir_name, "", + package_name); if (fcn) function_on_path = octave_value (fcn); @@ -1012,6 +1093,25 @@ return function_on_path; } +octave_value +symbol_table::fcn_info::fcn_info_rep::find_package (void) +{ + // FIXME: implement correct way to check out of date package + //if (package.is_defined ()) + // out_of_date_check (package); + + if (! (error_state || package.is_defined ())) + { + octave_function * fcn = + cdef_manager::find_package_symbol (full_name ()); + + if (fcn) + package = octave_value (fcn); + } + + return package; +} + // Insert INF_CLASS in the set of class names that are considered // inferior to SUP_CLASS. Return FALSE if INF_CLASS is currently // marked as superior to SUP_CLASS. @@ -1069,10 +1169,11 @@ symbol_table::fcn_info::fcn_info_rep::dump (std::ostream& os, const std::string& prefix) const { - os << prefix << name + os << prefix << full_name () << " [" << (cmdline_function.is_defined () ? "c" : "") << (built_in_function.is_defined () ? "b" : "") + << (package.is_defined () ? "p" : "") << "]\n"; std::string tprefix = prefix + " "; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/symtab.h --- a/libinterp/corefcn/symtab.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/symtab.h Sun May 25 10:29:05 2014 -0700 @@ -756,10 +756,19 @@ public: fcn_info_rep (const std::string& nm) - : name (nm), subfunctions (), private_functions (), + : name (nm), package_name (), subfunctions (), private_functions (), class_constructors (), class_methods (), dispatch_map (), cmdline_function (), autoload_function (), function_on_path (), - built_in_function (), count (1) { } + built_in_function (), count (1) + { + size_t pos = name.rfind ('.'); + + if (pos != std::string::npos) + { + package_name = name.substr (0, pos); + name = name.substr (pos+1); + } + } octave_value load_private_function (const std::string& dir_name); @@ -775,6 +784,8 @@ octave_value find_autoload (void); + octave_value find_package (void); + octave_value find_user_function (void); bool is_user_function_defined (void) const @@ -883,6 +894,11 @@ clear_user_function (); } + void clear_package (void) + { + package = octave_value (); + } + void clear (bool force = false) { clear_map (subfunctions, force); @@ -892,6 +908,7 @@ clear_autoload_function (force); clear_user_function (force); + clear_package (); } void add_dispatch (const std::string& type, const std::string& fname) @@ -915,8 +932,18 @@ void dump (std::ostream& os, const std::string& prefix) const; + std::string full_name (void) const + { + if (package_name.empty ()) + return name; + else + return package_name + "." + name; + } + std::string name; + std::string package_name; + // Scope id to function object. std::map subfunctions; @@ -938,6 +965,8 @@ octave_value function_on_path; + octave_value package; + octave_value built_in_function; octave_refcount count; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/syscalls.cc --- a/libinterp/corefcn/syscalls.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/syscalls.cc Sun May 25 10:29:05 2014 -0700 @@ -511,7 +511,7 @@ if (nargin == 3) { - octave_stream strm = octave_stream_list::lookup (args (0), "fcntl"); + octave_stream strm = octave_stream_list::lookup (args(0), "fcntl"); if (! error_state) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/toplev.cc --- a/libinterp/corefcn/toplev.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/toplev.cc Sun May 25 10:29:05 2014 -0700 @@ -301,7 +301,8 @@ octave_map octave_call_stack::do_backtrace (size_t nskip, - octave_idx_type& curr_user_frame) const + octave_idx_type& curr_user_frame, + bool print_subfn) const { size_t user_code_frames = do_num_user_code_frames (curr_user_frame); @@ -340,7 +341,7 @@ file(k) = f->fcn_file_name (); std::string parent_fcn_name = f->parent_fcn_name (); - if (parent_fcn_name == std::string ()) + if (! print_subfn || parent_fcn_name == std::string ()) name(k) = f->name (); else name(k) = f->parent_fcn_name () + Vfilemarker + f->name (); @@ -445,6 +446,8 @@ break; } } + else if (incr == 0) // Break out of infinite loop by choosing an incr. + incr = -1; // There is no need to set scope and context here. That will // happen when the dbup/dbdown/keyboard frame is popped and we @@ -651,6 +654,8 @@ } while (retval == 0); + octave_stdout << "\n"; + if (retval == EOF) retval = 0; @@ -1274,8 +1279,6 @@ { false, "CAMD_LIBS", OCTAVE_CONF_CAMD_LIBS }, { false, "CARBON_LIBS", OCTAVE_CONF_CARBON_LIBS }, { false, "CC", OCTAVE_CONF_CC }, - // FIXME: CC_VERSION is deprecated. Remove in version 3.12 - { false, "CC_VERSION", OCTAVE_CONF_CC_VERSION }, { false, "CCOLAMD_CPPFLAGS", OCTAVE_CONF_CCOLAMD_CPPFLAGS }, { false, "CCOLAMD_LDFLAGS", OCTAVE_CONF_CCOLAMD_LDFLAGS }, { false, "CCOLAMD_LIBS", OCTAVE_CONF_CCOLAMD_LIBS }, @@ -1298,8 +1301,6 @@ { false, "CXXCPP", OCTAVE_CONF_CXXCPP }, { false, "CXXFLAGS", OCTAVE_CONF_CXXFLAGS }, { false, "CXXPICFLAG", OCTAVE_CONF_CXXPICFLAG }, - // FIXME: CXX_VERSION is deprecated. Remove in version 3.12 - { false, "CXX_VERSION", OCTAVE_CONF_CXX_VERSION }, { false, "DEFAULT_PAGER", OCTAVE_DEFAULT_PAGER }, { false, "DEFS", OCTAVE_CONF_DEFS }, { false, "DL_LD", OCTAVE_CONF_DL_LD }, diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/toplev.h --- a/libinterp/corefcn/toplev.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/toplev.h Sun May 25 10:29:05 2014 -0700 @@ -278,7 +278,16 @@ static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame) { return instance_ok () - ? instance->do_backtrace (nskip, curr_user_frame) : octave_map (); + ? instance->do_backtrace (nskip, curr_user_frame, true) + : octave_map (); + } + + static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame, + bool print_subfn) + { + return instance_ok () + ? instance->do_backtrace (nskip, curr_user_frame, print_subfn) + : octave_map (); } static octave_map empty_backtrace (void); @@ -414,7 +423,8 @@ } octave_map do_backtrace (size_t nskip, - octave_idx_type& curr_user_frame) const; + octave_idx_type& curr_user_frame, + bool print_subfn) const; bool do_goto_frame (size_t n, bool verbose); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/tril.cc --- a/libinterp/corefcn/tril.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/tril.cc Sun May 25 10:29:05 2014 -0700 @@ -42,7 +42,8 @@ static Array do_tril (const Array& a, octave_idx_type k, bool pack) { - octave_idx_type nr = a.rows (), nc = a.columns (); + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.columns (); const T *avec = a.fortran_vec (); octave_idx_type zero = 0; @@ -83,7 +84,8 @@ static Array do_triu (const Array& a, octave_idx_type k, bool pack) { - octave_idx_type nr = a.rows (), nc = a.columns (); + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.columns (); const T *avec = a.fortran_vec (); octave_idx_type zero = 0; @@ -211,7 +213,7 @@ print_usage (); else { - octave_value arg = args (0); + octave_value arg = args(0); dim_vector dims = arg.dims (); if (dims.length () != 2) @@ -274,7 +276,8 @@ if (arg.numel () == 0) return arg; - octave_idx_type nr = dims(0), nc = dims (1); + octave_idx_type nr = dims(0); + octave_idx_type nc = dims(1); // The sole purpose of the below is to force the correct // matrix size. This would not be necessary if the diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/txt-eng-ft.cc --- a/libinterp/corefcn/txt-eng-ft.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/txt-eng-ft.cc Sun May 25 10:29:05 2014 -0700 @@ -121,7 +121,7 @@ typedef std::pair ft_key; typedef std::map ft_cache; - // Cache the fonts loaded by freetype. This cache only contains + // Cache the fonts loaded by FreeType. This cache only contains // weak references to the fonts, strong references are only present // in class ft_render. ft_cache cache; @@ -138,7 +138,7 @@ : library (), freetype_initialized (false), fontconfig_initialized (false) { if (FT_Init_FreeType (&library)) - ::error ("unable to initialize freetype library"); + ::error ("unable to initialize FreeType library"); else freetype_initialized = true; @@ -635,7 +635,8 @@ FT_UInt glyph_index, previous = 0; std::string str = e.string_value (); - size_t n = str.length (), curr = 0; + size_t n = str.length (); + size_t curr = 0; mbstate_t ps; memset (&ps, 0, sizeof (ps)); // Initialize state to 0. wchar_t wc; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/txt-eng-ft.h --- a/libinterp/corefcn/txt-eng-ft.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/txt-eng-ft.h Sun May 25 10:29:05 2014 -0700 @@ -114,7 +114,7 @@ ft_render& operator = (const ft_render&); // Class to hold information about fonts and a strong - // reference to the font objects loaded by freetype. + // reference to the font objects loaded by FreeType. class ft_font { public: diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/urlwrite.cc --- a/libinterp/corefcn/urlwrite.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/urlwrite.cc Sun May 25 10:29:05 2014 -0700 @@ -391,7 +391,7 @@ } - if (param.numel () % 2 == 1 ) + if (param.numel () % 2 == 1) { error ("urlwrite: number of elements in PARAM must be even"); return retval; @@ -539,7 +539,7 @@ return retval; } - if (param.numel () % 2 == 1 ) + if (param.numel () % 2 == 1) { error ("urlread: number of elements in PARAM must be even"); return retval; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/utils.cc --- a/libinterp/corefcn/utils.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/utils.cc Sun May 25 10:29:05 2014 -0700 @@ -303,7 +303,7 @@ If the second optional argument @qcode{\"all\"} is supplied, return\n\ a cell array containing the list of all files that have the same\n\ name in the path. If no files are found, return an empty cell array.\n\ -@seealso{file_in_path, find_dir_in_path, path}\n\ +@seealso{file_in_path, dir_in_loadpath, path}\n\ @end deftypefn") { octave_value retval; @@ -380,7 +380,7 @@ If the third optional argument @qcode{\"all\"} is supplied, return\n\ a cell array containing the list of all files that have the same\n\ name in the path. If no files are found, return an empty cell array.\n\ -@seealso{file_in_loadpath, find_dir_in_path, path}\n\ +@seealso{file_in_loadpath, dir_in_loadpath, path}\n\ @end deftypefn") { octave_value retval; @@ -892,10 +892,10 @@ %!error make_absolute_filename ("foo", "bar") */ -DEFUN (find_dir_in_path, args, , +DEFUN (dir_in_loadpath, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} find_dir_in_path (@var{dir})\n\ -@deftypefnx {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\ +@deftypefn {Built-in Function} {} dir_in_loadpath (@var{dir})\n\ +@deftypefnx {Built-in Function} {} dir_in_loadpath (@var{dir}, \"all\")\n\ Return the full name of the path element matching @var{dir}. The\n\ match is performed at the end of each path element. For example, if\n\ @var{dir} is @qcode{\"foo/bar\"}, it matches the path element\n\ @@ -926,7 +926,7 @@ retval = Cell (load_path::find_matching_dirs (dir)); } else - error ("find_dir_in_path: DIR must be a directory name"); + error ("dir_in_loadpath: DIR must be a directory name"); } else print_usage (); @@ -937,8 +937,8 @@ /* ## FIXME: We need system-dependent tests here. -%!error find_dir_in_path () -%!error find_dir_in_path ("foo", "bar", 1) +%!error dir_in_loadpath () +%!error dir_in_loadpath ("foo", "bar", 1) */ DEFUNX ("errno", Ferrno, args, , diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/variables.cc --- a/libinterp/corefcn/variables.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/variables.cc Sun May 25 10:29:05 2014 -0700 @@ -548,7 +548,7 @@ Check only for directories.\n\ @end table\n\ \n\ -@seealso{file_in_loadpath, file_in_path, find_dir_in_path, stat}\n\ +@seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}\n\ @end deftypefn") { octave_value retval = false; @@ -1405,7 +1405,9 @@ param.modifier = 'r'; param.parameter_length = 0; - int a = 0, b = -1, balance = 1; + int a = 0; + int b = -1; + int balance = 1; unsigned int items; size_t pos; std::string cmd; @@ -2255,6 +2257,7 @@ { symbol_table::clear_objects (); octave_class::clear_exemplar_map (); + symbol_table::clear_all (); } else { @@ -2464,6 +2467,7 @@ { symbol_table::clear_objects (); octave_class::clear_exemplar_map (); + symbol_table::clear_all (); } else { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/corefcn/xdiv.cc --- a/libinterp/corefcn/xdiv.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/corefcn/xdiv.cc Sun May 25 10:29:05 2014 -0700 @@ -713,7 +713,9 @@ if (! mx_div_conform (a, d)) return MT (); - octave_idx_type m = a.rows (), n = d.rows (), l = d.length (); + octave_idx_type m = a.rows (); + octave_idx_type n = d.rows (); + octave_idx_type l = d.length (); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; @@ -794,7 +796,10 @@ if (! mx_leftdiv_conform (d, a, blas_no_trans)) return MT (); - octave_idx_type m = d.cols (), n = a.cols (), k = a.rows (), l = d.length (); + octave_idx_type m = d.cols (); + octave_idx_type n = a.cols (); + octave_idx_type k = a.rows (); + octave_idx_type l = d.length (); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; @@ -871,8 +876,11 @@ if (! mx_div_conform (a, d)) return MT (); - octave_idx_type m = a.rows (), n = d.rows (), k = d.cols (); - octave_idx_type l = std::min (m, n), lk = std::min (l, k); + octave_idx_type m = a.rows (); + octave_idx_type n = d.rows (); + octave_idx_type k = d.cols (); + octave_idx_type l = std::min (m, n); + octave_idx_type lk = std::min (l, k); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; @@ -943,8 +951,11 @@ if (! mx_leftdiv_conform (d, a, blas_no_trans)) return MT (); - octave_idx_type m = d.cols (), n = a.cols (), k = d.rows (); - octave_idx_type l = std::min (m, n), lk = std::min (l, k); + octave_idx_type m = d.cols (); + octave_idx_type n = a.cols (); + octave_idx_type k = d.rows (); + octave_idx_type l = std::min (m, n); + octave_idx_type lk = std::min (l, k); MT x (m, n); typedef typename DMT::element_type S; typedef typename MT::element_type T; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/__delaunayn__.cc --- a/libinterp/dldfcn/__delaunayn__.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/__delaunayn__.cc Sun May 25 10:29:05 2014 -0700 @@ -175,7 +175,8 @@ facetT *facet; vertexT *vertex, **vertexp; - octave_idx_type nf = 0, i = 0; + octave_idx_type nf = 0; + octave_idx_type i = 0; FORALLfacets { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/__init_fltk__.cc --- a/libinterp/dldfcn/__init_fltk__.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/__init_fltk__.cc Sun May 25 10:29:05 2014 -0700 @@ -291,7 +291,7 @@ //returns the number of visible menu items int len = menubar->size (); int n = 0; - for (int t = 0; t < len; t++ ) + for (int t = 0; t < len; t++) { const Fl_Menu_Item *m = static_cast (& (menubar->menu ()[t])); @@ -326,7 +326,7 @@ // Kai Habel (14.10.2010) std::string menupath; - for (int t = 0; t < menubar->size (); t++ ) + for (int t = 0; t < menubar->size (); t++) { Fl_Menu_Item *m = const_cast (&(menubar->menu ()[t])); if (m->submenu ()) @@ -336,7 +336,7 @@ menupath += "/"; menupath += m->label (); - if (menupath.compare (findname) == 0 ) + if (menupath.compare (findname) == 0) return (t); } else @@ -1056,7 +1056,7 @@ void pixel2pos (const graphics_handle& ax, int px, int py, double& xx, double& yy) const { - pixel2pos ( gh_manager::get_object (ax), px, py, xx, yy); + pixel2pos (gh_manager::get_object (ax), px, py, xx, yy); } void pixel2pos (graphics_object ax, int px, int py, double& xx, @@ -1072,7 +1072,7 @@ } } - graphics_handle pixel2axes_or_ca (int px, int py ) + graphics_handle pixel2axes_or_ca (int px, int py) { Matrix kids = fp.get_children (); int len = kids.length (); @@ -1464,7 +1464,7 @@ if (Fl::event_button () == 1) { - if ( Fl::event_clicks () == 1) + if (Fl::event_clicks () == 1) { if (ax_obj && ax_obj.isa ("axes")) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/amd.cc --- a/libinterp/dldfcn/amd.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/amd.cc Sun May 25 10:29:05 2014 -0700 @@ -67,8 +67,8 @@ @table @asis\n\ @item @var{opts}.dense\n\ Determines what @code{amd} considers to be a dense row or column of the\n\ -input matrix. Rows or columns with more than @code{max(16, (dense *\n\ -sqrt (@var{n})} entries, where @var{n} is the order of the matrix @var{S},\n\ +input matrix. Rows or columns with more than @code{max (16, (dense *\n\ +sqrt (@var{n})))} entries, where @var{n} is the order of the matrix @var{S},\n\ are ignored by @code{amd} during the calculation of the permutation\n\ The value of dense must be a positive scalar and its default value is 10.0\n\ \n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/ccolamd.cc --- a/libinterp/dldfcn/ccolamd.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/ccolamd.cc Sun May 25 10:29:05 2014 -0700 @@ -100,10 +100,9 @@ @var{cmember} is an optional vector of length @math{n}. It defines the\n\ constraints on the column ordering. If @code{@var{cmember}(j) = @var{c}},\n\ then column @var{j} is in constraint set @var{c} (@var{c} must be in the\n\ -range 1 to\n\ -n). In the output permutation @var{p}, all columns in set 1 appear\n\ -first, followed by all columns in set 2, and so on. @code{@var{cmember} =\n\ -ones (1,n)} if not present or empty.\n\ +range 1 to n). In the output permutation @var{p}, all columns in set 1\n\ +appear first, followed by all columns in set 2, and so on.\n\ +@code{@var{cmember} = ones (1,n)} if not present or empty.\n\ @code{ccolamd (@var{S}, [], 1 : n)} returns @code{1 : n}\n\ \n\ @code{@var{p} = ccolamd (@var{S})} is about the same as\n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/chol.cc --- a/libinterp/dldfcn/chol.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/chol.cc Sun May 25 10:29:05 2014 -0700 @@ -155,7 +155,7 @@ { std::string tmp = args(n++).string_value (); - if (! error_state ) + if (! error_state) { if (tmp.compare ("vector") == 0) vecout = true; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/fftw.cc --- a/libinterp/dldfcn/fftw.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/fftw.cc Sun May 25 10:29:05 2014 -0700 @@ -303,7 +303,7 @@ if (args(1).is_real_scalar ()) { int nthreads = args(1).int_value(); - if ( nthreads >= 1) + if (nthreads >= 1) { #if defined (HAVE_FFTW3_THREADS) octave_fftw_planner::threads (nthreads); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/qr.cc --- a/libinterp/dldfcn/qr.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/qr.cc Sun May 25 10:29:05 2014 -0700 @@ -744,7 +744,9 @@ bool check_qr_dims (const octave_value& q, const octave_value& r, bool allow_ecf = false) { - octave_idx_type m = q.rows (), k = r.rows (), n = r.columns (); + octave_idx_type m = q.rows (); + octave_idx_type k = r.rows (); + octave_idx_type n = r.columns (); return ((q.ndims () == 2 && r.ndims () == 2 && k == q.columns ()) && (m == k || (allow_ecf && k == n && k < m))); } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/symrcm.cc --- a/libinterp/dldfcn/symrcm.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/symrcm.cc Sun May 25 10:29:05 2014 -0700 @@ -487,7 +487,8 @@ octave_idx_type s = 0; // head- and tail-indices for the queue - octave_idx_type qt = 0, qh = 0; + octave_idx_type qt = 0; + octave_idx_type qh = 0; CMK_Node v, w; // dimension of the matrix octave_idx_type N = nr; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/dldfcn/tsearch.cc --- a/libinterp/dldfcn/tsearch.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/dldfcn/tsearch.cc Sun May 25 10:29:05 2014 -0700 @@ -110,8 +110,10 @@ const octave_idx_type np = xi.length (); ColumnVector values (np); - double x0 = 0.0, y0 = 0.0; - double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0; + double x0, y0, a11, a12, a21, a22, det; + x0 = y0 = 0.0; + a11 = a12 = a21 = a22 = 0.0; + det = 0.0; octave_idx_type k = nelem; // k is a counter of elements for (octave_idx_type kp = 0; kp < np; kp++) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/genprops.awk --- a/libinterp/genprops.awk Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/genprops.awk Sun May 25 10:29:05 2014 -0700 @@ -290,7 +290,7 @@ if (class_name && ! base) emit_common_declarations(); - printf ("public:\n\n\n static std::set core_property_names (void);\n\n static bool has_core_property (const caseless_str& pname);\n\n std::set all_property_names (void) const;\n\n"); + printf ("public:\n\n\n static std::set core_property_names (void);\n\n static std::set readonly_property_names (void);\n\n static bool has_core_property (const caseless_str& pname);\n\n static bool has_readonly_property (const caseless_str& pname);\n\n std::set all_property_names (void) const;\n\n"); if (! base) printf (" bool has_property (const caseless_str& pname) const;\n\n"); @@ -470,7 +470,7 @@ class_name); if (! base) - printf (" const std::set& pnames = all_property_names ();\n\n caseless_str pname = validate_property_name (\"get\", go_name, pnames, pname_arg);\n\n if (error_state)\n return;\n\n"); + printf (" const std::set& pnames = all_property_names ();\n\n caseless_str pname = validate_property_name (\"get\", go_name, pnames, pname_arg);\n\n if (error_state)\n return;\n else if (has_readonly_property (pname))\n {\n error (\"set: \\\"%%s\\\" is read-only\", pname.c_str ());\n return;\n }\n\n"); first = 1; @@ -611,6 +611,7 @@ printf ("std::string %s::properties::go_name (\"%s\");\n\n", class_name, object_name); + ## core_property_names printf ("std::set\n"); if (base) printf ("base_properties"); @@ -622,7 +623,7 @@ if (! base) printf ("\n std::set base_pnames = base_properties::core_property_names ();\n all_pnames.insert (base_pnames.begin (), base_pnames.end ());\n"); printf ("\n initialized = true;\n }\n\n return all_pnames;\n}\n\n"); - + ## has_core_property printf ("bool\n"); if (base) printf ("base_properties"); @@ -630,6 +631,30 @@ printf ("%s::properties", class_name); printf ("::has_core_property (const caseless_str& pname)\n{\n std::set pnames = core_property_names ();\n\n return pnames.find (pname) != pnames.end ();\n}\n\n", class_name); + ## readonly_property_names + printf ("std::set\n"); + if (base) + printf ("base_properties"); + else + printf ("%s::properties", class_name); + printf ("::readonly_property_names (void)\n{\n static std::set all_pnames;\n\n static bool initialized = false;\n\n if (! initialized)\n {\n"); + for (i = 1; i <= idx; i++) + if (readonly[i]) + { + printf (" all_pnames.insert (\"%s\");\n", name[i]); + } + if (! base) + printf ("\n std::set base_pnames = base_properties::readonly_property_names ();\n all_pnames.insert (base_pnames.begin (), base_pnames.end ());\n"); + printf ("\n initialized = true;\n }\n\n return all_pnames;\n}\n\n"); + ## has_readonly_property + printf ("bool\n"); + if (base) + printf ("base_properties"); + else + printf ("%s::properties", class_name); + printf ("::has_readonly_property (const caseless_str& pname)\n{\n std::set pnames = readonly_property_names ();\n\n return pnames.find (pname) != pnames.end ();\n}\n\n", class_name); + + ## all_property_names printf ("std::set\n"); if (base) printf ("base_properties"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/module.mk --- a/libinterp/octave-value/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/module.mk Sun May 25 10:29:05 2014 -0700 @@ -36,6 +36,7 @@ octave-value/ov-cell.h \ octave-value/ov-ch-mat.h \ octave-value/ov-class.h \ + octave-value/ov-classdef.h \ octave-value/ov-colon.h \ octave-value/ov-complex.h \ octave-value/ov-cs-list.h \ @@ -94,6 +95,7 @@ octave-value/ov-cell.cc \ octave-value/ov-ch-mat.cc \ octave-value/ov-class.cc \ + octave-value/ov-classdef.cc \ octave-value/ov-colon.cc \ octave-value/ov-complex.cc \ octave-value/ov-cs-list.cc \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-diag.cc --- a/libinterp/octave-value/ov-base-diag.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-diag.cc Sun May 25 10:29:05 2014 -0700 @@ -100,7 +100,6 @@ bool resize_ok) { octave_value retval; - typedef typename DMT::element_type el_type; if (idx.length () == 2 && ! resize_ok) { @@ -441,7 +440,8 @@ bool octave_base_diag::load_ascii (std::istream& is) { - octave_idx_type r = 0, c = 0; + octave_idx_type r = 0; + octave_idx_type c = 0; bool success = true; if (extract_keyword (is, "rows", r, true) @@ -505,8 +505,7 @@ template void -octave_base_diag::print (std::ostream& os, - bool pr_as_read_syntax) const +octave_base_diag::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); @@ -531,6 +530,23 @@ template octave_value +octave_base_diag::fast_elem_extract (octave_idx_type n) const +{ + if (n < matrix.numel ()) + { + octave_idx_type nr = matrix.rows (); + + octave_idx_type r = n % nr; + octave_idx_type c = n / nr; + + return octave_value (matrix.elem (r, c)); + } + else + return octave_value (); +} + +template +octave_value octave_base_diag::to_dense (void) const { if (! dense_cache.is_defined ()) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-diag.h --- a/libinterp/octave-value/ov-base-diag.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-diag.h Sun May 25 10:29:05 2014 -0700 @@ -203,10 +203,12 @@ bool print_as_scalar (void) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_info (std::ostream& os, const std::string& prefix) const; + octave_value fast_elem_extract (octave_idx_type n) const; + protected: DMT matrix; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-int.cc --- a/libinterp/octave-value/ov-base-int.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-int.cc Sun May 25 10:29:05 2014 -0700 @@ -266,7 +266,7 @@ template bool octave_base_int_matrix::load_binary (std::istream& is, bool swap, - oct_mach_info::float_format ) + oct_mach_info::float_format) { int32_t mdims; if (! is.read (reinterpret_cast (&mdims), 4)) @@ -347,7 +347,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); // Octave uses column-major, while HDF5 uses row-major ordering @@ -550,7 +551,8 @@ hid_t save_type_hid = HDF5_SAVE_TYPE; bool retval = true; hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; space_hid = H5Screate_simple (0, dimens, 0); if (space_hid < 0) return false; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-int.h --- a/libinterp/octave-value/ov-base-int.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-int.h Sun May 25 10:29:05 2014 -0700 @@ -74,10 +74,10 @@ bool load_ascii (std::istream& is); - bool save_binary (std::ostream& os, bool& ); + bool save_binary (std::ostream& os, bool&); bool load_binary (std::istream& is, bool swap, - oct_mach_info::float_format ); + oct_mach_info::float_format); #if defined (HAVE_HDF5) bool save_hdf5 (hid_t loc_id, const char *name, bool); @@ -119,13 +119,13 @@ bool load_ascii (std::istream& is); - bool save_binary (std::ostream& os, bool& ); + bool save_binary (std::ostream& os, bool&); bool load_binary (std::istream& is, bool swap, - oct_mach_info::float_format ); + oct_mach_info::float_format); #if defined (HAVE_HDF5) - bool save_hdf5 (hid_t loc_id, const char *name, bool ); + bool save_hdf5 (hid_t loc_id, const char *name, bool); bool load_hdf5 (hid_t loc_id, const char *name); #endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-mat.cc --- a/libinterp/octave-value/ov-base-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -351,7 +351,8 @@ { // optimize all scalar indices. Don't construct an index array, // but rather calc a scalar index directly. - octave_idx_type k = 1, j = 0; + octave_idx_type k = 1; + octave_idx_type j = 0; for (octave_idx_type i = 0; i < n_idx; i++) { j += idx_vec(i)(0) * k; @@ -435,7 +436,7 @@ template void -octave_base_matrix::print (std::ostream& os, bool pr_as_read_syntax) const +octave_base_matrix::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-mat.h --- a/libinterp/octave-value/ov-base-mat.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-mat.h Sun May 25 10:29:05 2014 -0700 @@ -153,7 +153,7 @@ bool print_as_scalar (void) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_info (std::ostream& os, const std::string& prefix) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-scalar.cc --- a/libinterp/octave-value/ov-base-scalar.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-scalar.cc Sun May 25 10:29:05 2014 -0700 @@ -143,7 +143,7 @@ template void -octave_base_scalar::print (std::ostream& os, bool pr_as_read_syntax) const +octave_base_scalar::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); @@ -180,6 +180,13 @@ } template +octave_value +octave_base_scalar::fast_elem_extract (octave_idx_type n) const +{ + return (n == 0) ? octave_value (scalar) : octave_value (); +} + +template bool octave_base_scalar::fast_elem_insert_self (void *where, builtin_type_t btyp) const diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-scalar.h --- a/libinterp/octave-value/ov-base-scalar.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-scalar.h Sun May 25 10:29:05 2014 -0700 @@ -132,7 +132,7 @@ bool is_true (void) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; @@ -148,6 +148,8 @@ ST& scalar_ref (void) { return scalar; } + octave_value fast_elem_extract (octave_idx_type n) const; + bool fast_elem_insert_self (void *where, builtin_type_t btyp) const; protected: diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-sparse.cc --- a/libinterp/octave-value/ov-base-sparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-sparse.cc Sun May 25 10:29:05 2014 -0700 @@ -288,7 +288,7 @@ template void -octave_base_sparse::print (std::ostream& os, bool pr_as_read_syntax) const +octave_base_sparse::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); @@ -436,31 +436,73 @@ return success; } + +template +octave_value +octave_base_sparse::fast_elem_extract (octave_idx_type n) const +{ + octave_idx_type nr = matrix.rows (); + octave_idx_type nc = matrix.cols (); + + octave_idx_type i = n % nr; + octave_idx_type j = n / nr; + + return (i < nr && j < nc) ? octave_value (matrix(i,j)) : octave_value (); +} + template octave_value octave_base_sparse::map (octave_base_value::unary_mapper_t umap) const { + if (umap == umap_xtolower || umap == umap_xtoupper) + return matrix; + // Try the map on the dense value. + // FIXME: We should probably be smarter about this, especially for the + // cases that are expected to return sparse matrices. octave_value retval = this->full_value ().map (umap); // Sparsify the result if possible. - // FIXME: intentionally skip this step for string mappers. Is this wanted? - if (umap >= umap_xisalnum && umap <= umap_xtoupper) - return retval; - switch (retval.builtin_type ()) + switch (umap) { - case btyp_double: - retval = retval.sparse_matrix_value (); + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + // FIXME: intentionally skip this step for string mappers. + // Is this wanted? break; - case btyp_complex: - retval = retval.sparse_complex_matrix_value (); - break; - case btyp_bool: - retval = retval.sparse_bool_matrix_value (); - break; + default: - break; + { + switch (retval.builtin_type ()) + { + case btyp_double: + retval = retval.sparse_matrix_value (); + break; + + case btyp_complex: + retval = retval.sparse_complex_matrix_value (); + break; + + case btyp_bool: + retval = retval.sparse_bool_matrix_value (); + break; + + default: + break; + } + } } return retval; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base-sparse.h --- a/libinterp/octave-value/ov-base-sparse.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base-sparse.h Sun May 25 10:29:05 2014 -0700 @@ -147,7 +147,7 @@ bool print_as_scalar (void) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_info (std::ostream& os, const std::string& prefix) const; @@ -165,6 +165,8 @@ octave_idx_type *mex_get_jc (void) const { return matrix.mex_get_jc (); } + octave_value fast_elem_extract (octave_idx_type n) const; + protected: octave_value map (octave_base_value::unary_mapper_t umap) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base.cc --- a/libinterp/octave-value/ov-base.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base.cc Sun May 25 10:29:05 2014 -0700 @@ -52,6 +52,7 @@ #include "parse.h" #include "pr-output.h" #include "utils.h" +#include "toplev.h" #include "variables.h" builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y) @@ -396,7 +397,7 @@ } void -octave_base_value::print (std::ostream&, bool) const +octave_base_value::print (std::ostream&, bool) { gripe_wrong_type_arg ("octave_base_value::print ()", type_name ()); } @@ -1536,6 +1537,111 @@ return new octave_cell (); } +static inline octave_value_list +sanitize (const octave_value_list& ovl) +{ + octave_value_list retval = ovl; + + for (octave_idx_type i = 0; i < ovl.length (); i++) + { + if (retval(i).is_magic_colon ()) + retval(i) = ":"; + } + + return retval; +} + +octave_value +make_idx_args (const std::string& type, + const std::list& idx, + const std::string& who) +{ + octave_value retval; + + size_t len = type.length (); + + if (len == idx.size ()) + { + Cell type_field (1, len); + Cell subs_field (1, len); + + std::list::const_iterator p = idx.begin (); + + for (size_t i = 0; i < len; i++) + { + char t = type[i]; + + switch (t) + { + case '(': + type_field(i) = "()"; + subs_field(i) = Cell (sanitize (*p++)); + break; + + case '{': + type_field(i) = "{}"; + subs_field(i) = Cell (sanitize (*p++)); + break; + + case '.': + { + type_field(i) = "."; + + octave_value_list vlist = *p++; + + if (vlist.length () == 1) + { + octave_value val = vlist(0); + + if (val.is_string ()) + subs_field(i) = val; + else + { + error ("expecting character string argument for '.' index"); + return retval; + } + } + else + { + error ("expecting single argument for '.' index"); + return retval; + } + } + break; + + default: + panic_impossible (); + break; + } + } + + octave_map m; + + m.assign ("type", type_field); + m.assign ("subs", subs_field); + + retval = m; + } + else + error ("invalid index for %s", who.c_str ()); + + return retval; +} + +bool +called_from_builtin (void) +{ + octave_function *fcn = octave_call_stack::caller (); + + // FIXME: we probably need a better check here, or some other + // mechanism to avoid overloaded functions when builtin is used. + // For example, what if someone overloads the builtin function? + // Also, are there other places where using builtin is not properly + // avoiding dispatch? + + return (fcn && fcn->name () == "builtin"); +} + void install_base_type_conversions (void) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-base.h --- a/libinterp/octave-value/ov-base.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-base.h Sun May 25 10:29:05 2014 -0700 @@ -606,7 +606,7 @@ virtual bool print_as_scalar (void) const { return false; } - virtual void print (std::ostream& os, bool pr_as_read_syntax = false) const; + virtual void print (std::ostream& os, bool pr_as_read_syntax = false); virtual void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; @@ -828,4 +828,16 @@ // is memory to be saved extern OCTINTERP_API bool Vsparse_auto_mutate; +// Utility function to convert C++ arguments used in subsref/subsasgn into an +// octave_value_list object that can be used to call a function/method in the +// interpreter. +extern OCTINTERP_API octave_value +make_idx_args (const std::string& type, + const std::list& idx, + const std::string& who); + +// Tells whether some regular octave_value_base methods are being called from +// within the "builtin" function. +extern OCTINTERP_API bool called_from_builtin (void); + #endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-bool-mat.cc --- a/libinterp/octave-value/ov-bool-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-bool-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -421,7 +421,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; boolNDArray m = bool_array_value (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-bool-mat.h --- a/libinterp/octave-value/ov-bool-mat.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-bool-mat.h Sun May 25 10:29:05 2014 -0700 @@ -151,10 +151,10 @@ FloatComplex float_complex_value (bool = false) const; ComplexMatrix complex_matrix_value (bool = false) const - { return ComplexMatrix (matrix.matrix_value ( )); } + { return ComplexMatrix (matrix.matrix_value ()); } FloatComplexMatrix float_complex_matrix_value (bool = false) const - { return FloatComplexMatrix (matrix.matrix_value ( )); } + { return FloatComplexMatrix (matrix.matrix_value ()); } ComplexNDArray complex_array_value (bool = false) const { return ComplexNDArray (matrix); } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-bool-sparse.cc --- a/libinterp/octave-value/ov-bool-sparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-bool-sparse.cc Sun May 25 10:29:05 2014 -0700 @@ -225,16 +225,16 @@ int32_t itmp; // Use negative value for ndims to be consistent with other formats - itmp= -2; + itmp = -2; os.write (reinterpret_cast (&itmp), 4); - itmp= nr; + itmp = nr; os.write (reinterpret_cast (&itmp), 4); - itmp= nc; + itmp = nc; os.write (reinterpret_cast (&itmp), 4); - itmp= nz; + itmp = nz; os.write (reinterpret_cast (&itmp), 4); // add one to the printed indices to go from @@ -358,7 +358,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; SparseBoolMatrix m = sparse_bool_matrix_value (); octave_idx_type tmp; @@ -567,7 +568,7 @@ #else group_hid = H5Gopen (loc_id, name); #endif - if (group_hid < 0 ) return false; + if (group_hid < 0) return false; #if HAVE_HDF5_18 data_hid = H5Dopen (group_hid, "nr", H5P_DEFAULT); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-bool.cc --- a/libinterp/octave-value/ov-bool.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-bool.cc Sun May 25 10:29:05 2014 -0700 @@ -165,7 +165,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-cell.cc --- a/libinterp/octave-value/ov-cell.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-cell.cc Sun May 25 10:29:05 2014 -0700 @@ -687,7 +687,7 @@ } void -octave_cell::print (std::ostream& os, bool) const +octave_cell::print (std::ostream& os, bool) { print_raw (os); } @@ -1077,7 +1077,8 @@ return (empty > 0); hsize_t rank = dv.length (); - hid_t space_hid = -1, data_hid = -1, size_hid = -1; + hid_t space_hid, data_hid, size_hid; + space_hid = data_hid = size_hid = -1; #if HAVE_HDF5_18 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-cell.h --- a/libinterp/octave-value/ov-cell.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-cell.h Sun May 25 10:29:05 2014 -0700 @@ -147,7 +147,7 @@ bool print_as_scalar (void) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-class.cc Sun May 25 10:29:05 2014 -0700 @@ -268,97 +268,6 @@ error ("assignment to class element failed"); } -static inline octave_value_list -sanitize (const octave_value_list& ovl) -{ - octave_value_list retval = ovl; - - for (octave_idx_type i = 0; i < ovl.length (); i++) - { - if (retval(i).is_magic_colon ()) - retval(i) = ":"; - } - - return retval; -} - -static inline octave_value -make_idx_args (const std::string& type, - const std::list& idx, - const std::string& who) -{ - octave_value retval; - - size_t len = type.length (); - - if (len == idx.size ()) - { - Cell type_field (1, len); - Cell subs_field (1, len); - - std::list::const_iterator p = idx.begin (); - - for (size_t i = 0; i < len; i++) - { - char t = type[i]; - - switch (t) - { - case '(': - type_field(i) = "()"; - subs_field(i) = Cell (sanitize (*p++)); - break; - - case '{': - type_field(i) = "{}"; - subs_field(i) = Cell (sanitize (*p++)); - break; - - case '.': - { - type_field(i) = "."; - - octave_value_list vlist = *p++; - - if (vlist.length () == 1) - { - octave_value val = vlist(0); - - if (val.is_string ()) - subs_field(i) = val; - else - { - error ("expecting character string argument for '.' index"); - return retval; - } - } - else - { - error ("expecting single argument for '.' index"); - return retval; - } - } - break; - - default: - panic_impossible (); - break; - } - } - - octave_map m; - - m.assign ("type", type_field); - m.assign ("subs", subs_field); - - retval = m; - } - else - error ("invalid index for %s", who.c_str ()); - - return retval; -} - Cell octave_class::dotref (const octave_value_list& idx) { @@ -398,20 +307,6 @@ return retval; } -static bool -called_from_builtin (void) -{ - octave_function *fcn = octave_call_stack::caller (); - - // FIXME: we probably need a better check here, or some other - // mechanism to avoid overloaded functions when builtin is used. - // For example, what if someone overloads the builtin function? - // Also, are there other places where using builtin is not properly - // avoiding dispatch? - - return (fcn && fcn->name () == "builtin"); -} - Matrix octave_class::size (void) { @@ -1150,7 +1045,7 @@ void -octave_class::print (std::ostream& os, bool) const +octave_class::print (std::ostream& os, bool) { print_raw (os); } @@ -1279,7 +1174,8 @@ bool octave_class::reconstruct_parents (void) { - bool retval = true, might_have_inheritance = false; + bool retval = true; + bool might_have_inheritance = false; std::string dbgstr = "dork"; // First, check to see if there might be an issue with inheritance. @@ -1287,10 +1183,10 @@ { std::string key = map.key (p); Cell val = map.contents (p); - if ( val(0).is_object () ) + if (val(0).is_object ()) { dbgstr = "blork"; - if ( key == val(0).class_name () ) + if (key == val(0).class_name ()) { might_have_inheritance = true; dbgstr = "cork"; @@ -1429,7 +1325,7 @@ success = false; } } - else if (len == 0 ) + else if (len == 0) { map = octave_map (dim_vector (1, 1)); c_name = classname; @@ -1573,7 +1469,7 @@ success = false; } } - else if (len == 0 ) + else if (len == 0) map = octave_map (dim_vector (1, 1)); else panic_impossible (); @@ -2148,7 +2044,7 @@ "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} isobject (@var{x})\n\ Return true if @var{x} is a class object.\n\ -@seealso{class, typeinfo, isa, ismethod}\n\ +@seealso{class, typeinfo, isa, ismethod, isprop}\n\ @end deftypefn") { octave_value retval; @@ -2163,8 +2059,8 @@ DEFUN (ismethod, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} ismethod (@var{x}, @var{method})\n\ -Return true if @var{x} is a class object and the string @var{method}\n\ +@deftypefn {Built-in Function} {} ismethod (@var{obj}, @var{method})\n\ +Return true if @var{obj} is a class object and the string @var{method}\n\ is a method of this class.\n\ @seealso{isprop, isobject}\n\ @end deftypefn") diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-class.h --- a/libinterp/octave-value/ov-class.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-class.h Sun May 25 10:29:05 2014 -0700 @@ -169,7 +169,7 @@ string_vector all_strings (bool pad) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-classdef.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/octave-value/ov-classdef.cc Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,3910 @@ +/* + +Copyright (C) 2012-2013 Michael Goffioul + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "defun.h" +#include "load-path.h" +#include "ov-builtin.h" +#include "ov-classdef.h" +#include "ov-fcn-handle.h" +#include "ov-typeinfo.h" +#include "ov-usr-fcn.h" +#include "pt-assign.h" +#include "pt-classdef.h" +#include "pt-funcall.h" +#include "pt-misc.h" +#include "pt-stmt.h" +#include "pt-walk.h" +#include "singleton-cleanup.h" +#include "symtab.h" +#include "toplev.h" + +#include "Array.cc" + +static void +gripe_method_access (const std::string& from, const cdef_method& meth) +{ + octave_value acc = meth.get ("Access"); + std::string acc_s; + + if (acc.is_string ()) + acc_s = acc.string_value (); + else + acc_s = "class-restricted"; + + error ("%s: method `%s' has %s access and cannot be run in this context", + from.c_str (), meth.get_name ().c_str (), acc_s.c_str ()); +} + +static void +gripe_property_access (const std::string& from, const cdef_property& prop, + bool is_set = false) +{ + octave_value acc = prop.get (is_set ? "SetAccess" : "GetAccess"); + std::string acc_s; + + if (acc.is_string ()) + acc_s = acc.string_value (); + else + acc_s = "class-restricted"; + + if (is_set) + error ("%s: property `%s' has %s access and cannot be set in this context", + from.c_str (), prop.get_name ().c_str (), acc_s.c_str ()); + else + error ("%s: property `%s' has %s access and cannot be obtained in this context", + from.c_str (), prop.get_name ().c_str (), acc_s.c_str ()); +} + +static std::string +get_base_name (const std::string& nm) +{ + std::string::size_type pos = nm.find_last_of ('.'); + + if (pos != std::string::npos) + return nm.substr (pos + 1); + + return nm; +} + +static void +make_function_of_class (const std::string& class_name, + const octave_value& fcn) +{ + octave_function *of = fcn.function_value (); + + if (! error_state) + { + of->stash_dispatch_class (class_name); + + octave_user_function *uf = of->user_function_value (true); + + if (! error_state && uf) + { + if (get_base_name (class_name) == uf->name ()) + { + uf->mark_as_class_constructor (); + uf->mark_as_classdef_constructor (); + } + else + uf->mark_as_class_method (); + } + } +} + +static void +make_function_of_class (const cdef_class& cls, const octave_value& fcn) +{ + make_function_of_class (cls.get_name (), fcn); +} + +static octave_value +make_fcn_handle (octave_builtin::fcn ff, const std::string& nm) +{ + octave_value fcn (new octave_builtin (ff, nm)); + + octave_value fcn_handle (new octave_fcn_handle (fcn, nm)); + + return fcn_handle; +} + +static octave_value +make_fcn_handle (const octave_value& fcn, const std::string& nm) +{ + octave_value retval; + + if (fcn.is_defined ()) + retval = octave_value (new octave_fcn_handle (fcn, nm)); + + return retval; +} + +inline octave_value_list +execute_ov (octave_value val, const octave_value_list& args, int nargout) +{ + std::list idx (1, args); + + std::string type ("("); + + return val.subsref (type, idx, nargout); +} + +static cdef_class +lookup_class (const std::string& name, bool error_if_not_found = true, + bool load_if_not_found = true) +{ + return cdef_manager::find_class (name, error_if_not_found, + load_if_not_found); +} + +static cdef_class +lookup_class (const cdef_class& cls) +{ + // FIXME: placeholder for the time being, the purpose + // is to centralized any class update activity here. + + return cls; +} + +static cdef_class +lookup_class (const octave_value& ov) +{ + if (ov.is_string()) + return lookup_class (ov.string_value ()); + else + { + cdef_class cls (to_cdef (ov)); + + if (! error_state) + return lookup_class (cls); + } + + return cdef_class (); +} + +static std::list +lookup_classes (const Cell& cls_list) +{ + std::list retval; + + for (int i = 0; i < cls_list.numel (); i++) + { + cdef_class c = lookup_class (cls_list(i)); + + if (! error_state) + retval.push_back (c); + else + { + retval.clear (); + break; + } + } + + return retval; +} + +static octave_value +to_ov (const std::list& class_list) +{ + Cell cls (class_list.size (), 1); + int i = 0; + + for (std::list::const_iterator it = class_list.begin (); + it != class_list.end (); ++it, ++i) + cls(i) = to_ov (*it); + + return octave_value (cls); +} + +static bool +is_superclass (const cdef_class& clsa, const cdef_class& clsb, + bool allow_equal = true, int max_depth = -1) +{ + bool retval = false; + + if (allow_equal && clsa == clsb) + retval = true; + else if (max_depth != 0) + { + Cell c = clsb.get ("SuperClasses").cell_value (); + + for (int i = 0; ! error_state && ! retval && i < c.numel (); i++) + { + cdef_class cls = lookup_class (c(i)); + + if (! error_state) + retval = is_superclass (clsa, cls, true, + max_depth < 0 ? max_depth : max_depth-1); + } + } + + return retval; +} + +inline bool +is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb) +{ return is_superclass (clsa, clsb, false); } + +inline bool +is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb) +{ return is_superclass (clsa, clsb, false, 1); } + +static octave_value_list +class_get_properties (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); + + retval(0) = cls.get_properties (); + } + + return retval; +} + +static cdef_class +get_class_context (std::string& name, bool& in_constructor) +{ + cdef_class cls; + + octave_function* fcn = octave_call_stack::current (); + + in_constructor = false; + + if (fcn && + (fcn->is_class_method () + || fcn->is_classdef_constructor () + || fcn->is_anonymous_function_of_class () + || (fcn->is_private_function () + && ! fcn->dispatch_class ().empty ()))) + { + cls = lookup_class (fcn->dispatch_class ()); + if (! error_state) + { + name = fcn->name (); + in_constructor = fcn->is_classdef_constructor (); + } + } + + return cls; +} + +inline cdef_class +get_class_context (void) +{ + std::string dummy_string; + bool dummy_bool; + + return get_class_context (dummy_string, dummy_bool); +} + +static bool +in_class_method (const cdef_class& cls) +{ + cdef_class ctx = get_class_context (); + + return (ctx.ok () && is_superclass (ctx, cls)); +} + +static bool +check_access (const cdef_class& cls, const octave_value& acc, + const std::string& meth_name = std::string (), + const std::string& prop_name = std::string (), + bool is_prop_set = false) +{ + if (acc.is_string ()) + { + std::string acc_s = acc.string_value (); + + if (acc_s == "public") + return true; + + cdef_class ctx = get_class_context (); + + // The access is private or protected, this requires a + // valid class context. + + if (! error_state && ctx.ok ()) + { + if (acc_s == "private") + return (ctx == cls); + else if (acc_s == "protected") + { + if (is_superclass (cls, ctx)) + // Calling a protected method in a superclass. + return true; + else if (is_strict_superclass (ctx, cls)) + { + // Calling a protected method or property in a derived class. + // This is only allowed if the context class knows about it + // and has access to it. + + if (! meth_name.empty ()) + { + cdef_method m = ctx.find_method (meth_name); + + if (m.ok ()) + return check_access (ctx, m.get ("Access"), meth_name); + + return false; + } + else if (! prop_name.empty ()) + { + cdef_property p = ctx.find_property (prop_name); + + if (p.ok ()) + { + octave_value p_access = p.get (is_prop_set ? + "SetAccess" : + "GetAccess"); + + return check_access (ctx, p_access, meth_name, + prop_name, is_prop_set); + } + + return false; + } + else + panic_impossible (); + } + + return false; + } + else + panic_impossible (); + } + } + else if (acc.is_cell ()) + { + Cell acc_c = acc.cell_value (); + + cdef_class ctx = get_class_context (); + + // At this point, a class context is always required. + + if (! error_state && ctx.ok ()) + { + if (ctx == cls) + return true; + + for (int i = 0; ! error_state && i < acc.numel (); i++) + { + cdef_class acc_cls (to_cdef (acc_c(i))); + + if (! error_state) + { + if (is_superclass (acc_cls, ctx)) + return true; + } + } + } + } + else + error ("invalid property/method access in class `%s'", + cls.get_name ().c_str ()); + + return false; +} + +static bool +is_dummy_method (const octave_value& fcn) +{ + bool retval = false; + + if (fcn.is_defined ()) + { + if (fcn.is_user_function ()) + { + octave_user_function *uf = fcn.user_function_value (true); + + if (! uf || ! uf->body ()) + retval = true; + } + } + else + retval = true; + + return retval; +} + +bool +is_method_executing (const octave_value& ov, const cdef_object& obj) +{ + octave_function* stack_fcn = octave_call_stack::current (); + + octave_function* method_fcn = ov.function_value (true); + + // Does the top of the call stack match our target function? + + if (stack_fcn && stack_fcn == method_fcn) + { + octave_user_function* uf = method_fcn->user_function_value (true); + + // We can only check the context object for user-function (not builtin), + // where we have access to the parameters (arguments and return values). + // That's ok as there's no need to call this function for builtin + // methods. + + if (uf) + { + // At this point, the method is executing, but we still need to + // check the context object for which the method is executing. For + // methods, it's the first argument of the function; for ctors, it + // is the first return value. + + tree_parameter_list* pl = uf->is_classdef_constructor () + ? uf->return_list () : uf->parameter_list (); + + if (pl && pl->size () > 0) + { + octave_value arg0 = pl->front ()->lvalue ().value (); + + if (arg0.is_defined () && arg0.type_name () == "object") + { + cdef_object arg0_obj = to_cdef (arg0); + + return obj.is (arg0_obj); + } + } + } + } + + return false; +} + +static octave_value_list +class_get_methods (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); + + retval(0) = cls.get_methods (); + } + + return retval; +} + +static octave_value_list +class_get_superclasses (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls (to_cdef (args(0))); + + Cell classes = cls.get ("SuperClasses").cell_value (); + + retval(0) = to_ov (lookup_classes (classes)); + } + + return retval; +} + +static octave_value_list +class_get_inferiorclasses (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls (to_cdef (args(0))); + + Cell classes = cls.get ("InferiorClasses").cell_value (); + + retval(0) = to_ov (lookup_classes (classes)); + } + + return retval; +} + +static octave_value_list +class_fromName (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1) + { + std::string name = args(0).string_value (); + + if (! error_state) + retval(0) = to_ov (lookup_class (name)); + else + error ("fromName: invalid class name, expected a string value"); + } + else + error ("fromName: invalid number of parameters"); + + return retval; +} + +static octave_value_list +class_fevalStatic (const octave_value_list& args, int nargout) +{ + octave_value_list retval; + + if (args.length () > 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); + + if (! error_state) + { + std::string meth_name = args(1).string_value (); + + if (! error_state) + { + cdef_method meth = cls.find_method (meth_name); + + if (meth.ok ()) + { + if (meth.is_static ()) + retval = meth.execute (args.splice (0, 2), nargout, + true, "fevalStatic"); + else + error ("fevalStatic: method `%s' is not static", + meth_name.c_str ()); + } + else + error ("fevalStatic: method not found: %s", + meth_name.c_str ()); + } + else + error ("fevalStatic: invalid method name, expected a string value"); + } + error ("fevalStatic: invalid object, expected a meta.class object"); + } + else + error ("fevalStatic: invalid arguments"); + + return retval; +} + +static octave_value_list +class_getConstant (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 2 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls = to_cdef (args(0)); + + if (! error_state) + { + std::string prop_name = args(1).string_value (); + + if (! error_state) + { + cdef_property prop = cls.find_property (prop_name); + + if (prop.ok ()) + { + if (prop.is_constant ()) + retval(0) = prop.get_value (true, "getConstant"); + else + error ("getConstant: property `%s' is not constant", + prop_name.c_str ()); + } + else + error ("getConstant: property not found: %s", + prop_name.c_str ()); + } + else + error ("getConstant: invalid property name, expected a string value"); + } + else + error ("getConstant: invalid object, expected a meta.class object"); + } + else + error ("getConstant: invalid arguments"); + + return retval; +} + +#define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \ +static octave_value_list \ +class_ ## OP (const octave_value_list& args, int /* nargout */) \ +{ \ + octave_value_list retval; \ +\ + if (args.length () == 2 \ + && args(0).type_name () == "object" && args(1).type_name () == "object" \ + && args(0).class_name () == "meta.class" && args(1).class_name () == "meta.class") \ + { \ + cdef_class clsa = to_cdef (args(0)); \ +\ + cdef_class clsb = to_cdef (args(1)); \ +\ + if (! error_state) \ + retval(0) = FUN (CLSA, CLSB); \ + else \ + error (#OP ": invalid objects, expected meta.class objects"); \ + } \ + else \ + error (#OP ": invalid arguments"); \ +\ + return retval; \ +} + +META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass) +META_CLASS_CMP (le, clsb, clsa, is_superclass) +META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass) +META_CLASS_CMP (ge, clsa, clsb, is_superclass) +META_CLASS_CMP (eq, clsa, clsb, operator==) +META_CLASS_CMP (ne, clsa, clsb, operator!=) + +octave_value_list +property_get_defaultvalue (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_property prop (to_cdef (args(0))); + + retval(0) = prop.get ("DefaultValue"); + + if (! retval(0).is_defined ()) + error_with_id ("Octave:class:NotDefaultDefined", + "no default value for property `%s'", + prop.get_name ().c_str ()); + } + + return retval; +} + +static octave_value_list +handle_delete (const octave_value_list& /* args */, int /* nargout */) +{ + octave_value_list retval; + + // FIXME: implement this + + return retval; +} + +static cdef_class +make_class (const std::string& name, + const std::list& super_list = std::list ()) +{ + cdef_class cls (name, super_list); + + cls.set_class (cdef_class::meta_class ()); + cls.put ("Abstract", false); + cls.put ("ConstructOnLoad", false); + cls.put ("ContainingPackage", Matrix ()); + cls.put ("Description", std::string ()); + cls.put ("DetailedDescription", std::string ()); + cls.put ("Events", Cell ()); + cls.put ("Hidden", false); + cls.put ("InferiorClasses", Cell ()); + cls.put ("Methods", Cell ()); + cls.put ("Properties", Cell ()); + cls.put ("Sealed", false); + + if (name == "handle") + { + cls.put ("HandleCompatible", true); + cls.mark_as_handle_class (); + } + else if (super_list.empty ()) + { + cls.put ("HandleCompatible", false); + } + else + { + bool all_handle_compatible = true; + bool has_handle_class = false; + + for (std::list::const_iterator it = super_list.begin (); + it != super_list.end (); ++it) + { + all_handle_compatible = all_handle_compatible && it->get ("HandleCompatible").bool_value (); + has_handle_class = has_handle_class || it->is_handle_class (); + } + + if (has_handle_class && ! all_handle_compatible) + ::error ("%s: cannot mix handle and non-HandleCompatible classes", + name.c_str ()); + else + { + cls.put ("HandleCompatible", all_handle_compatible); + if (has_handle_class) + cls.mark_as_handle_class (); + } + } + + if (error_state) + return cdef_class (); + + if (! name.empty ()) + cdef_manager::register_class (cls); + + return cls; +} + +static cdef_class +make_class (const std::string& name, const cdef_class& super) +{ + return make_class (name, std::list (1, super)); +} + +static cdef_class +make_meta_class (const std::string& name, const cdef_class& super) +{ + cdef_class cls = make_class (name, super); + + cls.put ("Sealed", true); + cls.mark_as_meta_class (); + + return cls; +} + +static cdef_property +make_property (const cdef_class& cls, const std::string& name, + const octave_value& get_method = Matrix (), + const std::string& get_access = "public", + const octave_value& set_method = Matrix (), + const std::string& set_access = "public") +{ + cdef_property prop (name); + + prop.set_class (cdef_class::meta_property ()); + prop.put ("Description", std::string ()); + prop.put ("DetailedDescription", std::string ()); + prop.put ("Abstract", false); + prop.put ("Constant", false); + prop.put ("GetAccess", get_access); + prop.put ("SetAccess", set_access); + prop.put ("Dependent", false); + prop.put ("Transient", false); + prop.put ("Hidden", false); + prop.put ("GetObservable", false); + prop.put ("SetObservable", false); + prop.put ("GetMethod", get_method); + prop.put ("SetMethod", set_method); + prop.put ("DefiningClass", to_ov (cls)); + prop.put ("DefaultValue", octave_value ()); + prop.put ("HasDefault", false); + + std::string class_name = cls.get_name (); + + if (! get_method.is_empty ()) + make_function_of_class (class_name, get_method); + if (! set_method.is_empty ()) + make_function_of_class (class_name, set_method); + + return prop; +} + +inline cdef_property +make_attribute (const cdef_class& cls, const std::string& name) +{ + return make_property (cls, name, Matrix (), "public", Matrix (), "private"); +} + +static cdef_method +make_method (const cdef_class& cls, const std::string& name, + const octave_value& fcn,const std::string& m_access = "public", + bool is_static = false) +{ + cdef_method meth (name); + + meth.set_class (cdef_class::meta_method ()); + meth.put ("Abstract", false); + meth.put ("Access", m_access); + meth.put ("DefiningClass", to_ov (cls)); + meth.put ("Description", std::string ()); + meth.put ("DetailedDescription", std::string ()); + meth.put ("Hidden", false); + meth.put ("Sealed", true); + meth.put ("Static", is_static); + + if (fcn.is_defined ()) + make_function_of_class (cls, fcn); + + meth.set_function (fcn); + + if (is_dummy_method (fcn)) + meth.mark_as_external (cls.get_name ()); + + return meth; +} + +inline cdef_method +make_method (const cdef_class& cls, const std::string& name, + octave_builtin::fcn ff, const std::string& m_access = "public", + bool is_static = false) +{ + octave_value fcn (new octave_builtin (ff, name)); + + return make_method (cls, name, fcn, m_access, is_static); +} + +static cdef_package +make_package (const std::string& nm, + const std::string& parent = std::string ()) +{ + cdef_package pack (nm); + + pack.set_class (cdef_class::meta_package ()); + if (parent.empty ()) + pack.put ("ContainingPackage", Matrix ()); + else + pack.put ("ContainingPackage", to_ov (cdef_manager::find_package (parent))); + + if (! nm.empty ()) + cdef_manager::register_package (pack); + + return pack; +} + +//---------------------------------------------------------------------------- + +DEFINE_OCTAVE_ALLOCATOR (octave_classdef); + +int octave_classdef::t_id (-1); + +const std::string octave_classdef::t_name ("object"); + +void +octave_classdef::register_type (void) +{ + t_id = octave_value_typeinfo::register_type + (octave_classdef::t_name, "", octave_value (new octave_classdef ())); +} + +octave_value_list +octave_classdef::subsref (const std::string& type, + const std::list& idx, + int nargout) +{ + size_t skip = 0; + octave_value_list retval; + + cdef_class cls = object.get_class (); + + if (! in_class_method (cls) && ! called_from_builtin ()) + { + cdef_method meth = cls.find_method ("subsref"); + + if (meth.ok ()) + { + octave_value_list args; + + args(1) = make_idx_args (type, idx, "subsref"); + + if (! error_state) + { + count++; + args(0) = octave_value (this); + + retval = meth.execute (args, nargout, true, "subsref"); + } + + return retval; + } + } + + // At this point, the default subsref mechanism must be used. + + retval = object.subsref (type, idx, nargout, skip, cdef_class ()); + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip) + retval = retval(0).next_subsref (nargout, type, idx, skip); + } + + return retval; +} + +octave_value +octave_classdef::subsref (const std::string& type, + const std::list& idx, + bool auto_add) +{ + size_t skip = 0; + octave_value_list retval; + + // This variant of subsref is used to create temporary values when doing + // assignment with multi-level indexing. AFAIK this is only used for internal + // purpose (not sure we should even implement this) and any overload subsref + // should not be called. + + retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add); + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip) + retval = retval(0).next_subsref (1, type, idx, skip); + } + + return retval.length () > 0 ? retval(0) : octave_value (); +} + +octave_value +octave_classdef::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + cdef_class cls = object.get_class (); + + if (! in_class_method (cls) && ! called_from_builtin ()) + { + cdef_method meth = cls.find_method ("subsasgn"); + + if (meth.ok ()) + { + octave_value_list args; + + args(1) = make_idx_args (type, idx, "subsasgn"); + + if (! error_state) + { + count++; + args(0) = octave_value (this); + args(2) = rhs; + + octave_value_list retlist; + + retlist = meth.execute (args, 1, true, "subsasgn"); + + if (! error_state) + { + if (retlist.length () > 0) + retval = retlist(0); + else + ::error ("overloaded method `subsasgn' did not return any value"); + } + } + } + } + + if (! error_state && ! retval.is_defined ()) + retval = object.subsasgn (type, idx, rhs); + + return retval; +} + +octave_value +octave_classdef::undef_subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + if (type.length () == 1 && type[0] == '(') + { + object = object.make_array (); + + if (! error_state) + return subsasgn (type, idx, rhs); + } + else + return octave_base_value::undef_subsasgn (type, idx, rhs); + + return octave_value (); +} + +void +octave_classdef::print (std::ostream& os, bool) +{ + if (! called_from_builtin ()) + { + cdef_method meth = object.get_class ().find_method ("disp"); + + if (meth.ok ()) + { + octave_value_list args; + + count++; + args(0) = octave_value (this); + + indent (os); + meth.execute (args, 0, true, "disp"); + + return; + } + } + + print_raw (os); +} + +void +octave_classdef::print_raw (std::ostream& os, bool) const +{ + indent (os); + os << ""; + newline (os); +} + +bool +octave_classdef::print_name_tag (std::ostream& os, + const std::string& name) const +{ + return octave_base_value::print_name_tag (os, name); +} + +void +octave_classdef::print_with_name (std::ostream& os, const std::string& name, + bool print_padding) +{ + cdef_method meth = object.get_class ().find_method ("display"); + + if (meth.ok ()) + { + octave_value_list args; + + count++; + args(0) = octave_value (this); + + string_vector arg_names (1); + + arg_names[0] = name; + args.stash_name_tags (arg_names); + + indent (os); + meth.execute (args, 0, true, "display"); + } + else + octave_base_value::print_with_name (os, name, print_padding); +} + +//---------------------------------------------------------------------------- + +class octave_classdef_meta : public octave_function +{ +public: + octave_classdef_meta (const cdef_meta_object& obj) + : object (obj) { } + + ~octave_classdef_meta (void) + { object.meta_release (); } + + octave_function* function_value (bool = false) { return this; } + + octave_value_list + subsref (const std::string& type, + const std::list& idx, + int nargout) + { return object.meta_subsref (type, idx, nargout); } + + octave_value + subsref (const std::string& type, + const std::list& idx) + { + octave_value_list retval; + + retval = subsref (type, idx, 1); + + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value_list + do_multi_index_op (int nargout, const octave_value_list& idx) + { + // Emulate ()-type meta subsref + + std::list l (1, idx); + std::string type ("("); + + return subsref (type, l, nargout); + } + + bool is_postfix_index_handled (char type) const + { return object.meta_is_postfix_index_handled (type); } + + bool + is_classdef_constructor (const std::string& cname = std::string ()) const + { + bool retval = false; + + if (object.is_class ()) + { + if (cname.empty ()) + retval = true; + else + { + cdef_class cls (object); + + if (cls.get_name () == cname) + retval = true; + } + } + + return retval; + } + +private: + cdef_meta_object object; +}; + +//---------------------------------------------------------------------------- + +class octave_classdef_superclass_ref : public octave_function +{ +public: + octave_classdef_superclass_ref (const octave_value_list& a) + : octave_function (), args (a) { } + + ~octave_classdef_superclass_ref (void) { } + + octave_function* function_value (bool = false) { return this; } + + octave_value_list + subsref (const std::string& type, + const std::list& idx, + int nargout) + { + size_t skip = 0; + octave_value_list retval; + + switch (type[0]) + { + case '(': + skip = 1; + retval = do_multi_index_op (type.length () > 1 ? 1 : nargout, + idx.front ()); + break; + default: + retval = do_multi_index_op (1, octave_value_list ()); + break; + } + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip + && retval.length () > 0) + retval = retval(0).next_subsref (nargout, type, idx, skip); + } + + return retval; + } + + octave_value + subsref (const std::string& type, + const std::list& idx) + { + octave_value_list retval; + + retval = subsref (type, idx, 1); + + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value_list + do_multi_index_op (int nargout, const octave_value_list& idx) + { + octave_value_list retval; + + std::string meth_name; + bool in_constructor; + cdef_class ctx; + + ctx = get_class_context (meth_name, in_constructor); + + if (! error_state && ctx.ok ()) + { + std::string mname = args(0).string_value (); + std::string cname = args(1).string_value (); + + cdef_class cls = lookup_class (cname); + + if (! error_state) + { + if (in_constructor) + { + if (is_direct_superclass (cls, ctx)) + { + if (is_constructed_object (mname)) + { + octave_value sym = symbol_table::varval (mname); + + cls.run_constructor (to_cdef_ref (sym), idx); + + retval(0) = sym; + } + else + ::error ("cannot call superclass constructor with " + "variable `%s'", mname.c_str ()); + } + else + ::error ("`%s' is not a direct superclass of `%s'", + cname.c_str (), ctx.get_name ().c_str ()); + } + else + { + if (mname == meth_name) + { + if (is_strict_superclass (cls, ctx)) + { + // I see 2 possible implementations here: + // 1) use cdef_object::subsref with a different class + // context; this avoids duplicating code, but + // assumes the object is always the first argument + // 2) lookup the method manually and call + // cdef_method::execute; this duplicates part of + // logic in cdef_object::subsref, but avoid the + // assumption of 1) + // Not being sure about the assumption of 1), I + // go with option 2) for the time being. + + cdef_method meth = cls.find_method (meth_name, false); + + if (meth.ok ()) + retval = meth.execute (idx, nargout, true, + meth_name); + else + ::error ("no method `%s' found in superclass `%s'", + meth_name.c_str (), cname.c_str ()); + } + else + ::error ("`%s' is not a superclass of `%s'", + cname.c_str (), ctx.get_name ().c_str ()); + } + else + ::error ("method name mismatch (`%s' != `%s')", + mname.c_str (), meth_name.c_str ()); + } + } + } + else if (! error_state) + ::error ("superclass calls can only occur in methods or constructors"); + + return retval; + } + +private: + bool is_constructed_object (const std::string nm) + { + octave_function *of = octave_call_stack::current (); + + if (of->is_classdef_constructor ()) + { + octave_user_function *uf = of->user_function_value (true); + + if (uf) + { + tree_parameter_list *ret_list = uf->return_list (); + + if (ret_list && ret_list->length () == 1) + return (ret_list->front ()->name () == nm); + } + } + + return false; + } + +private: + octave_value_list args; +}; + +//---------------------------------------------------------------------------- + +string_vector +cdef_object_rep::map_keys (void) const +{ + cdef_class cls = get_class (); + + if (cls.ok ()) + return cls.get_names (); + + return string_vector (); +} + +octave_value_list +cdef_object_scalar::subsref (const std::string& type, + const std::list& idx, + int nargout, size_t& skip, + const cdef_class& context, bool auto_add) +{ + skip = 0; + + cdef_class cls = (context.ok () ? context : get_class ()); + + octave_value_list retval; + + if (! cls.ok ()) + return retval; + + switch (type[0]) + { + case '.': + { + std::string name = (idx.front ())(0).string_value (); + + cdef_method meth = cls.find_method (name); + + if (meth.ok ()) + { + int _nargout = (type.length () > 2 ? 1 : nargout); + + octave_value_list args; + + skip = 1; + + if (type.length () > 1 && type[1] == '(') + { + std::list::const_iterator it = idx.begin (); + + args = *++it; + + skip++; + } + + if (meth.is_static ()) + retval = meth.execute (args, _nargout, true, "subsref"); + else + { + refcount++; + retval = meth.execute (cdef_object (this), args, _nargout, + true, "subsref"); + } + } + + if (skip == 0 && ! error_state) + { + cdef_property prop = cls.find_property (name); + + if (prop.ok ()) + { + if (prop.is_constant ()) + retval(0) = prop.get_value (true, "subsref"); + else + { + refcount++; + retval(0) = prop.get_value (cdef_object (this), + true, "subsref"); + } + + skip = 1; + } + else + error ("subsref: unknown method or property: %s", name.c_str ()); + } + break; + } + + case '(': + { + refcount++; + + cdef_object this_obj (this); + + Array arr (dim_vector (1, 1), this_obj); + + cdef_object new_obj = cdef_object (new cdef_object_array (arr)); + + new_obj.set_class (get_class ()); + + retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add); + } + break; + + default: + error ("object cannot be indexed with `%c'", type[0]); + break; + } + + return retval; +} + +octave_value +cdef_object_scalar::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + cdef_class cls = get_class (); + + switch (type[0]) + { + case '.': + { + std::string name = (idx.front ())(0).string_value (); + + if (! error_state) + { + cdef_property prop = cls.find_property (name); + + if (prop.ok ()) + { + if (prop.is_constant ()) + error ("subsasgn: cannot assign constant property: %s", + name.c_str ()); + else + { + refcount++; + + cdef_object obj (this); + + if (type.length () == 1) + { + prop.set_value (obj, rhs, true, "subsasgn"); + + if (! error_state) + retval = to_ov (obj); + } + else + { + octave_value val = + prop.get_value (obj, true, "subsasgn"); + + if (! error_state) + { + std::list args (idx); + + args.erase (args.begin ()); + + val = val.assign (octave_value::op_asn_eq, + type.substr (1), args, rhs); + + if (! error_state) + { + if (val.class_name () != "object" + || ! to_cdef (val).is_handle_object ()) + prop.set_value (obj, val, true, "subsasgn"); + + if (! error_state) + retval = to_ov (obj); + } + } + } + } + } + else + error ("subsasgn: unknown property: %s", name.c_str ()); + } + } + break; + + case '(': + { + refcount++; + + cdef_object this_obj (this); + + Array arr (dim_vector (1, 1), this_obj); + + cdef_object new_obj = cdef_object (new cdef_object_array (arr)); + + new_obj.set_class (get_class ()); + + octave_value tmp = new_obj.subsasgn (type, idx, rhs); + + if (! error_state) + retval = tmp; + } + break; + + default: + error ("subsasgn: object cannot be index with `%c'", type[0]); + break; + } + + return retval; +} + +void +cdef_object_scalar::mark_for_construction (const cdef_class& cls) +{ + std::string cls_name = cls.get_name (); + + Cell supcls = cls.get ("SuperClasses").cell_value (); + + if (! error_state) + { + std::list supcls_list = lookup_classes (supcls); + + if (! error_state) + ctor_list[cls] = supcls_list; + } +} + +octave_value_list +cdef_object_array::subsref (const std::string& type, + const std::list& idx, + int /* nargout */, size_t& skip, + const cdef_class& /* context */, bool auto_add) +{ + octave_value_list retval; + + skip = 1; + + switch (type[0]) + { + case '(': + { + const octave_value_list& ival = idx.front (); + bool is_scalar = true; + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + if (! error_state) + is_scalar = is_scalar && iv(i).is_scalar (); + } + + if (! error_state) + { + Array ires = array.index (iv, auto_add); + + if (! error_state) + { + // If resizing is enabled (auto_add = true), it's possible + // indexing was out-of-bound and the result array contains + // invalid cdef_objects. + + if (auto_add) + fill_empty_values (ires); + + if (is_scalar) + retval(0) = to_ov (ires(0)); + else + { + cdef_object array_obj (new cdef_object_array (ires)); + + array_obj.set_class (get_class ()); + + retval(0) = to_ov (array_obj); + } + } + } + } + break; + + case '.': + if (type.size () == 1 && idx.size () == 1) + { + Cell c (dims ()); + + octave_idx_type n = array.numel (); + + // dummy variables + size_t dummy_skip; + cdef_class dummy_cls; + + for (octave_idx_type i = 0; i < n; i++) + { + octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip, + dummy_cls); + + if (! error_state) + { + if (r.length () > 0) + c(i) = r(0); + } + else + break; + } + + if (! error_state) + retval(0) = octave_value (c, true); + + break; + } + // fall through "default" + + default: + ::error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } + + return retval; +} + +octave_value +cdef_object_array::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + case '(': + if (type.length () == 1) + { + cdef_object rhs_obj = to_cdef (rhs); + + if (! error_state) + { + if (rhs_obj.get_class () == get_class ()) + { + const octave_value_list& ival = idx.front (); + bool is_scalar = true; + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + if (! error_state) + is_scalar = is_scalar && iv(i).is_scalar (); + } + + if (! error_state) + { + Array rhs_mat; + + if (! rhs_obj.is_array ()) + { + rhs_mat = Array (dim_vector (1, 1)); + rhs_mat(0) = rhs_obj; + } + else + rhs_mat = rhs_obj.array_value (); + + if (! error_state) + { + octave_idx_type n = array.numel (); + + array.assign (iv, rhs_mat, cdef_object ()); + + if (! error_state) + { + if (array.numel () > n) + fill_empty_values (); + + if (! error_state) + { + refcount++; + retval = to_ov (cdef_object (this)); + } + } + } + } + } + else + ::error ("can't assign %s object into array of %s objects.", + rhs_obj.class_name ().c_str (), + class_name ().c_str ()); + } + } + else + { + const octave_value_list& ival = idx.front (); + + bool is_scalar = true; + + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + + if (! error_state) + { + is_scalar = is_scalar && iv(i).is_scalar (); + + if (! is_scalar) + error ("subsasgn: invalid indexing for object array " + "assignment, the index must reference a single " + "object in the array."); + } + } + + if (! error_state) + { + Array a = array.index (iv, true); + + if (a.numel () != 1) + error ("subsasgn: invalid indexing for object array " + "assignment"); + + if (! error_state) + { + cdef_object obj = a(0); + + int ignore_copies = 0; + + // If the object in 'a' is not valid, this means the index + // was out-of-bound and we need to create a new object. + + if (! obj.ok ()) + obj = get_class ().construct_object (octave_value_list ()); + else + // Optimize the subsasgn call to come. There are 2 copies + // that we can safely ignore: + // - 1 in "array" + // - 1 in "a" + ignore_copies = 2; + + std::list next_idx (idx); + + next_idx.erase (next_idx.begin ()); + + octave_value tmp = obj.subsasgn (type.substr (1), next_idx, + rhs, ignore_copies); + + if (! error_state) + { + cdef_object robj = to_cdef (tmp); + + if (robj.ok () + && ! robj.is_array () + && robj.get_class () == get_class ()) + { + // Small optimization, when dealing with handle + // objects, we don't need to re-assign the result + // of subsasgn back into the array. + + if (! robj.is (a(0))) + { + Array rhs_a (dim_vector (1, 1), + robj); + + octave_idx_type n = array.numel (); + + array.assign (iv, rhs_a); + + if (array.numel () > n) + fill_empty_values (); + } + + refcount++; + + retval = to_ov (cdef_object (this)); + } + else + error ("subasgn: invalid assignment into array of %s " + "objects", class_name ().c_str ()); + } + } + } + } + break; + + default: + ::error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } + + return retval; +} + +void +cdef_object_array::fill_empty_values (Array& arr) +{ + cdef_class cls = get_class (); + + if (! error_state) + { + cdef_object obj; + + int n = arr.numel (); + + for (int i = 0; ! error_state && i < n; i++) + { + if (! arr.xelem (i).ok ()) + { + if (! obj.ok ()) + { + obj = cls.construct_object (octave_value_list ()); + + if (! error_state) + arr.xelem (i) = obj; + } + else + arr.xelem (i) = obj.copy (); + } + } + } +} + +bool cdef_object_scalar::is_constructed_for (const cdef_class& cls) const +{ + return (is_constructed () + || ctor_list.find (cls) == ctor_list.end ()); +} + +bool cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const +{ + std::map< cdef_class, std::list >::const_iterator it; + + if (is_constructed ()) + return true; + else if ((it = ctor_list.find (cls)) == ctor_list.end () + || it->second.empty ()) + return true; + + for (std::list::const_iterator lit = it->second.begin (); + lit != it->second.end (); ++lit) + if (! is_constructed_for (*lit)) + return false; + + return true; +} + +handle_cdef_object::~handle_cdef_object (void) +{ + gnulib::printf ("deleting %s object (handle)\n", + get_class ().get_name ().c_str ()); +} + +value_cdef_object::~value_cdef_object (void) +{ + gnulib::printf ("deleting %s object (value)\n", + get_class ().get_name ().c_str ()); +} + +cdef_class::cdef_class_rep::cdef_class_rep (const std::list& superclasses) + : cdef_meta_object_rep (), member_count (0), handle_class (false), + object_count (0), meta (false) +{ + put ("SuperClasses", to_ov (superclasses)); + implicit_ctor_list = superclasses; +} + +cdef_method +cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local) +{ + method_iterator it = method_map.find (nm); + + if (it == method_map.end ()) + { + // FIXME: look into class directory + } + else + { + cdef_method& meth = it->second; + + // FIXME: check if method reload needed + + if (meth.ok ()) + return meth; + } + + if (! local) + { + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + { + cdef_method meth = cls.find_method (nm); + + if (meth.ok ()) + return meth; + } + } + } + + return cdef_method (); +} + +class ctor_analyzer : public tree_walker +{ +public: + ctor_analyzer (const std::string& ctor, const std::string& obj) + : tree_walker (), who (ctor), obj_name (obj) { } + + void visit_statement_list (tree_statement_list& t) + { + for (tree_statement_list::const_iterator it = t.begin (); + ! error_state && it != t.end (); ++it) + (*it)->accept (*this); + } + + void visit_statement (tree_statement& t) + { + if (t.is_expression ()) + t.expression ()->accept (*this); + } + + void visit_simple_assignment (tree_simple_assignment& t) + { + t.right_hand_side ()->accept (*this); + } + + void visit_multi_assignment (tree_multi_assignment& t) + { + t.right_hand_side ()->accept (*this); + } + + void visit_index_expression (tree_index_expression& t) + { + t.expression ()->accept (*this); + } + + void visit_funcall (tree_funcall& t) + { + octave_value fcn = t.function (); + + if (fcn.is_function ()) + { + octave_function *of = fcn.function_value (true); + + if (of) + { + if (of->name () == "__superclass_reference__") + { + octave_value_list args = t.arguments (); + + if (args(0).string_value () == obj_name) + { + std::string class_name = args(1).string_value (); + + cdef_class cls = lookup_class (class_name, false); + + if (cls.ok ()) + ctor_list.push_back (cls); + } + } + } + } + } + + std::list get_constructor_list (void) const + { return ctor_list; } + + // NO-OP + void visit_anon_fcn_handle (tree_anon_fcn_handle&) { } + void visit_argument_list (tree_argument_list&) { } + void visit_binary_expression (tree_binary_expression&) { } + void visit_break_command (tree_break_command&) { } + void visit_colon_expression (tree_colon_expression&) { } + void visit_continue_command (tree_continue_command&) { } + void visit_global_command (tree_global_command&) { } + void visit_persistent_command (tree_persistent_command&) { } + void visit_decl_elt (tree_decl_elt&) { } + void visit_decl_init_list (tree_decl_init_list&) { } + void visit_simple_for_command (tree_simple_for_command&) { } + void visit_complex_for_command (tree_complex_for_command&) { } + void visit_octave_user_script (octave_user_script&) { } + void visit_octave_user_function (octave_user_function&) { } + void visit_function_def (tree_function_def&) { } + void visit_identifier (tree_identifier&) { } + void visit_if_clause (tree_if_clause&) { } + void visit_if_command (tree_if_command&) { } + void visit_if_command_list (tree_if_command_list&) { } + void visit_switch_case (tree_switch_case&) { } + void visit_switch_case_list (tree_switch_case_list&) { } + void visit_switch_command (tree_switch_command&) { } + void visit_matrix (tree_matrix&) { } + void visit_cell (tree_cell&) { } + void visit_no_op_command (tree_no_op_command&) { } + void visit_constant (tree_constant&) { } + void visit_fcn_handle (tree_fcn_handle&) { } + void visit_parameter_list (tree_parameter_list&) { } + void visit_postfix_expression (tree_postfix_expression&) { } + void visit_prefix_expression (tree_prefix_expression&) { } + void visit_return_command (tree_return_command&) { } + void visit_return_list (tree_return_list&) { } + void visit_try_catch_command (tree_try_catch_command&) { } + void visit_unwind_protect_command (tree_unwind_protect_command&) { } + void visit_while_command (tree_while_command&) { } + void visit_do_until_command (tree_do_until_command&) { } + +private: + /* The name of the constructor being analyzed */ + std::string who; + + /* The name of the first output argument of the constructor */ + std::string obj_name; + + /* The list of superclass constructors that are explicitly called */ + std::list ctor_list; +}; + +void +cdef_class::cdef_class_rep::install_method (const cdef_method& meth) +{ + method_map[meth.get_name ()] = meth; + + member_count++; + + if (meth.is_constructor ()) + { + // Analyze the constructor code to determine what superclass + // constructors are called explicitly. + + octave_function *of = meth.get_function ().function_value (true); + + if (of) + { + octave_user_function *uf = of->user_function_value (true); + + if (uf) + { + tree_parameter_list *ret_list = uf->return_list (); + tree_statement_list *body = uf->body (); + + if (ret_list && ret_list->size () == 1) + { + std::string obj_name = ret_list->front ()->name (); + ctor_analyzer a (meth.get_name (), obj_name); + + body->accept (a); + if (! error_state) + { + std::list explicit_ctor_list + = a.get_constructor_list (); + + for (std::list::const_iterator it = explicit_ctor_list.begin (); + ! error_state && it != explicit_ctor_list.end (); ++it) + { + gnulib::printf ("explicit superclass constructor: %s\n", + it->get_name ().c_str ()); + implicit_ctor_list.remove (*it); + } + } + } + else + ::error ("%s: invalid constructor output arguments", + meth.get_name ().c_str ()); + } + } + } +} + +void +cdef_class::cdef_class_rep::load_all_methods (void) +{ + // FIXME: re-scan class directory +} + +Cell +cdef_class::cdef_class_rep::get_methods (void) +{ + std::map meths; + + find_methods (meths, false); + + if (! error_state) + { + Cell c (meths.size (), 1); + + int idx = 0; + + for (std::map::const_iterator it = meths.begin (); + it != meths.end (); ++it, ++idx) + c (idx, 0) = to_ov (it->second); + + return c; + } + + return Cell (); +} + +void +cdef_class::cdef_class_rep::find_methods (std::map& meths, + bool only_inherited) +{ + load_all_methods (); + + method_const_iterator it; + + for (it = method_map.begin (); it != method_map.end (); ++it) + { + if (! it->second.is_constructor ()) + { + std::string nm = it->second.get_name (); + + if (meths.find (nm) == meths.end ()) + { + if (only_inherited) + { + octave_value acc = it->second.get ("Access"); + + if (! acc.is_string () + || acc.string_value () == "private") + continue; + } + + meths[nm] = it->second; + } + } + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + cls.get_rep ()->find_methods (meths, true); + else + break; + } +} + +cdef_property +cdef_class::cdef_class_rep::find_property (const std::string& nm) +{ + property_iterator it = property_map.find (nm); + + if (it != property_map.end ()) + { + cdef_property& prop = it->second; + + if (prop.ok ()) + return prop; + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + { + cdef_property prop = cls.find_property (nm); + + if (prop.ok ()) + return prop; + } + } + + return cdef_property (); +} + +void +cdef_class::cdef_class_rep::install_property (const cdef_property& prop) +{ + property_map[prop.get_name ()] = prop; + + member_count++; +} + +Cell +cdef_class::cdef_class_rep::get_properties (void) +{ + std::map props; + + find_properties (props, false); + + if (! error_state) + { + Cell c (props.size (), 1); + + int idx = 0; + + for (std::map::const_iterator it = props.begin (); + it != props.end (); ++it, ++idx) + c (idx, 0) = to_ov (it->second); + + return c; + } + + return Cell (); +} + +void +cdef_class::cdef_class_rep::find_properties (std::map& props, + bool only_inherited) +{ + property_const_iterator it; + + for (it = property_map.begin (); ! error_state && it != property_map.end (); + ++it) + { + std::string nm = it->second.get_name (); + + if (props.find (nm) == props.end ()) + { + if (only_inherited) + { + octave_value acc = it->second.get ("GetAccess"); + + if (! acc.is_string () + || acc.string_value () == "private") + continue; + } + + props[nm] = it->second; + } + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; ! error_state && i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + cls.get_rep ()->find_properties (props, true); + else + break; + } +} + +void +cdef_class::cdef_class_rep::find_names (std::set& names, + bool all) +{ + load_all_methods (); + + for (method_const_iterator it = method_map.begin (); + ! error_state && it != method_map.end(); ++it) + { + if (! it->second.is_constructor ()) + { + std::string nm = it->second.get_name (); + + if (! all) + { + octave_value acc = it->second.get ("Access"); + + if (! acc.is_string() + || acc.string_value () != "public") + continue; + } + + names.insert (nm); + } + } + + for (property_const_iterator it = property_map.begin (); + ! error_state && it != property_map.end (); ++it) + { + std::string nm = it->second.get_name (); + + if (! all) + { + octave_value acc = it->second.get ("GetAccess"); + + if (! acc.is_string() + || acc.string_value () != "public") + continue; + } + + names.insert (nm); + } + + // Look into superclasses + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; ! error_state && i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (! error_state) + cls.get_rep ()->find_names (names, all); + else + break; + } +} + +string_vector +cdef_class::cdef_class_rep::get_names (void) +{ + std::set names; + + find_names (names, false); + + if (! error_state) + { + string_vector v (names.size ()); + + int idx = 0; + for (std::set::const_iterator it = names.begin (); + it != names.end (); ++it, ++idx) + v[idx] = *it; + + return v.sort (true); + } + + return string_vector (); +} + +void +cdef_class::cdef_class_rep::delete_object (cdef_object obj) +{ + method_iterator it = method_map.find ("delete"); + + if (it != method_map.end ()) + { + cdef_class cls = obj.get_class (); + + obj.set_class (wrap ()); + + it->second.execute (obj, octave_value_list (), 0, false); + + obj.set_class (cls); + } + + // FIXME: should we destroy corresponding properties here? + + // Call "delete" in super classes + + Cell super_classes = get ("SuperClasses").cell_value (); + + for (int i = 0; i < super_classes.numel (); i++) + { + cdef_class cls = lookup_class (super_classes(i)); + + if (!error_state) + cls.delete_object (obj); + } +} + +octave_value_list +cdef_class::cdef_class_rep::meta_subsref (const std::string& type, + const std::list& idx, + int nargout) +{ + size_t skip = 1; + + octave_value_list retval; + + switch (type[0]) + { + case '(': + // Constructor call + gnulib::printf ("constructor\n"); + retval(0) = construct (idx.front ()); + break; + + case '.': + // Static method, constant (or property?) + gnulib::printf ("static method/property\n"); + if (idx.front ().length () == 1) + { + std::string nm = idx.front ()(0).string_value (); + + if (! error_state) + { + cdef_method meth = find_method (nm); + + if (meth.ok ()) + { + if (meth.is_static ()) + { + octave_value_list args; + + if (type.length () > 1 && idx.size () > 1 + && type[1] == '(') + { + args = *(++(idx.begin ())); + skip++; + } + + retval = meth.execute (args, (type.length () > skip + ? 1 : nargout), true, + "meta.class"); + } + else + ::error ("method `%s' is not static", nm.c_str ()); + } + else + { + cdef_property prop = find_property (nm); + + if (prop.ok ()) + { + if (prop.is_constant ()) + retval(0) = prop.get_value (true, "meta.class"); + else + ::error ("property `%s' is not constant", + nm.c_str ()); + } + else + ::error ("no such method or property `%s'", nm.c_str ()); + } + } + else + ::error ("invalid meta.class indexing, expected a method or property name"); + } + else + ::error ("invalid meta.class indexing"); + break; + + default: + ::error ("invalid meta.class indexing"); + break; + } + + if (! error_state) + { + if (type.length () > skip && idx.size () > skip && ! retval.empty ()) + retval = retval(0).next_subsref (nargout, type, idx, skip); + } + + return retval; +} + +void +cdef_class::cdef_class_rep::meta_release (void) +{ + cdef_manager::unregister_class (wrap ()); +} + +void +cdef_class::cdef_class_rep::initialize_object (cdef_object& obj) +{ + // Populate the object with default property values + + std::list super_classes = lookup_classes (get ("SuperClasses").cell_value ()); + + if (! error_state) + { + for (std::list::iterator it = super_classes.begin (); + ! error_state && it != super_classes.end (); ++it) + it->initialize_object (obj); + + if (! error_state) + { + for (property_const_iterator it = property_map.begin (); + ! error_state && it != property_map.end (); ++it) + { + if (! it->second.get ("Dependent").bool_value ()) + { + octave_value pvalue = it->second.get ("DefaultValue"); + + if (pvalue.is_defined ()) + obj.put (it->first, pvalue); + else + obj.put (it->first, octave_value (Matrix ())); + } + } + + if (! error_state) + { + refcount++; + obj.mark_for_construction (cdef_class (this)); + } + } + } +} + +void +cdef_class::cdef_class_rep::run_constructor (cdef_object& obj, + const octave_value_list& args) +{ + octave_value_list empty_args; + + for (std::list::const_iterator it = implicit_ctor_list.begin (); + ! error_state && it != implicit_ctor_list.end (); ++it) + { + cdef_class supcls = lookup_class (*it); + + if (! error_state) + supcls.run_constructor (obj, empty_args); + } + + if (error_state) + return; + + std::string cls_name = get_name (); + std::string ctor_name = get_base_name (cls_name); + + cdef_method ctor = find_method (ctor_name); + + if (ctor.ok ()) + { + octave_value_list ctor_args (args); + octave_value_list ctor_retval; + + ctor_args.prepend (to_ov (obj)); + ctor_retval = ctor.execute (ctor_args, 1, true, "constructor"); + + if (! error_state) + { + if (ctor_retval.length () == 1) + obj = to_cdef (ctor_retval(0)); + else + { + ::error ("%s: invalid number of output arguments for classdef constructor", + ctor_name.c_str ()); + return; + } + } + } + + obj.mark_as_constructed (wrap ()); +} + +octave_value +cdef_class::cdef_class_rep::construct (const octave_value_list& args) +{ + cdef_object obj = construct_object (args); + + if (! error_state && obj.ok ()) + return to_ov (obj); + + return octave_value (); +} + +cdef_object +cdef_class::cdef_class_rep::construct_object (const octave_value_list& args) +{ + if (! is_abstract ()) + { + cdef_object obj; + + if (is_meta_class ()) + { + // This code path is only used to create empty meta objects + // as filler for the empty values within a meta object array. + + cdef_class this_cls = wrap (); + + static cdef_object empty_class; + + if (this_cls == cdef_class::meta_class ()) + { + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + obj = empty_class; + } + else if (this_cls == cdef_class::meta_property ()) + { + static cdef_property empty_property; + + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + if (! empty_property.ok ()) + empty_property = make_property (empty_class, ""); + obj = empty_property; + } + else if (this_cls == cdef_class::meta_method ()) + { + static cdef_method empty_method; + + if (! empty_class.ok ()) + empty_class = make_class ("", std::list ()); + if (! empty_method.ok ()) + empty_method = make_method (empty_class, "", octave_value ()); + obj = empty_method; + } + else if (this_cls == cdef_class::meta_package ()) + { + static cdef_package empty_package; + + if (! empty_package.ok ()) + empty_package = make_package (""); + obj = empty_package; + } + else + panic_impossible (); + + return obj; + } + else + { + if (is_handle_class ()) + obj = cdef_object (new handle_cdef_object ()); + else + obj = cdef_object (new value_cdef_object ()); + obj.set_class (wrap ()); + + initialize_object (obj); + + if (! error_state) + { + run_constructor (obj, args); + + if (! error_state) + return obj; + } + } + } + else + error ("cannot instantiate object for abstract class `%s'", + get_name ().c_str ()); + + return cdef_object (); +} + +static octave_value +compute_attribute_value (tree_classdef_attribute* t) +{ + if (t->expression ()) + { + if (t->expression ()->is_identifier ()) + { + std::string s = t->expression ()->name (); + + if (s == "public") + return std::string ("public"); + else if (s == "protected") + return std::string ("protected"); + else if (s == "private") + return std::string ("private"); + } + + return t->expression ()->rvalue1 (); + } + else + return octave_value (true); +} + +template +static std::string +attribute_value_to_string (T* t, octave_value v) +{ + if (v.is_string ()) + return v.string_value (); + else if (t->expression ()) + return t->expression ()->original_text (); + else + return std::string ("true"); +} + +cdef_class +cdef_class::make_meta_class (tree_classdef* t, bool is_at_folder) +{ + cdef_class retval; + std::string class_name, full_class_name; + + // Class creation + + class_name = full_class_name = t->ident ()->name (); + if (! t->package_name ().empty ()) + full_class_name = t->package_name () + "." + full_class_name; + gnulib::printf ("class: %s\n", full_class_name.c_str ()); + + std::list slist; + + if (t->superclass_list ()) + { + for (tree_classdef_superclass_list::iterator it = t->superclass_list ()->begin (); + ! error_state && it != t->superclass_list ()->end (); ++it) + { + std::string sclass_name = (*it)->class_name (); + + gnulib::printf ("superclass: %s\n", sclass_name.c_str ()); + + cdef_class sclass = lookup_class (sclass_name); + + if (! error_state) + { + if (! sclass.get ("Sealed").bool_value ()) + slist.push_back (sclass); + else + { + ::error ("`%s' cannot inherit from `%s', because it is sealed", + full_class_name.c_str (), sclass_name.c_str ()); + return retval; + } + } + else + return retval; + + } + } + + retval = ::make_class (full_class_name, slist); + + if (error_state) + return cdef_class (); + + // Package owning this class + + if (! t->package_name ().empty ()) + { + cdef_package pack = cdef_manager::find_package (t->package_name ()); + + if (! error_state && pack.ok ()) + retval.put ("ContainingPackage", to_ov (pack)); + } + + // Class attributes + + if (t->attribute_list ()) + { + for (tree_classdef_attribute_list::iterator it = t->attribute_list ()->begin (); + it != t->attribute_list ()->end (); ++it) + { + std::string aname = (*it)->ident ()->name (); + octave_value avalue = compute_attribute_value (*it); + + gnulib::printf ("class attribute: %s = %s\n", aname.c_str (), + attribute_value_to_string (*it, avalue).c_str ()); + retval.put (aname, avalue); + } + } + + tree_classdef_body* b = t->body (); + + if (b) + { + // Keep track of the get/set accessor methods. They will be used + // later on when creating properties. + + std::map get_methods; + std::map set_methods; + + // Method blocks + + std::list mb_list = b->methods_list (); + + for (tree_classdef_body::methods_list_iterator it = mb_list.begin (); + it != mb_list.end (); ++it) + { + std::map amap; + gnulib::printf ("method block\n"); + + // Method attributes + + if ((*it)->attribute_list ()) + { + for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin (); + ait != (*it)->attribute_list ()->end (); ++ait) + { + std::string aname = (*ait)->ident ()->name (); + octave_value avalue = compute_attribute_value (*ait); + + gnulib::printf ("method attribute: %s = %s\n", aname.c_str (), + attribute_value_to_string (*ait, avalue).c_str ()); + amap[aname] = avalue; + } + } + + // Methods + + if ((*it)->element_list ()) + { + for (tree_classdef_methods_list::iterator mit = (*it)->element_list ()->begin (); + mit != (*it)->element_list ()->end (); ++mit) + { + std::string mname = mit->function_value ()->name (); + std::string mprefix = mname.substr (0, 4); + + if (mprefix == "get.") + get_methods[mname.substr (4)] = + make_fcn_handle (*mit, full_class_name + ">" + mname); + else if (mprefix == "set.") + set_methods[mname.substr (4)] = + make_fcn_handle (*mit, full_class_name + ">" + mname); + else + { + cdef_method meth = make_method (retval, mname, *mit); + + gnulib::printf ("%s: %s\n", (mname == class_name ? "constructor" : "method"), + mname.c_str ()); + for (std::map::iterator ait = amap.begin (); + ait != amap.end (); ++ait) + meth.put (ait->first, ait->second); + + retval.install_method (meth); + } + } + } + } + + if (is_at_folder) + { + // Look for all external methods visible on octave path at the + // time of loading of the class. + // + // TODO: This is an "extension" to Matlab behavior, which only + // looks in the @-folder containing the original classdef + // file. However, this is easier to implement it that way at + // the moment. + + std::list external_methods = + load_path::methods (full_class_name); + + for (std::list::const_iterator it = external_methods.begin (); + it != external_methods.end (); ++it) + { + // TODO: should we issue a warning if the method is already + // defined in the classdef file? + + if (*it != class_name + && ! retval.find_method (*it, true).ok ()) + { + // Create a dummy method that is used until the actual + // method is loaded. + + octave_user_function *fcn = new octave_user_function (); + + fcn->stash_function_name (*it); + + cdef_method meth = make_method (retval, *it, + octave_value (fcn)); + + retval.install_method (meth); + } + } + } + + // Property blocks + + // FIXME: default property expression should be able to call static + // methods of the class being constructed. A restricted CLASSNAME + // symbol should be added to the scope before evaluating default + // value expressions. + + std::list pb_list = b->properties_list (); + + for (tree_classdef_body::properties_list_iterator it = pb_list.begin (); + it != pb_list.end (); ++it) + { + std::map amap; + gnulib::printf ("property block\n"); + + // Property attributes + + if ((*it)->attribute_list ()) + { + for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin (); + ait != (*it)->attribute_list ()->end (); ++ait) + { + std::string aname = (*ait)->ident ()->name (); + octave_value avalue = compute_attribute_value (*ait); + + gnulib::printf ("property attribute: %s = %s\n", aname.c_str (), + attribute_value_to_string (*ait, avalue).c_str ()); + if (aname == "Access") + { + amap["GetAccess"] = avalue; + amap["SetAccess"] = avalue; + } + else + amap[aname] = avalue; + } + } + + // Properties + + if ((*it)->element_list ()) + { + for (tree_classdef_property_list::iterator pit = (*it)->element_list ()->begin (); + pit != (*it)->element_list ()->end (); ++pit) + { + std::string prop_name = (*pit)->ident ()->name (); + + cdef_property prop = ::make_property (retval, prop_name); + + gnulib::printf ("property: %s\n", (*pit)->ident ()->name ().c_str ()); + if ((*pit)->expression ()) + { + octave_value pvalue = (*pit)->expression ()->rvalue1 (); + + gnulib::printf ("property default: %s\n", + attribute_value_to_string (*pit, pvalue).c_str ()); + prop.put ("DefaultValue", pvalue); + } + + // Install property attributes. This is done before assigning the + // property accessors so we can do validationby using cdef_property + // methods. + + for (std::map::iterator ait = amap.begin (); + ait != amap.end (); ++ait) + prop.put (ait->first, ait->second); + + // Install property access methods, if any. Remove the accessor + // methods from the temporary storage map, so we can detect which + // ones are invalid and do not correspond to a defined property. + + std::map::iterator git = + get_methods.find (prop_name); + + if (git != get_methods.end ()) + { + make_function_of_class (retval, git->second); + prop.put ("GetMethod", git->second); + get_methods.erase (git); + } + + std::map::iterator sit = + set_methods.find (prop_name); + + if (sit != set_methods.end ()) + { + make_function_of_class (retval, sit->second); + prop.put ("SetMethod", sit->second); + set_methods.erase (sit); + } + + retval.install_property (prop); + } + } + } + } + + return retval; +} + +octave_function* +cdef_class::get_method_function (const std::string& /* nm */) +{ + octave_classdef_meta* p = new octave_classdef_meta (*this); + + return p; +} + +octave_value +cdef_property::cdef_property_rep::get_value (const cdef_object& obj, + bool do_check_access, + const std::string& who) +{ + octave_value retval; + + if (do_check_access && ! check_get_access ()) + { + gripe_property_access (who, wrap (), false); + + return retval; + } + + if (! obj.is_constructed ()) + { + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! obj.is_partially_constructed_for (cls)) + { + ::error ("cannot reference properties of class `%s' for non-constructed object", + cls.get_name ().c_str ()); + return retval; + } + } + + octave_value get_fcn = get ("GetMethod"); + + // FIXME: should check whether we're already in get accessor method + + if (get_fcn.is_empty () || is_method_executing (get_fcn, obj)) + retval = obj.get (get ("Name").string_value ()); + else + { + octave_value_list args; + + args(0) = to_ov (obj); + + args = execute_ov (get_fcn, args, 1); + + if (! error_state) + retval = args(0); + } + + return retval; +} + +octave_value +cdef_property::cdef_property_rep::get_value (bool do_check_access, + const std::string& who) +{ + if (do_check_access && ! check_get_access ()) + { + gripe_property_access (who, wrap (), false); + + return octave_value (); + } + + return get ("DefaultValue"); +} + +bool +cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const +{ + // FIXME: implement + return false; +} + +void +cdef_property::cdef_property_rep::set_value (cdef_object& obj, + const octave_value& val, + bool do_check_access, + const std::string& who) +{ + if (do_check_access && ! check_set_access ()) + { + gripe_property_access (who, wrap (), true); + + return; + } + + if (! obj.is_constructed ()) + { + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! obj.is_partially_constructed_for (cls)) + { + ::error ("cannot reference properties of class `%s' for non-constructed object", + cls.get_name ().c_str ()); + return; + } + } + + octave_value set_fcn = get ("SetMethod"); + + if (set_fcn.is_empty () || is_method_executing (set_fcn, obj)) + obj.put (get ("Name").string_value (), val); + else + { + octave_value_list args; + + args(0) = to_ov (obj); + args(1) = val; + + args = execute_ov (set_fcn, args, 1); + + if (! error_state) + { + if (args.length() > 0) + { + cdef_object new_obj = to_cdef (args(0)); + + if (! error_state) + obj = new_obj; + } + } + } +} + +bool +cdef_property::cdef_property_rep::check_get_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! error_state) + return ::check_access (cls, get ("GetAccess"), std::string (), + get_name (), false); + + return false; +} + +bool +cdef_property::cdef_property_rep::check_set_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! error_state) + return ::check_access (cls, get ("SetAccess"), std::string (), + get_name (), true); + + return false; +} + +void +cdef_method::cdef_method_rep::check_method (void) +{ + if (is_external ()) + { + if (is_dummy_method (function)) + { + std::string name = get_name (); + std::string cls_name = dispatch_type; + std::string pack_name; + + size_t pos = cls_name.rfind ('.'); + + if (pos != std::string::npos) + { + pack_name = cls_name.substr (0, pos); + cls_name = cls_name.substr (pos + 1); + } + + std::string dir_name; + std::string file_name = load_path::find_method (cls_name, name, + dir_name, pack_name); + + if (! file_name.empty ()) + { + octave_function *fcn = load_fcn_from_file (file_name, dir_name, + dispatch_type, + pack_name); + + if (fcn) + { + function = octave_value (fcn); + + make_function_of_class (dispatch_type, function); + } + } + } + else + { + // FIXME: check out-of-date status + } + + if (is_dummy_method (function)) + ::error ("no definition found for method `%s' of class `%s'", + get_name ().c_str (), dispatch_type.c_str ()); + } +} + +octave_value_list +cdef_method::cdef_method_rep::execute (const octave_value_list& args, + int nargout, bool do_check_access, + const std::string& who) +{ + octave_value_list retval; + + if (do_check_access && ! check_access ()) + { + gripe_method_access (who, wrap ()); + + return retval; + } + + if (! get ("Abstract").bool_value ()) + { + check_method (); + + if (! error_state && function.is_defined ()) + { + retval = execute_ov (function, args, nargout); + } + } + else + error ("%s: cannot execute abstract method", + get ("Name").string_value ().c_str ()); + + return retval; +} + +octave_value_list +cdef_method::cdef_method_rep::execute (const cdef_object& obj, + const octave_value_list& args, + int nargout, bool do_check_access, + const std::string& who) +{ + octave_value_list retval; + + if (do_check_access && ! check_access ()) + { + gripe_method_access (who, wrap ()); + + return retval; + } + + if (! get ("Abstract").bool_value ()) + { + check_method (); + + if (! error_state && function.is_defined ()) + { + octave_value_list new_args; + + new_args.resize (args.length () + 1); + + new_args(0) = to_ov (obj); + for (int i = 0; i < args.length (); i++) + new_args(i+1) = args(i); + + retval = execute_ov (function, new_args, nargout); + } + } + else + error ("%s: cannot execute abstract method", + get ("Name").string_value ().c_str ()); + + return retval; +} + +bool +cdef_method::cdef_method_rep::is_constructor (void) const +{ + if (function.is_function()) + return function.function_value ()->is_classdef_constructor (); + + return false; +} + +bool +cdef_method::cdef_method_rep::check_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); + + if (! error_state) + return ::check_access (cls, get ("Access"), get_name ()); + + return false; +} + +octave_value_list +cdef_method::cdef_method_rep::meta_subsref + (const std::string& type, const std::list& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '(': + retval = execute (idx.front (), type.length () > 1 ? 1 : nargout, true); + break; + + default: + error ("invalid meta.method indexing"); + break; + } + + if (! error_state) + { + if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) + retval = retval(0).next_subsref (nargout, type, idx, 1); + } + + return retval; +} + +static cdef_package +lookup_package (const std::string& name) +{ + return cdef_manager::find_package (name); +} + +static octave_value_list +package_fromName (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; + + if (args.length () == 1) + { + std::string name = args(0).string_value (); + + if (! error_state) + retval(0) = to_ov (lookup_package (name)); + else + error ("fromName: invalid package name, expected a string value"); + } + else + error ("fromName: invalid number of parameters"); + + return retval; +} + +static octave_value_list +package_get_classes (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); + + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); + + retval(0) = pack.get_classes (); + } + + return retval; +} + +static octave_value_list +package_get_functions (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); + + if (args.length () == 0 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); + + retval(0) = pack.get_functions (); + } + + return retval; +} + +static octave_value_list +package_get_packages (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); + + if (args.length () == 0 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); + + retval(0) = pack.get_packages (); + } + + return retval; +} + +static octave_value_list +package_getAllPackages (const octave_value_list& /* args */, + int /* nargout */) +{ + std::map toplevel_packages; + + std::list names = load_path::get_all_package_names (); + + toplevel_packages["meta"] = cdef_manager::find_package ("meta", false, + false); + + for (std::list::const_iterator it = names.begin (); + it != names.end (); ++it) + toplevel_packages[*it] = cdef_manager::find_package (*it, false, true); + + Cell c (toplevel_packages.size (), 1); + + int i = 0; + + for (std::map::const_iterator it = toplevel_packages.begin (); + it != toplevel_packages.end (); ++it) + c(i++,0) = to_ov (it->second); + + return octave_value_list (octave_value (c)); +} + +void +cdef_package::cdef_package_rep::install_class (const cdef_class& cls, + const std::string& nm) +{ + class_map[nm] = cls; + + member_count++; +} + +void +cdef_package::cdef_package_rep::install_function (const octave_value& fcn, + const std::string& nm) +{ + function_map[nm] = fcn; +} + +void +cdef_package::cdef_package_rep::install_package (const cdef_package& pack, + const std::string& nm) +{ + package_map[nm] = pack; + + member_count++; +} + +template +Cell +map2Cell (const std::map& m) +{ + Cell retval (1, m.size ()); + int i = 0; + + for (typename std::map::const_iterator it = m.begin (); + it != m.end (); ++it, ++i) + { + retval(i) = to_ov (it->second); + } + + return retval; +} + +Cell +cdef_package::cdef_package_rep::get_classes (void) const +{ return map2Cell (class_map); } + +Cell +cdef_package::cdef_package_rep::get_functions (void) const +{ return map2Cell (function_map); } + +Cell +cdef_package::cdef_package_rep::get_packages (void) const +{ return map2Cell (package_map); } + +octave_value +cdef_package::cdef_package_rep::find (const std::string& nm) +{ + std::string symbol_name = get_name () + "." + nm; + + return symbol_table::find (symbol_name, octave_value_list (), true, false); +} + +octave_value_list +cdef_package::cdef_package_rep::meta_subsref + (const std::string& type, const std::list& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '.': + if (idx.front ().length () == 1) + { + std::string nm = idx.front ()(0).string_value (); + + if (! error_state) + { + gnulib::printf ("meta.package query: %s\n", nm.c_str ()); + + octave_value o = find (nm); + + if (o.is_defined ()) + { + if (o.is_function ()) + { + octave_function* fcn = o.function_value (); + + if (! error_state) + { + // NOTE: the case where the package query is the last + // part of this subsref index is handled in the parse + // tree, because there is some logic to handle magic + // "end" that makes it impossible to execute the + // function call at this stage. + + if (type.size () > 1 && + ! fcn->is_postfix_index_handled (type[1])) + { + octave_value_list tmp_args; + + retval = o.do_multi_index_op (nargout, + tmp_args); + } + else + retval(0) = o; + + if (type.size () > 1 && idx.size () > 1) + retval = retval(0).next_subsref (nargout, type, + idx, 1); + } + } + else if (type.size () > 1 && idx.size () > 1) + retval = o.next_subsref (nargout, type, idx, 1); + else + retval(0) = o; + } + else if (! error_state) + error ("member `%s' in package `%s' does not exist", + nm.c_str (), get_name ().c_str ()); + } + else + error ("invalid meta.package indexing, expected a symbol name"); + } + else + error ("invalid meta.package indexing"); + break; + + default: + error ("invalid meta.package indexing"); + break; + } + + return retval; +} + +void +cdef_package::cdef_package_rep::meta_release (void) +{ + // FIXME: Do we really want to unregister the package, as it + // could still be referenced by classes or sub-packages? + // If the package object is recreated later on, it won't + // match the one already referenced by those classes or + // sub-packages. + + //cdef_manager::unregister_package (wrap ()); +} + +cdef_class cdef_class::_meta_class = cdef_class (); +cdef_class cdef_class::_meta_property = cdef_class (); +cdef_class cdef_class::_meta_method = cdef_class (); +cdef_class cdef_class::_meta_package = cdef_class (); + +cdef_package cdef_package::_meta = cdef_package (); + +void +install_classdef (void) +{ + octave_classdef::register_type (); + + /* bootstrap */ + cdef_class handle = make_class ("handle"); + cdef_class meta_class = cdef_class::_meta_class = make_meta_class ("meta.class", handle); + handle.set_class (meta_class); + meta_class.set_class (meta_class); + + /* meta classes */ + cdef_class meta_property = cdef_class::_meta_property = make_meta_class ("meta.property", handle); + cdef_class meta_method = cdef_class::_meta_method = make_meta_class ("meta.method", handle); + cdef_class meta_package = cdef_class::_meta_package = make_meta_class ("meta.package", handle); + + cdef_class meta_event = make_meta_class ("meta.event", handle); + cdef_class meta_dynproperty = make_meta_class ("meta.dynamicproperty", handle); + + /* meta.class properties */ + meta_class.install_property (make_attribute (meta_class, "Abstract")); + meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad")); + meta_class.install_property (make_property (meta_class, "ContainingPackage")); + meta_class.install_property (make_property (meta_class, "Description")); + meta_class.install_property (make_property (meta_class, "DetailedDescription")); + meta_class.install_property (make_property (meta_class, "Events")); + meta_class.install_property (make_attribute (meta_class, "HandleCompatible")); + meta_class.install_property (make_attribute (meta_class, "Hidden")); + meta_class.install_property + (make_property (meta_class, "InferiorClasses", + make_fcn_handle (class_get_inferiorclasses, "meta.class>get.InferiorClasses"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "Methods", + make_fcn_handle (class_get_methods, "meta.class>get.Methods"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "MethodList", + make_fcn_handle (class_get_methods, "meta.class>get.MethodList"), + "public", Matrix (), "private")); + meta_class.install_property (make_attribute (meta_class, "Name")); + meta_class.install_property + (make_property (meta_class, "Properties", + make_fcn_handle (class_get_properties, "meta.class>get.Properties"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "PropertyList", + make_fcn_handle (class_get_properties, "meta.class>get.PropertyList"), + "public", Matrix (), "private")); + meta_class.install_property (make_attribute (meta_class, "Sealed")); + meta_class.install_property + (make_property (meta_class, "SuperClasses", + make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClasses"), + "public", Matrix (), "private")); + meta_class.install_property + (make_property (meta_class, "SuperClassList", + make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClassList"), + "public", Matrix (), "private")); + /* meta.class methods */ + meta_class.install_method (make_method (meta_class, "fromName", class_fromName, + "public", true)); + meta_class.install_method (make_method (meta_class, "fevalStatic", class_fevalStatic, + "public", false)); + meta_class.install_method (make_method (meta_class, "getConstant", class_getConstant, + "public", false)); + meta_class.install_method (make_method (meta_class, "eq", class_eq)); + meta_class.install_method (make_method (meta_class, "ne", class_ne)); + meta_class.install_method (make_method (meta_class, "lt", class_lt)); + meta_class.install_method (make_method (meta_class, "le", class_le)); + meta_class.install_method (make_method (meta_class, "gt", class_gt)); + meta_class.install_method (make_method (meta_class, "ge", class_ge)); + + /* meta.method properties */ + meta_method.install_property (make_attribute (meta_method, "Abstract")); + meta_method.install_property (make_attribute (meta_method, "Access")); + meta_method.install_property (make_attribute (meta_method, "DefiningClass")); + meta_method.install_property (make_attribute (meta_method, "Description")); + meta_method.install_property (make_attribute (meta_method, "DetailedDescription")); + meta_method.install_property (make_attribute (meta_method, "Hidden")); + meta_method.install_property (make_attribute (meta_method, "Name")); + meta_method.install_property (make_attribute (meta_method, "Sealed")); + meta_method.install_property (make_attribute (meta_method, "Static")); + + /* meta.property properties */ + meta_property.install_property (make_attribute (meta_property, "Name")); + meta_property.install_property (make_attribute (meta_property, "Description")); + meta_property.install_property (make_attribute (meta_property, "DetailedDescription")); + meta_property.install_property (make_attribute (meta_property, "Abstract")); + meta_property.install_property (make_attribute (meta_property, "Constant")); + meta_property.install_property (make_attribute (meta_property, "GetAccess")); + meta_property.install_property (make_attribute (meta_property, "SetAccess")); + meta_property.install_property (make_attribute (meta_property, "Dependent")); + meta_property.install_property (make_attribute (meta_property, "Transient")); + meta_property.install_property (make_attribute (meta_property, "Hidden")); + meta_property.install_property (make_attribute (meta_property, "GetObservable")); + meta_property.install_property (make_attribute (meta_property, "SetObservable")); + meta_property.install_property (make_attribute (meta_property, "GetMethod")); + meta_property.install_property (make_attribute (meta_property, "SetMethod")); + meta_property.install_property (make_attribute (meta_property, "DefiningClass")); + meta_property.install_property + (make_property (meta_property, "DefaultValue", + make_fcn_handle (property_get_defaultvalue, "meta.property>get.DefaultValue"), + "public", Matrix (), "private")); + meta_property.install_property (make_attribute (meta_property, "HasDefault")); + /* meta.property events */ + // FIXME: add events + + /* handle methods */ + handle.install_method (make_method (handle, "delete", handle_delete)); + + /* meta.package properties */ + meta_package.install_property (make_attribute (meta_package, "Name")); + meta_package.install_property (make_property (meta_package, "ContainingPackage")); + meta_package.install_property + (make_property (meta_package, "ClassList", + make_fcn_handle (package_get_classes, "meta.package>get.ClassList"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "Classes", + make_fcn_handle (package_get_classes, "meta.package>get.Classes"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "FunctionList", + make_fcn_handle (package_get_functions, "meta.package>get.FunctionList"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "Functions", + make_fcn_handle (package_get_functions, "meta.package>get.Functions"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "PackageList", + make_fcn_handle (package_get_packages, "meta.package>get.PackageList"), + "public", Matrix (), "private")); + meta_package.install_property + (make_property (meta_package, "Packages", + make_fcn_handle (package_get_packages, "meta.package>get.Packages"), + "public", Matrix (), "private")); + meta_package.install_method (make_method (meta_package, "fromName", package_fromName, + "public", true)); + meta_package.install_method (make_method (meta_package, "getAllPackages", package_getAllPackages, + "public", true)); + + /* create "meta" package */ + cdef_package package_meta = cdef_package::_meta = make_package ("meta"); + package_meta.install_class (meta_class, "class"); + package_meta.install_class (meta_property, "property"); + package_meta.install_class (meta_method, "method"); + package_meta.install_class (meta_package, "package"); + package_meta.install_class (meta_event, "event"); + package_meta.install_class (meta_dynproperty, "dynproperty"); + + /* install built-in classes into the symbol table */ + symbol_table::install_built_in_function + ("meta.class", octave_value (meta_class.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.method", octave_value (meta_method.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.property", octave_value (meta_property.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.package", octave_value (meta_package.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.event", octave_value (meta_event.get_constructor_function ())); + symbol_table::install_built_in_function + ("meta.dynproperty", octave_value (meta_dynproperty.get_constructor_function ())); +} + +//---------------------------------------------------------------------------- + +cdef_manager* cdef_manager::instance = 0; + +void +cdef_manager::create_instance (void) +{ + instance = new cdef_manager (); + + if (instance) + singleton_cleanup_list::add (cleanup_instance); +} + +cdef_class +cdef_manager::do_find_class (const std::string& name, + bool error_if_not_found, bool load_if_not_found) +{ + std::map::iterator it = all_classes.find (name); + + if (it == all_classes.end ()) + { + if (load_if_not_found) + { + octave_value ov_cls; + + size_t pos = name.rfind ('.'); + + if (pos == std::string::npos) + ov_cls = symbol_table::find (name); + else + { + std::string pack_name = name.substr (0, pos); + + cdef_package pack = do_find_package (pack_name, false, true); + + if (pack.ok ()) + ov_cls = pack.find (name.substr (pos+1)); + } + + if (ov_cls.is_defined ()) + it = all_classes.find (name); + } + } + + if (it == all_classes.end ()) + { + if (error_if_not_found) + error ("class not found: %s", name.c_str ()); + } + else + { + cdef_class cls = it->second; + + if (! cls.is_builtin ()) + cls = lookup_class (cls); + + if (cls.ok ()) + return cls; + else + all_classes.erase (it); + } + + return cdef_class (); +} + +octave_function* +cdef_manager::do_find_method_symbol (const std::string& method_name, + const std::string& class_name) +{ + octave_function *retval = 0; + + cdef_class cls = find_class (class_name, false, false); + + if (cls.ok ()) + { + cdef_method meth = cls.find_method (method_name); + + if (meth.ok ()) + retval = new octave_classdef_meta (meth); + } + + return retval; +} + +cdef_package +cdef_manager::do_find_package (const std::string& name, + bool error_if_not_found, + bool load_if_not_found) +{ + cdef_package retval; + + std::map::const_iterator it + = all_packages.find (name); + + if (it != all_packages.end ()) + { + retval = it->second; + + if (! retval.ok ()) + error ("invalid package `%s'", name.c_str ()); + } + else + { + if (load_if_not_found && load_path::find_package (name)) + { + size_t pos = name.find ('.'); + + if (pos == std::string::npos) + retval = make_package (name, std::string ()); + else + { + std::string parent_name = name.substr (0, pos); + + retval = make_package (name, parent_name); + } + } + else if (error_if_not_found) + error ("unknown package `%s'", name.c_str ()); + } + + return retval; +} + +octave_function* +cdef_manager::do_find_package_symbol (const std::string& pack_name) +{ + octave_function* retval = 0; + + cdef_package pack = find_package (pack_name, false); + + if (pack.ok ()) + retval = new octave_classdef_meta (pack); + + return retval; +} + +//---------------------------------------------------------------------------- + +DEFUN (__meta_get_package__, args, , "") +{ + octave_value retval; + + if (args.length () == 1) + { + std::string cname = args(0).string_value (); + + if (! error_state) + retval = to_ov (lookup_package (cname)); + else + error ("invalid package name, expected a string value"); + } + else + print_usage (); + + return retval; +} + +DEFUN (__superclass_reference__, args, /* nargout */, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __superclass_reference__ ()\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + return octave_value (new octave_classdef_superclass_ref (args)); +} + +DEFUN (__meta_class_query__, args, /* nargout */, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __meta_class_query__ ()\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value retval; + + std::cerr << "__meta_class_query__ (" + << args(0).string_value () << ")" + << std::endl; + + if (args.length () == 1) + { + std::string cls = args(0).string_value (); + + if (! error_state) + retval = to_ov (lookup_class (cls)); + else + error ("invalid class name, expected a string value"); + } + else + print_usage (); + + return retval; +} + +DEFUN (metaclass, args, /* nargout */, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} metaclass (obj)\n\ +Returns the meta.class object corresponding to the class of @var{obj}.\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + { + cdef_object obj = to_cdef (args(0)); + + if (! error_state) + retval = to_ov (obj.get_class ()); + else + print_usage (); + } + else + print_usage (); + + return retval; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-classdef.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/octave-value/ov-classdef.h Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,1666 @@ +/* + +Copyright (C) 2012-2013 Michael Goffioul + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if !defined (octave_classdef_h) +#define octave_classdef_h 1 + +#include +#include +#include + +#include "oct-map.h" +#include "oct-refcount.h" +#include "ov-base.h" +#include "symtab.h" + +class cdef_object; +class cdef_class; +class cdef_property; +class cdef_method; +class cdef_package; + +class tree_classdef; + +// This is mainly a boostrap class to declare the expected interface. +// The actual base class is cdef_class_base, which is declared after +// cdef_object, such that it can contain cdef_object objects. +class +cdef_object_rep +{ +public: + friend class cdef_object; + +public: + cdef_object_rep (void) : refcount (1) { } + + virtual ~cdef_object_rep (void) { } + + virtual cdef_class get_class (void) const; + + virtual void set_class (const cdef_class&) + { gripe_invalid_object ("set_class"); } + + virtual cdef_object_rep* clone (void) const + { + gripe_invalid_object ("clone"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* empty_clone (void) const + { + gripe_invalid_object ("empty_clone"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* copy (void) const + { + gripe_invalid_object ("copy"); + return new cdef_object_rep (); + } + + virtual cdef_object_rep* make_array (void) const + { + gripe_invalid_object ("make_array"); + return new cdef_object_rep (); + } + + virtual bool is_array (void) const { return false; } + + virtual bool is_value_object (void) const { return false; } + + virtual bool is_handle_object (void) const { return false; } + + virtual bool is_meta_object (void) const { return false; } + + virtual Array array_value (void) const + { + gripe_invalid_object ("array_value"); + return Array (); + } + + virtual void put (const std::string&, const octave_value&) + { gripe_invalid_object ("put"); } + + virtual octave_value get (const std::string&) const + { + gripe_invalid_object ("get"); + return octave_value (); + } + + virtual octave_value_list + subsref (const std::string&, const std::list&, + int, size_t&, const cdef_class&, bool) + { + gripe_invalid_object ("subsref"); + return octave_value_list (); + } + + virtual octave_value + subsasgn (const std::string&, const std::list&, + const octave_value&) + { + gripe_invalid_object ("subsasgn"); + return octave_value (); + } + + virtual string_vector map_keys(void) const; + + virtual bool is_valid (void) const { return false; } + + std::string class_name (void) const; + + virtual void mark_for_construction (const cdef_class&) + { gripe_invalid_object ("mark_for_construction"); } + + virtual bool is_constructed_for (const cdef_class&) const + { + gripe_invalid_object ("is_constructed_for"); + return false; + } + + virtual bool is_partially_constructed_for (const cdef_class&) const + { + gripe_invalid_object ("is_partially_constructed_for"); + return false; + } + + virtual void mark_as_constructed (void) + { gripe_invalid_object ("mark_as_constructed"); } + + virtual void mark_as_constructed (const cdef_class&) + { gripe_invalid_object ("mark_as_constructed"); } + + virtual bool is_constructed (void) const + { + gripe_invalid_object ("is_constructed"); + return false; + } + + virtual octave_idx_type static_count (void) const { return 0; } + + virtual void destroy (void) { delete this; } + + void release (void) + { + if (--refcount == static_count ()) + destroy (); + } + + virtual dim_vector dims (void) const { return dim_vector (); } + +protected: + /* reference count */ + octave_refcount refcount; + +protected: + /* Restricted copying */ + cdef_object_rep (const cdef_object_rep&) + : refcount (1) { } + +private: + /* No assignment */ + cdef_object_rep& operator = (const cdef_object_rep& ); + + void gripe_invalid_object (const char *who) const + { error ("%s: invalid object", who); } +}; + +class +cdef_object +{ +public: + /* FIXME: use a null object */ + cdef_object (void) + : rep (new cdef_object_rep ()) { } + + cdef_object (const cdef_object& obj) + : rep (obj.rep) + { + rep->refcount++; + } + + cdef_object (cdef_object_rep *r) + : rep (r) { } + + virtual ~cdef_object (void) + { rep->release (); } + + cdef_object& operator = (const cdef_object& obj) + { + if (rep != obj.rep) + { + rep->release (); + + rep = obj.rep; + rep->refcount++; + } + + return *this; + } + + cdef_class get_class (void) const; + + void set_class (const cdef_class& cls) { rep->set_class (cls); } + + std::string class_name (void) const + { return rep->class_name (); } + + cdef_object clone (void) const + { return cdef_object (rep->clone ()); } + + cdef_object empty_clone (void) const + { return cdef_object (rep->empty_clone ()); } + + dim_vector dims (void) const { return rep->dims (); } + + cdef_object make_array (void) const + { return cdef_object (rep->make_array ()); } + + cdef_object copy (void) const + { return cdef_object (rep->copy ()); } + + bool is_array (void) const { return rep->is_array (); } + + bool is_value_object (void) const { return rep->is_value_object (); } + + bool is_handle_object (void) const { return rep->is_handle_object (); } + + bool is_meta_object (void) const { return rep->is_meta_object (); } + + Array array_value (void) const { return rep->array_value (); } + + void put (const std::string& pname, const octave_value& val) + { rep->put (pname, val); } + + octave_value get (const std::string& pname) const + { return rep->get (pname); } + + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, size_t& skip, const cdef_class& context, + bool auto_add = false) + { return rep->subsref (type, idx, nargout, skip, context, auto_add); } + + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs, int ignore_copies = 0) + { + make_unique (ignore_copies); + return rep->subsasgn (type, idx, rhs); + } + + string_vector map_keys (void) const { return rep->map_keys (); } + + const cdef_object_rep* get_rep (void) const { return rep; } + + bool ok (void) const { return rep->is_valid (); } + + void mark_for_construction (const cdef_class& cls) + { rep->mark_for_construction (cls); } + + bool is_constructed (void) const { return rep->is_constructed (); } + + bool is_constructed_for (const cdef_class& cls) const + { return rep->is_constructed_for (cls); } + + bool is_partially_constructed_for (const cdef_class& cls) const + { return rep->is_partially_constructed_for (cls); } + + void mark_as_constructed (void) { rep->mark_as_constructed (); } + + void mark_as_constructed (const cdef_class& cls) + { rep->mark_as_constructed (cls); } + + bool is (const cdef_object& obj) const { return rep == obj.rep; } + +protected: + cdef_object_rep* get_rep (void) { return rep; } + + void make_unique (int ignore_copies) + { + if (rep->refcount > ignore_copies + 1) + *this = clone (); + } + +private: + cdef_object_rep *rep; +}; + +class +cdef_object_base : public cdef_object_rep +{ +public: + cdef_object_base (void) + : cdef_object_rep (), klass () + { + register_object (); + } + + ~cdef_object_base (void) { unregister_object (); } + + cdef_class get_class (void) const; + + void set_class (const cdef_class& cls); + + cdef_object_rep* empty_clone (void) const + { return new cdef_object_base (*this); } + + cdef_object_rep* make_array (void) const; + +protected: + // Restricted copying! + cdef_object_base (const cdef_object_base& obj) + : cdef_object_rep (obj), klass (obj.klass) + { + register_object (); + } + +private: + void register_object (void); + + void unregister_object (void); + +private: + // The class of the object + cdef_object klass; + +private: + // No assignment! + cdef_object_base& operator = (const cdef_object_base&); +}; + +class +cdef_object_array : public cdef_object_base +{ +public: + cdef_object_array (void) : cdef_object_base () { } + + cdef_object_array (const Array& a) + : cdef_object_base (), array (a) { } + + cdef_object_rep* clone (void) const + { return new cdef_object_array (*this); } + + dim_vector dims (void) const { return array.dims (); } + + bool is_valid (void) const { return true; } + + bool is_array (void) const { return true; } + + Array array_value (void) const { return array; } + + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, size_t& skip, const cdef_class& context, + bool auto_add); + + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs); + +private: + Array array; + +private: + void fill_empty_values (void) { fill_empty_values (array); } + + void fill_empty_values (Array& arr); + + // Private copying! + cdef_object_array (const cdef_object_array& obj) + : cdef_object_base (obj), array (obj.array) { } + + // No assignment! + cdef_object_array& operator = (const cdef_object_array&); +}; + +class +cdef_object_scalar : public cdef_object_base +{ +public: + cdef_object_scalar (void) : cdef_object_base () { } + + ~cdef_object_scalar (void) { } + + dim_vector dims (void) const { return dim_vector (1, 1); } + + void put (const std::string& pname, const octave_value& val) + { map.assign (pname, val); } + + octave_value get (const std::string& pname) const + { + Cell val = map.contents (pname); + + if (val.numel () > 0) + return val(0, 0); + else + { + error ("get: unknown slot: %s", pname.c_str ()); + return octave_value (); + } + } + + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, size_t& skip, const cdef_class& context, + bool auto_add); + + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs); + + void mark_for_construction (const cdef_class&); + + bool is_constructed_for (const cdef_class& cls) const; + + bool is_partially_constructed_for (const cdef_class& cls) const; + + void mark_as_constructed (void) { ctor_list.clear (); } + + void mark_as_constructed (const cdef_class& cls) { ctor_list.erase (cls); } + + bool is_constructed (void) const { return ctor_list.empty (); } + +protected: + // Object property values + octave_scalar_map map; + + // Internal/temporary structure used during object construction + std::map< cdef_class, std::list > ctor_list; + +protected: + // Restricted object copying! + cdef_object_scalar (const cdef_object_scalar& obj) + : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { } + +private: + // No assignment! + cdef_object_scalar& operator = (const cdef_object_scalar&); +}; + +class +handle_cdef_object : public cdef_object_scalar +{ +public: + handle_cdef_object (void) + : cdef_object_scalar () { } + + ~handle_cdef_object (void); + + cdef_object_rep* clone (void) const + { + handle_cdef_object *obj = const_cast (this); + obj->refcount++; + return obj; + } + + cdef_object_rep* copy (void) const + { return new handle_cdef_object (*this); } + + bool is_valid (void) const { return true; } + + bool is_handle_object (void) const { return true; } + +protected: + // Restricted copying! + handle_cdef_object (const handle_cdef_object& obj) + : cdef_object_scalar (obj) { } + +private: + // No assignment + handle_cdef_object& operator = (const handle_cdef_object&); +}; + +class +value_cdef_object : public cdef_object_scalar +{ +public: + value_cdef_object (void) + : cdef_object_scalar () { } + + ~value_cdef_object (void); + + cdef_object_rep* clone (void) const + { return new value_cdef_object (*this); } + + cdef_object_rep* copy (void) const { return clone (); } + + bool is_valid (void) const { return true; } + + bool is_value_object (void) const { return true; } + +private: + // Private copying! + value_cdef_object (const value_cdef_object& obj) + : cdef_object_scalar (obj) { } + + // No assignment! + value_cdef_object& operator = (const value_cdef_object&); +}; + +class +cdef_meta_object_rep : public handle_cdef_object +{ +public: + cdef_meta_object_rep (void) + : handle_cdef_object () { } + + ~cdef_meta_object_rep (void) { } + + cdef_object_rep* copy (void) const + { return new cdef_meta_object_rep (*this); } + + bool is_meta_object (void) const { return true; } + + virtual bool is_class (void) const { return false; } + + virtual bool is_property (void) const { return false; } + + virtual bool is_method (void) const { return false; } + + virtual bool is_package (void) const { return false; } + + virtual octave_value_list + meta_subsref (const std::string& /* type */, + const std::list& /* idx */, + int /* nargout */) + { + ::error ("subsref: invalid meta object"); + return octave_value_list (); + } + + virtual void meta_release (void) { } + + virtual bool meta_is_postfix_index_handled (char /* type */) const + { return false; } + +protected: + // Restricted copying! + cdef_meta_object_rep (const cdef_meta_object_rep& obj) + : handle_cdef_object (obj) { } + +private: + // No assignment! + cdef_meta_object_rep& operator = (const cdef_meta_object_rep&); +}; + +class +cdef_meta_object : public cdef_object +{ +public: + cdef_meta_object (void) + : cdef_object () { } + + cdef_meta_object (const cdef_meta_object& obj) + : cdef_object (obj) { } + + cdef_meta_object (cdef_meta_object_rep *r) + : cdef_object (r) { } + + // Object consistency is checked in sub-classes. + cdef_meta_object (const cdef_object& obj) + : cdef_object (obj) { } + + ~cdef_meta_object (void) { } + + bool is_class (void) const { return get_rep ()->is_class (); } + + bool is_property (void) const { return get_rep ()->is_property (); } + + bool is_method (void) const { return get_rep ()->is_method (); } + + bool is_package (void) const { return get_rep ()->is_package (); } + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout) + { return get_rep ()->meta_subsref (type, idx, nargout); } + + void meta_release (void) { get_rep ()->meta_release (); } + + bool meta_is_postfix_index_handled (char type) const + { return get_rep ()->meta_is_postfix_index_handled (type); } + +private: + cdef_meta_object_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_meta_object_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } +}; + +class +cdef_class : public cdef_meta_object +{ +private: + + class + cdef_class_rep : public cdef_meta_object_rep + { + public: + cdef_class_rep (void) + : cdef_meta_object_rep (), member_count (0), handle_class (false), + object_count (0), meta (false) { } + + cdef_class_rep (const std::list& superclasses); + + cdef_object_rep* copy (void) const { return new cdef_class_rep (*this); } + + bool is_class (void) const { return true; } + + std::string get_name (void) const + { return get ("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_abstract (void) const { return get ("Abstract").bool_value (); } + + bool is_sealed (void) const { return get ("Sealed").bool_value (); } + + cdef_method find_method (const std::string& nm, bool local = false); + + void install_method (const cdef_method& meth); + + Cell get_methods (void); + + cdef_property find_property (const std::string& nm); + + void install_property (const cdef_property& prop); + + Cell get_properties (void); + + string_vector get_names (void); + + void set_directory (const std::string& dir) { directory = dir; } + + std::string get_directory (void) const { return directory; } + + void delete_object (cdef_object obj); + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + void meta_release (void); + + bool meta_is_postfix_index_handled (char type) const + { return (type == '(' || type == '.'); } + + octave_value construct (const octave_value_list& args); + + cdef_object construct_object (const octave_value_list& args); + + void initialize_object (cdef_object& obj); + + void run_constructor (cdef_object& obj, const octave_value_list& args); + + void mark_as_handle_class (void) { handle_class = true; } + + bool is_handle_class (void) const { return handle_class; } + + void register_object (void) { object_count++; } + + void unregister_object (void) { object_count--; } + + octave_idx_type static_count (void) const { return member_count; } + + void destroy (void) + { + if (member_count) + { + refcount++; + cdef_class lock (this); + + member_count = 0; + method_map.clear (); + property_map.clear (); + } + else + delete this; + } + + void mark_as_meta_class (void) { meta = true; } + + bool is_meta_class (void) const { return meta; } + + private: + void load_all_methods (void); + + void find_names (std::set& names, bool all); + + void find_properties (std::map& props, + bool only_inherited); + + void find_methods (std::map& meths, + bool only_inherited); + + cdef_class wrap (void) + { + refcount++; + return cdef_class (this); + } + + private: + // The @-directory were this class is loaded from. + // (not used yet) + std::string directory; + + // The methods defined by this class. + std::map method_map; + + // The properties defined by this class. + std::map property_map; + + // The number of members in this class (methods, properties...) + octave_idx_type member_count; + + // TRUE if this class is a handle class. A class is a handle + // class when the abstract "handle" class is one of its superclasses. + bool handle_class; + + // The list of super-class constructors that are called implicitly by the + // the classdef engine when creating an object. These constructors are not + // called explicitly by the class constructor. + std::list implicit_ctor_list; + + // The number of objects of this class. + octave_refcount object_count; + + // TRUE if this class is a built-in meta class. + bool meta; + + // Utility iterator typedef's. + typedef std::map::iterator method_iterator; + typedef std::map::const_iterator method_const_iterator; + typedef std::map::iterator property_iterator; + typedef std::map::const_iterator property_const_iterator; + + private: + cdef_class_rep (const cdef_class_rep& c) + : cdef_meta_object_rep (c), directory (c.directory), + method_map (c.method_map), property_map (c.property_map), + member_count (c.member_count), handle_class (c.handle_class), + implicit_ctor_list (c.implicit_ctor_list), + object_count (c.object_count), meta (c.meta) { } + }; + +public: + // Create and invalid class object + cdef_class (void) + : cdef_meta_object () { } + + cdef_class (const std::string& nm, + const std::list& superclasses) + : cdef_meta_object (new cdef_class_rep (superclasses)) + { get_rep ()->set_name (nm); } + + cdef_class (const cdef_class& cls) + : cdef_meta_object (cls) { } + + cdef_class (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_class ()) + error ("internal error: invalid assignment from %s to meta.class object", + class_name ().c_str ()); + } + + cdef_class& operator = (const cdef_class& cls) + { + cdef_object::operator= (cls); + + return *this; + } + + cdef_method find_method (const std::string& nm, bool local = false); + + void install_method (const cdef_method& meth) + { get_rep ()->install_method (meth); } + + Cell get_methods (void) { return get_rep ()->get_methods (); } + + cdef_property find_property (const std::string& nm); + + void install_property (const cdef_property& prop) + { get_rep ()->install_property (prop); } + + Cell get_properties (void) { return get_rep ()->get_properties (); } + + string_vector get_names (void) { return get_rep ()->get_names (); } + + bool is_abstract (void) const { return get_rep ()->is_abstract (); } + + bool is_sealed (void) const { return get_rep ()->is_sealed (); } + + void set_directory (const std::string& dir) + { get_rep ()->set_directory (dir); } + + std::string get_directory (void) const + { return get_rep ()->get_directory (); } + + std::string get_name (void) const + { return get_rep ()->get_name (); } + + bool is_builtin (void) const + { return get_directory ().empty (); } + + void delete_object (cdef_object obj) + { get_rep ()->delete_object (obj); } + + static cdef_class make_meta_class (tree_classdef* t, + bool is_at_folder = false); + + octave_function* get_method_function (const std::string& nm); + + octave_function* get_constructor_function (void) + { return get_method_function (get_name ()); } + + octave_value construct (const octave_value_list& args) + { return get_rep ()->construct (args); } + + cdef_object construct_object (const octave_value_list& args) + { return get_rep ()->construct_object (args); } + + void initialize_object (cdef_object& obj) + { get_rep ()->initialize_object (obj); } + + void run_constructor (cdef_object& obj, const octave_value_list& args) + { get_rep ()->run_constructor (obj, args); } + + void mark_as_handle_class (void) + { get_rep ()->mark_as_handle_class (); } + + bool is_handle_class (void) const + { return get_rep ()->is_handle_class (); } + + void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); } + + bool is_meta_class (void) const { return get_rep ()->is_meta_class (); } + + static const cdef_class& meta_class (void) { return _meta_class; } + static const cdef_class& meta_property (void) { return _meta_property; } + static const cdef_class& meta_method (void) { return _meta_method; } + static const cdef_class& meta_package (void) { return _meta_package; } + + void register_object (void) { get_rep ()->register_object (); } + + void unregister_object (void) { get_rep ()->unregister_object (); } + +private: + cdef_class_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_class_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } + + friend bool operator == (const cdef_class&, const cdef_class&); + friend bool operator != (const cdef_class&, const cdef_class&); + friend bool operator < (const cdef_class&, const cdef_class&); + +private: + static cdef_class _meta_class; + static cdef_class _meta_property; + static cdef_class _meta_method; + static cdef_class _meta_package; + + friend void install_classdef (void); +}; + +inline bool +operator == (const cdef_class& clsa, const cdef_class& clsb) +// FIXME: is this really the right way to check class equality? +{ return (clsa.get_rep () == clsb.get_rep ()); } + +inline bool +operator != (const cdef_class& clsa, const cdef_class& clsb) +{ return ! (clsa == clsb); } + +// This is only to be able to use cdef_class as map keys. +inline bool +operator < (const cdef_class& clsa, const cdef_class& clsb) +{ return clsa.get_rep () < clsb.get_rep (); } + +class +cdef_property : public cdef_meta_object +{ + friend class cdef_class; + +private: + + class + cdef_property_rep : public cdef_meta_object_rep + { + public: + cdef_property_rep (void) + : cdef_meta_object_rep () { } + + cdef_object_rep* copy (void) const { return new cdef_property_rep (*this); } + + bool is_property (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_constant (void) const { return get("Constant").bool_value (); } + + octave_value get_value (bool do_check_access = true, + const std::string& who = std::string ()); + + octave_value get_value (const cdef_object& obj, + bool do_check_access = true, + const std::string& who = std::string ()); + + void set_value (cdef_object& obj, const octave_value& val, + bool do_check_access = true, + const std::string& who = std::string ()); + + bool check_get_access (void) const; + + bool check_set_access (void) const; + + private: + cdef_property_rep (const cdef_property_rep& p) + : cdef_meta_object_rep (p) { } + + bool is_recursive_set (const cdef_object& obj) const; + + cdef_property wrap (void) + { + refcount++; + return cdef_property (this); + } + }; + +public: + cdef_property (void) : cdef_meta_object () { } + + cdef_property (const std::string& nm) + : cdef_meta_object (new cdef_property_rep ()) + { get_rep ()->set_name (nm); } + + cdef_property (const cdef_property& prop) + : cdef_meta_object (prop) { } + + cdef_property (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_property ()) + error ("internal error: invalid assignment from %s to meta.property object", + class_name ().c_str ()); + } + + cdef_property& operator = (const cdef_property& prop) + { + cdef_object::operator= (prop); + + return *this; + } + + octave_value get_value (const cdef_object& obj, bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->get_value (obj, do_check_access, who); } + + octave_value get_value (bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->get_value (do_check_access, who); } + + void set_value (cdef_object& obj, const octave_value& val, + bool do_check_access = true, + const std::string& who = std::string ()) + { get_rep ()->set_value (obj, val, do_check_access, who); } + + bool check_get_access (void) const + { return get_rep ()->check_get_access (); } + + bool check_set_access (void) const + { return get_rep ()->check_set_access (); } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + bool is_constant (void) const { return get_rep ()->is_constant (); } + +private: + cdef_property_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_property_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } +}; + +class +cdef_method : public cdef_meta_object +{ + friend class cdef_class; + +private: + + class + cdef_method_rep : public cdef_meta_object_rep + { + public: + cdef_method_rep (void) + : cdef_meta_object_rep (), function (), dispatch_type () + { } + + cdef_object_rep* copy (void) const { return new cdef_method_rep(*this); } + + bool is_method (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + bool is_static (void) const { return get("Static").bool_value (); } + + octave_value get_function (void) const { return function; } + + void set_function (const octave_value& fcn) { function = fcn; } + + bool check_access (void) const; + + bool is_external (void) const { return ! dispatch_type.empty (); } + + void mark_as_external (const std::string& dtype) + { dispatch_type = dtype; } + + octave_value_list execute (const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()); + + octave_value_list execute (const cdef_object& obj, + const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()); + + bool is_constructor (void) const; + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + bool meta_is_postfix_index_handled (char type) const + { return (type == '(' || type == '.'); } + + private: + cdef_method_rep (const cdef_method_rep& m) + : cdef_meta_object_rep (m), function (m.function), + dispatch_type (m.dispatch_type) + { } + + void check_method (void); + + cdef_method wrap (void) + { + refcount++; + return cdef_method (this); + } + + private: + octave_value function; + + // When non-empty, the method is externally defined and this member + // is used to cache the dispatch type to look for the method. + std::string dispatch_type; + }; + +public: + cdef_method (void) : cdef_meta_object () { } + + cdef_method (const std::string& nm) + : cdef_meta_object (new cdef_method_rep ()) + { get_rep ()->set_name (nm); } + + cdef_method (const cdef_method& meth) + : cdef_meta_object (meth) { } + + cdef_method (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_method ()) + error ("internal error: invalid assignment from %s to meta.method object", + class_name ().c_str ()); + } + + cdef_method& operator = (const cdef_method& meth) + { + cdef_object::operator= (meth); + + return *this; + } + + /* normal invokation */ + octave_value_list execute (const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->execute (args, nargout, do_check_access, who); } + + /* dot-invokation: object is pushed as 1st argument */ + octave_value_list execute (const cdef_object& obj, + const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = std::string ()) + { return get_rep ()->execute (obj, args, nargout, do_check_access, who); } + + bool check_access (void) const { return get_rep ()->check_access (); } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + bool is_static (void) const { return get_rep ()->is_static (); } + + void set_function (const octave_value& fcn) + { get_rep ()->set_function (fcn); } + + octave_value get_function (void) const + { return get_rep ()->get_function (); } + + bool is_constructor (void) const + { return get_rep ()->is_constructor (); } + + bool is_external (void) const { return get_rep ()->is_external (); } + + void mark_as_external (const std::string& dtype) + { get_rep ()->mark_as_external (dtype); } + +private: + cdef_method_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_method_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } +}; + +inline cdef_class +cdef_object_rep::get_class (void) const +{ + gripe_invalid_object ("get_class"); + return cdef_class (); +} + +inline std::string +cdef_object_rep::class_name (void) const +{ return get_class ().get_name (); } + +inline cdef_class +cdef_object::get_class (void) const +{ return rep->get_class (); } + +inline cdef_class +cdef_object_base::get_class (void) const +{ return cdef_class (klass); } + +inline void +cdef_object_base::set_class (const cdef_class& cls) +{ + if ((klass.ok () && cls.ok () && cls != get_class ()) + || (klass.ok () && ! cls.ok ()) + || (! klass.ok () && cls.ok ())) + { + unregister_object (); + klass = cls; + register_object (); + } +} + +inline void +cdef_object_base::register_object (void) +{ + if (klass.ok ()) + { + cdef_class cls (get_class ()); + + if (! error_state && cls.ok ()) + cls.register_object (); + } +} + +inline void +cdef_object_base::unregister_object (void) +{ + if (klass.ok ()) + { + cdef_class cls (get_class ()); + + if (! error_state && cls.ok ()) + cls.unregister_object (); + } +} + +inline cdef_object_rep* +cdef_object_base::make_array (void) const +{ + cdef_object_rep* r = new cdef_object_array (); + + r->set_class (get_class ()); + + return r; +} + +inline cdef_method +cdef_class::find_method (const std::string& nm, bool local) +{ return get_rep ()->find_method (nm, local); } + +inline cdef_property +cdef_class::find_property (const std::string& nm) +{ return get_rep ()->find_property (nm); } + +class +cdef_package : public cdef_meta_object +{ + friend class cdef_class; + +private: + + class + cdef_package_rep : public cdef_meta_object_rep + { + public: + cdef_package_rep (void) + : cdef_meta_object_rep (), member_count (0) { } + + ~cdef_package_rep (void) { } + + cdef_object_rep* copy (void) const { return new cdef_package_rep (*this); } + + bool is_package (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + void install_class (const cdef_class& cls, const std::string& nm); + + void install_function (const octave_value& fcn, const std::string& nm); + + void install_package (const cdef_package& pack, const std::string& nm); + + Cell get_classes (void) const; + + Cell get_functions (void) const; + + Cell get_packages (void) const; + + octave_idx_type static_count (void) const { return member_count; } + + void destroy (void) + { + if (member_count) + { + refcount++; + cdef_package lock (this); + + member_count = 0; + class_map.clear (); + package_map.clear (); + } + else + delete this; + } + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + void meta_release (void); + + bool meta_is_postfix_index_handled (char type) const + { return (type == '.'); } + + octave_value find (const std::string& nm); + + private: + std::string full_name; + std::map class_map; + std::map function_map; + std::map package_map; + + // The number of registered members in this package (classes, packages). + // This only accounts for the members that back-reference to this package. + octave_idx_type member_count; + + typedef std::map::iterator class_iterator; + typedef std::map::const_iterator class_const_iterator; + typedef std::map::iterator function_iterator; + typedef std::map::const_iterator function_const_iterator; + typedef std::map::iterator package_iterator; + typedef std::map::const_iterator package_const_iterator; + + private: + cdef_package_rep (const cdef_package_rep& p) + : cdef_meta_object_rep (p), full_name (p.full_name), + class_map (p.class_map), function_map (p.function_map), + package_map (p.package_map), member_count (p.member_count) + { } + + cdef_package wrap (void) + { + refcount++; + return cdef_package (this); + } + }; + +public: + cdef_package (void) : cdef_meta_object () { } + + cdef_package (const std::string& nm) + : cdef_meta_object (new cdef_package_rep ()) + { get_rep ()->set_name (nm); } + + cdef_package (const cdef_package& pack) + : cdef_meta_object (pack) { } + + cdef_package (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_package ()) + error ("internal error: invalid assignment from %s to meta.package object", + class_name ().c_str ()); + } + + cdef_package& operator = (const cdef_package& pack) + { + cdef_object::operator= (pack); + + return *this; + } + + void install_class (const cdef_class& cls, const std::string& nm) + { get_rep ()->install_class (cls, nm); } + + void install_function (const octave_value& fcn, const std::string& nm) + { get_rep ()->install_function (fcn, nm); } + + void install_package (const cdef_package& pack, const std::string& nm) + { get_rep ()->install_package (pack, nm); } + + Cell get_classes (void) const + { return get_rep ()->get_classes (); } + + Cell get_functions (void) const + { return get_rep ()->get_functions (); } + + Cell get_packages (void) const + { return get_rep ()->get_packages (); } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + octave_value find (const std::string& nm) { return get_rep ()->find (nm); } + + static const cdef_package& meta (void) { return _meta; } + +private: + cdef_package_rep* get_rep (void) + { return dynamic_cast (cdef_object::get_rep ()); } + + const cdef_package_rep* get_rep (void) const + { return dynamic_cast (cdef_object::get_rep ()); } + +private: + static cdef_package _meta; + + friend void install_classdef (void); +}; + +class +octave_classdef : public octave_base_value +{ +public: + octave_classdef (void) + : octave_base_value (), object () { } + + octave_classdef (const cdef_object& obj) + : octave_base_value (), object (obj) { } + + octave_classdef (const octave_classdef& obj) + : octave_base_value (obj), object (obj.object) { } + + octave_base_value* clone (void) const + { return new octave_classdef (object.clone ()); } + + octave_base_value* empty_clone (void) const + { return new octave_classdef (object.empty_clone ()); } + + cdef_object get_object (void) const { return object; } + + cdef_object& get_object_ref (void) { return object; } + + bool is_defined (void) const { return true; } + + bool is_map (void) const { return true; } + + bool is_object (void) const { return true; } + + void print (std::ostream& os, bool pr_as_read_syntax = false); + + void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + + bool print_name_tag (std::ostream& os, const std::string& name) const; + + void print_with_name (std::ostream& os, const std::string& name, + bool print_padding = true); + + octave_value_list subsref (const std::string& type, + const std::list& idx, + int nargout); + + octave_value subsref (const std::string& type, + const std::list& idx) + { + octave_value_list retval = subsref (type, idx, 1); + return (retval.length () > 0 ? retval(0) : octave_value ()); + } + + octave_value subsref (const std::string& type, + const std::list& idx, + bool auto_add); + + octave_value subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs); + + octave_value + undef_subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs); + + string_vector map_keys (void) const { return object.map_keys (); } + + dim_vector dims (void) const { return object.dims (); } + +private: + cdef_object object; + +private: + DECLARE_OCTAVE_ALLOCATOR + +public: + int type_id (void) const { return t_id; } + std::string type_name (void) const { return t_name; } + std::string class_name (void) const { return object.class_name (); } + + static int static_type_id (void) { return t_id; } + static std::string static_type_name (void) { return t_name; } + static std::string static_class_name (void) { return ""; } + static void register_type (void); + +private: + static int t_id; + + static const std::string t_name; +}; + +inline octave_value +to_ov (const cdef_object& obj) +{ + if (obj.ok ()) + return octave_value (new octave_classdef (obj)); + else + return octave_value (Matrix ()); +} + +inline octave_value +to_ov (const octave_value& ov) +{ return ov; } + +inline cdef_object +to_cdef (const octave_value& val) +{ + if (val.type_name () == "object") + return dynamic_cast (val.internal_rep ())->get_object (); + else + { + error ("cannot convert `%s' into `object'", val.type_name().c_str ()); + return cdef_object (); + } +} + +inline cdef_object& +to_cdef_ref (const octave_value& val) +{ + static cdef_object empty; + + if (val.type_name () == "object") + return dynamic_cast (val.internal_rep ())->get_object_ref (); + else + { + error ("cannot convert `%s' into `object'", val.type_name().c_str ()); + return empty; + } +} + +inline cdef_object +to_cdef (const cdef_object& obj) +{ return obj; } + +OCTINTERP_API void install_classdef (void); + +class +cdef_manager +{ +public: + + static cdef_class find_class (const std::string& name, + bool error_if_not_found = true, + bool load_if_not_found = true) + { + if (instance_ok ()) + return instance->do_find_class (name, error_if_not_found, + load_if_not_found); + + return cdef_class (); + } + + static octave_function* find_method_symbol (const std::string& method_name, + const std::string& class_name) + { + if (instance_ok ()) + return instance->do_find_method_symbol (method_name, class_name); + + return 0; + } + + static cdef_package find_package (const std::string& name, + bool error_if_not_found = true, + bool load_if_not_found = true) + { + if (instance_ok ()) + return instance->do_find_package (name, error_if_not_found, + load_if_not_found); + + return cdef_package (); + } + + static octave_function* find_package_symbol (const std::string& pack_name) + { + if (instance_ok ()) + return instance->do_find_package_symbol (pack_name); + + return 0; + } + + static void register_class (const cdef_class& cls) + { + if (instance_ok ()) + instance->do_register_class (cls); + } + + static void unregister_class (const cdef_class& cls) + { + if (instance_ok ()) + instance->do_unregister_class (cls); + } + + static void register_package (const cdef_package& pkg) + { + if (instance_ok ()) + instance->do_register_package (pkg); + } + + static void unregister_package (const cdef_package& pkg) + { + if (instance_ok ()) + instance->do_unregister_package (pkg); + } + +private: + + cdef_manager (void) { } + + cdef_manager (const cdef_manager&); + + cdef_manager& operator = (const cdef_manager&); + + ~cdef_manager (void) { } + + static void create_instance (void); + + static bool instance_ok (void) + { + bool retval = true; + + if (! instance) + create_instance (); + + if (! instance) + { + ::error ("unable to create cdef_manager!"); + + retval = false; + } + + return retval; + } + + static void cleanup_instance (void) + { + delete instance; + + instance = 0; + } + + cdef_class do_find_class (const std::string& name, bool error_if_not_found, + bool load_if_not_found); + + octave_function* do_find_method_symbol (const std::string& method_name, + const std::string& class_name); + + cdef_package do_find_package (const std::string& name, + bool error_if_not_found, + bool load_if_not_found); + + octave_function* do_find_package_symbol (const std::string& pack_name); + + void do_register_class (const cdef_class& cls) + { all_classes[cls.get_name ()] = cls; } + + void do_unregister_class (const cdef_class& cls) + { all_classes.erase(cls.get_name ()); } + + void do_register_package (const cdef_package& pkg) + { all_packages[pkg.get_name ()] = pkg; } + + void do_unregister_package (const cdef_package& pkg) + { all_packages.erase(pkg.get_name ()); } + +private: + + // The single cdef_manager instance + static cdef_manager *instance; + + // All registered/loaded classes + std::map all_classes; + + // All registered/loaded packages + std::map all_packages; +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-colon.cc --- a/libinterp/octave-value/ov-colon.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-colon.cc Sun May 25 10:29:05 2014 -0700 @@ -35,7 +35,7 @@ "magic-colon", "magic-colon"); void -octave_magic_colon::print (std::ostream& os, bool) const +octave_magic_colon::print (std::ostream& os, bool) { indent (os); print_raw (os); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-colon.h --- a/libinterp/octave-value/ov-colon.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-colon.h Sun May 25 10:29:05 2014 -0700 @@ -67,7 +67,7 @@ bool is_magic_colon (void) const { return true; } - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-complex.cc --- a/libinterp/octave-value/ov-complex.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-complex.cc Sun May 25 10:29:05 2014 -0700 @@ -105,7 +105,7 @@ double octave_complex::double_value (bool force_conversion) const { - double retval = lo_ieee_nan_value (); + double retval; if (! force_conversion) gripe_implicit_conversion ("Octave:imag-to-real", @@ -119,7 +119,7 @@ float octave_complex::float_value (bool force_conversion) const { - float retval = lo_ieee_float_nan_value (); + float retval; if (! force_conversion) gripe_implicit_conversion ("Octave:imag-to-real", @@ -315,7 +315,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, type_hid = -1, data_hid = -1; + hid_t space_hid, type_hid, data_hid; + space_hid = type_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-cx-diag.cc --- a/libinterp/octave-value/ov-cx-diag.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-cx-diag.cc Sun May 25 10:29:05 2014 -0700 @@ -167,7 +167,8 @@ octave_complex_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-cx-mat.cc --- a/libinterp/octave-value/ov-cx-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-cx-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -561,7 +561,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1, type_hid = -1; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; bool retval = true; ComplexNDArray m = complex_array_value (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-cx-sparse.cc --- a/libinterp/octave-value/ov-cx-sparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-cx-sparse.cc Sun May 25 10:29:05 2014 -0700 @@ -241,16 +241,16 @@ int32_t itmp; // Use negative value for ndims to be consistent with other formats - itmp= -2; + itmp = -2; os.write (reinterpret_cast (&itmp), 4); - itmp= nr; + itmp = nr; os.write (reinterpret_cast (&itmp), 4); - itmp= nc; + itmp = nc; os.write (reinterpret_cast (&itmp), 4); - itmp= nz; + itmp = nz; os.write (reinterpret_cast (&itmp), 4); save_type st = LS_DOUBLE; @@ -390,7 +390,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; SparseComplexMatrix m = sparse_complex_matrix_value (); octave_idx_type tmp; @@ -636,7 +637,7 @@ #else group_hid = H5Gopen (loc_id, name); #endif - if (group_hid < 0 ) return false; + if (group_hid < 0) return false; #if HAVE_HDF5_18 data_hid = H5Dopen (group_hid, "nr", H5P_DEFAULT); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-fcn-handle.cc Sun May 25 10:29:05 2014 -0700 @@ -270,7 +270,7 @@ std::string dir_name = str.substr (0, xpos); octave_function *xfcn - = load_fcn_from_file (str, dir_name, "", nm); + = load_fcn_from_file (str, dir_name, "", "", nm); if (xfcn) { @@ -300,7 +300,7 @@ std::string dir_name = str.substr (0, xpos); - octave_function *xfcn = load_fcn_from_file (str, dir_name, "", nm); + octave_function *xfcn = load_fcn_from_file (str, dir_name, "", "", nm); if (xfcn) { @@ -323,7 +323,7 @@ std::string dir_name = fpath.substr (0, xpos); - octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", nm); + octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", "", nm); if (xfcn) { @@ -721,7 +721,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1, type_hid = -1;; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; // attach the type of the variable type_hid = H5Tcopy (H5T_C_S1); @@ -1386,7 +1387,7 @@ */ void -octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) const +octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); @@ -1572,7 +1573,8 @@ // for any class. if (local_funcs && fptr && (fptr->is_subfunction () || fptr->is_private_function () - || fptr->is_class_constructor ())) + || fptr->is_class_constructor () + || fptr->is_classdef_constructor ())) { // Locally visible function. retval = octave_value (new octave_fcn_handle (f, tnm)); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-fcn-handle.h --- a/libinterp/octave-value/ov-fcn-handle.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-fcn-handle.h Sun May 25 10:29:05 2014 -0700 @@ -153,7 +153,7 @@ bool load_hdf5 (hid_t loc_id, const char *name); #endif - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-fcn-inline.cc --- a/libinterp/octave-value/ov-fcn-inline.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-fcn-inline.cc Sun May 25 10:29:05 2014 -0700 @@ -284,14 +284,15 @@ #else group_hid = H5Gcreate (loc_id, name, 0); #endif - if (group_hid < 0 ) return false; + if (group_hid < 0) return false; size_t len = 0; for (int i = 0; i < ifargs.length (); i++) if (len < ifargs(i).length ()) len = ifargs(i).length (); - hid_t space_hid = -1, data_hid = -1, type_hid = -1;; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; bool retval = true; // FIXME: Is there a better way of saving string vectors, @@ -423,7 +424,7 @@ #else group_hid = H5Gopen (loc_id, name); #endif - if (group_hid < 0 ) return false; + if (group_hid < 0) return false; #if HAVE_HDF5_18 data_hid = H5Dopen (group_hid, "args", H5P_DEFAULT); @@ -597,7 +598,7 @@ #endif void -octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax) const +octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-fcn-inline.h --- a/libinterp/octave-value/ov-fcn-inline.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-fcn-inline.h Sun May 25 10:29:05 2014 -0700 @@ -86,7 +86,7 @@ bool load_hdf5 (hid_t loc_id, const char *name); #endif - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-fcn.h --- a/libinterp/octave-value/ov-fcn.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-fcn.h Sun May 25 10:29:05 2014 -0700 @@ -46,7 +46,8 @@ octave_function (void) : relative (false), locked (false), private_function (false), - xdispatch_class (), my_name (), my_dir_name (), doc () { } + xdispatch_class (), xpackage_name (), my_name (), my_dir_name (), + doc () { } ~octave_function (void) { } @@ -85,6 +86,10 @@ virtual bool is_class_constructor (const std::string& = std::string ()) const { return false; } + virtual bool + is_classdef_constructor (const std::string& = std::string ()) const + { return false; } + virtual bool is_class_method (const std::string& = std::string ()) const { return false; } @@ -96,6 +101,10 @@ std::string dispatch_class (void) const { return xdispatch_class; } + void stash_package_name (const std::string& pack) { xpackage_name = pack; } + + std::string package_name (void) const { return xpackage_name; } + virtual void mark_as_private_function (const std::string& cname = std::string ()) { @@ -152,6 +161,14 @@ std::string name (void) const { return my_name; } + std::string canonical_name (void) const + { + if (xpackage_name.empty ()) + return my_name; + else + return xpackage_name + "." + my_name; + } + void document (const std::string& ds) { doc = ds; } std::string doc_string (void) const { return doc; } @@ -160,6 +177,9 @@ virtual void accept (tree_walker&) { } + virtual bool is_postfix_index_handled (char type) const + { return (type == '(' || type == '{'); } + protected: octave_function (const std::string& nm, @@ -181,6 +201,10 @@ // to which the method belongs. std::string xdispatch_class; + // If this function is part of a package, this is the full name + // of the package to which the function belongs. + std::string xpackage_name; + // The name of this function. std::string my_name; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-float.cc --- a/libinterp/octave-value/ov-float.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-float.cc Sun May 25 10:29:05 2014 -0700 @@ -191,7 +191,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); @@ -326,8 +327,31 @@ SCALAR_MAPPER (isnan, xisnan); SCALAR_MAPPER (xsignbit, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return scalar; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: - return octave_base_value::map (umap); + return octave_base_value::map (umap); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-flt-complex.cc --- a/libinterp/octave-value/ov-flt-complex.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-flt-complex.cc Sun May 25 10:29:05 2014 -0700 @@ -89,7 +89,7 @@ double octave_float_complex::double_value (bool force_conversion) const { - double retval = lo_ieee_nan_value (); + double retval; if (! force_conversion) gripe_implicit_conversion ("Octave:imag-to-real", @@ -103,7 +103,7 @@ float octave_float_complex::float_value (bool force_conversion) const { - float retval = lo_ieee_float_nan_value (); + float retval; if (! force_conversion) gripe_implicit_conversion ("Octave:imag-to-real", @@ -300,7 +300,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, type_hid = -1, data_hid = -1; + hid_t space_hid, type_hid, data_hid; + space_hid = type_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-flt-cx-diag.cc --- a/libinterp/octave-value/ov-flt-cx-diag.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-flt-cx-diag.cc Sun May 25 10:29:05 2014 -0700 @@ -150,7 +150,8 @@ bool& /* save_as_floats */) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-flt-cx-mat.cc --- a/libinterp/octave-value/ov-flt-cx-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-flt-cx-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -536,7 +536,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1, type_hid = -1; + hid_t space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; bool retval = true; FloatComplexNDArray m = complex_array_value (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-flt-re-diag.cc --- a/libinterp/octave-value/ov-flt-re-diag.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-flt-re-diag.cc Sun May 25 10:29:05 2014 -0700 @@ -119,7 +119,8 @@ bool& /* save_as_floats*/) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-flt-re-mat.cc --- a/libinterp/octave-value/ov-flt-re-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-flt-re-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -563,7 +563,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; FloatNDArray m = array_value (); @@ -811,6 +812,29 @@ ARRAY_MAPPER (isna, bool, octave_is_NA); ARRAY_MAPPER (xsignbit, float, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return matrix; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: return octave_base_value::map (umap); } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-intx.h --- a/libinterp/octave-value/ov-intx.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-intx.h Sun May 25 10:29:05 2014 -0700 @@ -358,8 +358,15 @@ case umap_finite: return boolNDArray (matrix.dims (), true); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return matrix; + default: { + // FIXME: we should be able to do better than converting to + // double here. octave_matrix m (array_value ()); return m.map (umap); } @@ -658,6 +665,11 @@ case umap_finite: return true; + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return scalar; + default: { octave_scalar m (scalar_value ()); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-java.cc --- a/libinterp/octave-value/ov-java.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-java.cc Sun May 25 10:29:05 2014 -0700 @@ -1150,7 +1150,8 @@ if (jni_env->IsInstanceOf (jobj, cls)) { jobjectArray jarr = reinterpret_cast (jobj); - int rows = jni_env->GetArrayLength (jarr), cols = 0; + int rows = jni_env->GetArrayLength (jarr); + int cols = 0; if (rows > 0) { @@ -1761,7 +1762,7 @@ } void -octave_java::print (std::ostream& os, bool) const +octave_java::print (std::ostream& os, bool) { print_raw (os); newline (os); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-java.h --- a/libinterp/octave-value/ov-java.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-java.h Sun May 25 10:29:05 2014 -0700 @@ -149,7 +149,7 @@ dim_vector dims (void) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-lazy-idx.h --- a/libinterp/octave-value/ov-lazy-idx.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-lazy-idx.h Sun May 25 10:29:05 2014 -0700 @@ -128,7 +128,7 @@ bool print_as_scalar (void) const { return make_value ().print_as_scalar (); } - void print (std::ostream& os, bool pr_as_read_syntax = false) const + void print (std::ostream& os, bool pr_as_read_syntax = false) { make_value ().print (os, pr_as_read_syntax); } void print_info (std::ostream& os, const std::string& prefix) const diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-oncleanup.cc --- a/libinterp/octave-value/ov-oncleanup.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-oncleanup.cc Sun May 25 10:29:05 2014 -0700 @@ -170,7 +170,7 @@ #endif void -octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax) const +octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-oncleanup.h --- a/libinterp/octave-value/ov-oncleanup.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-oncleanup.h Sun May 25 10:29:05 2014 -0700 @@ -87,7 +87,7 @@ bool load_hdf5 (hid_t loc_id, const char *name); #endif - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-perm.cc --- a/libinterp/octave-value/ov-perm.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-perm.cc Sun May 25 10:29:05 2014 -0700 @@ -260,8 +260,6 @@ bool octave_perm_matrix::save_ascii (std::ostream& os) { - typedef octave_int idx_int_type; - os << "# size: " << matrix.rows () << "\n"; os << "# orient: " << (matrix.is_col_perm () ? 'c' : 'r') << '\n'; @@ -277,7 +275,6 @@ bool octave_perm_matrix::load_ascii (std::istream& is) { - typedef octave_int idx_int_type; octave_idx_type n; bool success = true; char orient; @@ -328,7 +325,7 @@ bool octave_perm_matrix::load_binary (std::istream& is, bool swap, - oct_mach_info::float_format ) + oct_mach_info::float_format) { int32_t sz; bool colp; @@ -389,7 +386,7 @@ } void -octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax) const +octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); @@ -451,3 +448,18 @@ return retval; } +octave_value +octave_perm_matrix::fast_elem_extract (octave_idx_type n) const +{ + if (n < matrix.numel ()) + { + octave_idx_type nr = matrix.rows (); + + octave_idx_type r = n % nr; + octave_idx_type c = n / nr; + + return octave_value (matrix.elem (r, c)); + } + else + return octave_value (); +} diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-perm.h --- a/libinterp/octave-value/ov-perm.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-perm.h Sun May 25 10:29:05 2014 -0700 @@ -211,13 +211,15 @@ bool print_as_scalar (void) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_info (std::ostream& os, const std::string& prefix) const; octave_value map (unary_mapper_t umap) const { return to_dense ().map (umap); } + octave_value fast_elem_extract (octave_idx_type n) const; + protected: PermMatrix matrix; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-range.cc --- a/libinterp/octave-value/ov-range.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-range.cc Sun May 25 10:29:05 2014 -0700 @@ -352,7 +352,7 @@ } void -octave_range::print (std::ostream& os, bool pr_as_read_syntax) const +octave_range::print (std::ostream& os, bool pr_as_read_syntax) { print_raw (os, pr_as_read_syntax); newline (os); @@ -549,7 +549,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, type_hid = -1, data_hid = -1; + hid_t space_hid, type_hid, data_hid; + space_hid = type_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); @@ -676,6 +677,13 @@ return retval; } +octave_value +octave_range::fast_elem_extract (octave_idx_type n) const +{ + return (n < range.nelem ()) + ? octave_value (range.elem (n)) : octave_value (); +} + DEFUN (allow_noninteger_range_as_index, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} allow_noninteger_range_as_index ()\n\ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-range.h --- a/libinterp/octave-value/ov-range.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-range.h Sun May 25 10:29:05 2014 -0700 @@ -249,7 +249,7 @@ octave_value convert_to_str_internal (bool pad, bool force, char type) const; - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; @@ -290,6 +290,8 @@ return m.map (umap); } + octave_value fast_elem_extract (octave_idx_type n) const; + private: Range range; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-re-diag.cc --- a/libinterp/octave-value/ov-re-diag.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-re-diag.cc Sun May 25 10:29:05 2014 -0700 @@ -179,7 +179,8 @@ octave_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats) { - int32_t r = matrix.rows (), c = matrix.cols (); + int32_t r = matrix.rows (); + int32_t c = matrix.cols (); os.write (reinterpret_cast (&r), 4); os.write (reinterpret_cast (&c), 4); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-re-mat.cc --- a/libinterp/octave-value/ov-re-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-re-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -675,7 +675,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; NDArray m = array_value (); @@ -934,13 +935,30 @@ ARRAY_MAPPER (isna, bool, octave_is_NA); ARRAY_MAPPER (xsignbit, double, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return matrix; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: - if (umap >= umap_xisalnum && umap <= umap_xtoupper) - { - octave_value str_conv = convert_to_str (true, true); - return error_state ? octave_value () : str_conv.map (umap); - } - else return octave_base_value::map (umap); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-re-sparse.cc --- a/libinterp/octave-value/ov-re-sparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-re-sparse.cc Sun May 25 10:29:05 2014 -0700 @@ -274,16 +274,16 @@ int32_t itmp; // Use negative value for ndims to be consistent with other formats - itmp= -2; + itmp = -2; os.write (reinterpret_cast (&itmp), 4); - itmp= nr; + itmp = nr; os.write (reinterpret_cast (&itmp), 4); - itmp= nc; + itmp = nc; os.write (reinterpret_cast (&itmp), 4); - itmp= nz; + itmp = nz; os.write (reinterpret_cast (&itmp), 4); save_type st = LS_DOUBLE; @@ -421,7 +421,8 @@ if (group_hid < 0) return false; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; SparseMatrix m = sparse_matrix_value (); octave_idx_type tmp; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-scalar.cc --- a/libinterp/octave-value/ov-scalar.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-scalar.cc Sun May 25 10:29:05 2014 -0700 @@ -206,7 +206,8 @@ bool /* save_as_floats */) { hsize_t dimens[3]; - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; space_hid = H5Screate_simple (0, dimens, 0); @@ -342,14 +343,31 @@ SCALAR_MAPPER (isnan, xisnan); SCALAR_MAPPER (xsignbit, xsignbit); + // Special cases for Matlab compatibility. + case umap_xtolower: + case umap_xtoupper: + return scalar; + + case umap_xisalnum: + case umap_xisalpha: + case umap_xisascii: + case umap_xiscntrl: + case umap_xisdigit: + case umap_xisgraph: + case umap_xislower: + case umap_xisprint: + case umap_xispunct: + case umap_xisspace: + case umap_xisupper: + case umap_xisxdigit: + case umap_xtoascii: + { + octave_value str_conv = convert_to_str (true, true); + return error_state ? octave_value () : str_conv.map (umap); + } + default: - if (umap >= umap_xisalnum && umap <= umap_xtoupper) - { - octave_value str_conv = convert_to_str (true, true); - return error_state ? octave_value () : str_conv.map (umap); - } - else - return octave_base_value::map (umap); + return octave_base_value::map (umap); } } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-str-mat.cc --- a/libinterp/octave-value/ov-str-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-str-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -583,7 +583,8 @@ return (empty > 0); int rank = dv.length (); - hid_t space_hid = -1, data_hid = -1; + hid_t space_hid, data_hid; + space_hid = data_hid = -1; bool retval = true; charNDArray m = char_array_value (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-struct.cc --- a/libinterp/octave-value/ov-struct.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-struct.cc Sun May 25 10:29:05 2014 -0700 @@ -648,7 +648,7 @@ } void -octave_struct::print (std::ostream& os, bool) const +octave_struct::print (std::ostream& os, bool) { print_raw (os); } @@ -844,7 +844,7 @@ success = false; } } - else if (len == 0 ) + else if (len == 0) map = octave_map (dv); else panic_impossible (); @@ -1359,7 +1359,7 @@ } void -octave_scalar_struct::print (std::ostream& os, bool) const +octave_scalar_struct::print (std::ostream& os, bool) { print_raw (os); } @@ -2066,9 +2066,9 @@ return retval; } -DEFUN (nfields, args, , +DEFUN (numfields, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} nfields (@var{s})\n\ +@deftypefn {Built-in Function} {} numfields (@var{s})\n\ Return the number of fields of the structure @var{s}.\n\ @seealso{fieldnames}\n\ @end deftypefn") diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-struct.h --- a/libinterp/octave-value/ov-struct.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-struct.h Sun May 25 10:29:05 2014 -0700 @@ -126,7 +126,7 @@ string_vector map_keys (void) const { return map.fieldnames (); } - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; @@ -249,7 +249,7 @@ string_vector map_keys (void) const { return map.fieldnames (); } - void print (std::ostream& os, bool pr_as_read_syntax = false) const; + void print (std::ostream& os, bool pr_as_read_syntax = false); void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-usr-fcn.cc Sun May 25 10:29:05 2014 -0700 @@ -203,7 +203,7 @@ num_named_args (param_list ? param_list->length () : 0), subfunction (false), inline_function (false), anonymous_function (false), nested_function (false), - class_constructor (false), class_method (false), + class_constructor (none), class_method (false), parent_scope (-1), local_scope (sid), curr_unwind_protect_frame (0) #ifdef HAVE_LLVM @@ -319,14 +319,18 @@ { std::ostringstream result; - if (is_inline_function ()) - result << "inline@" << fcn_file_name () - << ":" << location_line << ":" << location_column; - else if (is_anonymous_function ()) + if (is_anonymous_function ()) result << "anonymous@" << fcn_file_name () << ":" << location_line << ":" << location_column; else if (is_subfunction ()) result << parent_fcn_name () << ">" << name (); + else if (is_class_method ()) + result << "@" << dispatch_class () << "/" << name (); + else if (is_class_constructor () || is_classdef_constructor ()) + result << "@" << name (); + else if (is_inline_function ()) + result << "inline@" << fcn_file_name () + << ":" << location_line << ":" << location_column; else result << name (); @@ -470,7 +474,7 @@ octave_value_list octave_user_function::do_multi_index_op (int nargout, - const octave_value_list& args, + const octave_value_list& _args, const std::list* lvalue_list) { octave_value_list retval; @@ -481,6 +485,23 @@ if (! cmd_list) return retval; + // If this function is a classdef constructor, extract the first input + // argument, which must be the partially constructed object instance. + + octave_value_list args (_args); + octave_value_list ret_args; + + if (is_classdef_constructor ()) + { + if (args.length () > 0) + { + ret_args = args.slice (0, 1, true); + args = args.slice (1, args.length () - 1, true); + } + else + panic_impossible (); + } + #ifdef HAVE_LLVM if (is_special_expr () && tree_jit::execute (*this, args, retval)) @@ -524,6 +545,25 @@ return retval; } + // For classdef constructor, pre-populate the output arguments + // with the pre-initialized object instance, extracted above. + + if (is_classdef_constructor ()) + { + if (ret_list) + { + ret_list->define_from_arg_vector (ret_args); + if (error_state) + return retval; + } + else + { + ::error ("%s: invalid classdef constructor, no output argument defined", + dispatch_class ().c_str ()); + return retval; + } + } + // Force parameter list to be undefined when this function exits. // Doing so decrements the reference counts on the values of local // variables that are also named function parameters. @@ -744,7 +784,8 @@ { // Only assign the hidden variable if black holes actually present. Matrix bh (1, nbh); - octave_idx_type k = 0, l = 0; + octave_idx_type k = 0; + octave_idx_type l = 0; for (std::list::const_iterator p = lvalue_list->begin (); p != lvalue_list->end (); p++) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov-usr-fcn.h --- a/libinterp/octave-value/ov-usr-fcn.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov-usr-fcn.h Sun May 25 10:29:05 2014 -0700 @@ -327,12 +327,20 @@ void mark_as_nested_function (void) { nested_function = true; } - void mark_as_class_constructor (void) { class_constructor = true; } + void mark_as_class_constructor (void) { class_constructor = legacy; } + + void mark_as_classdef_constructor (void) { class_constructor = classdef; } bool is_class_constructor (const std::string& cname = std::string ()) const { - return class_constructor - ? (cname.empty () ? true : cname == dispatch_class ()) : false; + return class_constructor == legacy + ? (cname.empty () ? true : cname == dispatch_class ()) : false; + } + + bool is_classdef_constructor (const std::string& cname = std::string ()) const + { + return class_constructor == classdef + ? (cname.empty () ? true : cname == dispatch_class ()) : false; } void mark_as_class_method (void) { class_method = true; } @@ -408,6 +416,13 @@ private: + enum class_ctor_type + { + none, + legacy, + classdef + }; + // List of arguments for this function. These are local variables. tree_parameter_list *param_list; @@ -470,8 +485,8 @@ // TRUE means this is a nested function. (either a child or parent) bool nested_function; - // TRUE means this function is the constructor for class object. - bool class_constructor; + // Enum describing whether this function is the constructor for class object. + class_ctor_type class_constructor; // TRUE means this function is a method for a class. bool class_method; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov.cc Sun May 25 10:29:05 2014 -0700 @@ -65,6 +65,7 @@ #include "ov-range.h" #include "ov-struct.h" #include "ov-class.h" +#include "ov-classdef.h" #include "ov-oncleanup.h" #include "ov-cs-list.h" #include "ov-colon.h" @@ -1193,13 +1194,14 @@ { } -octave_value::octave_value (const Octave_map& m) - : rep (new octave_struct (m)) +octave_value::octave_value (const octave_map& m, const std::string& id, + const std::list& plist) + : rep (new octave_class (m, id, plist)) { maybe_mutate (); } -octave_value::octave_value (const Octave_map& m, const std::string& id, +octave_value::octave_value (const octave_scalar_map& m, const std::string& id, const std::list& plist) : rep (new octave_class (m, id, plist)) { @@ -1951,7 +1953,9 @@ int t2 = v2.type_id (); if (t1 == octave_class::static_type_id () - || t2 == octave_class::static_type_id ()) + || t2 == octave_class::static_type_id () + || t1 == octave_classdef::static_type_id () + || t2 == octave_classdef::static_type_id ()) { octave_value_typeinfo::binary_class_op_fcn f = octave_value_typeinfo::lookup_binary_class_op (op); @@ -2207,7 +2211,9 @@ int t2 = v2.type_id (); if (t1 == octave_class::static_type_id () - || t2 == octave_class::static_type_id ()) + || t2 == octave_class::static_type_id () + || t1 == octave_classdef::static_type_id () + || t2 == octave_classdef::static_type_id ()) { octave_value_typeinfo::binary_class_op_fcn f = octave_value_typeinfo::lookup_binary_class_op (op); @@ -2381,7 +2387,8 @@ int t = v.type_id (); - if (t == octave_class::static_type_id ()) + if (t == octave_class::static_type_id () + || t == octave_classdef::static_type_id ()) { octave_value_typeinfo::unary_class_op_fcn f = octave_value_typeinfo::lookup_unary_class_op (op); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave-value/ov.h Sun May 25 10:29:05 2014 -0700 @@ -46,7 +46,6 @@ class mxArray; class octave_map; class octave_scalar_map; -class Octave_map; class octave_stream; class octave_function; class octave_user_function; @@ -285,8 +284,9 @@ octave_value (const Range& r); octave_value (const octave_map& m); octave_value (const octave_scalar_map& m); - octave_value (const Octave_map& m); - octave_value (const Octave_map& m, const std::string& id, + octave_value (const octave_map& m, const std::string& id, + const std::list& plist); + octave_value (const octave_scalar_map& m, const std::string& id, const std::list& plist); octave_value (const octave_value_list& m, bool = false); octave_value (octave_value::magic_colon); @@ -1017,7 +1017,7 @@ bool print_as_scalar (void) const { return rep->print_as_scalar (); } - void print (std::ostream& os, bool pr_as_read_syntax = false) const + void print (std::ostream& os, bool pr_as_read_syntax = false) { rep->print (os, pr_as_read_syntax); } void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/octave.cc --- a/libinterp/octave.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/octave.cc Sun May 25 10:29:05 2014 -0700 @@ -68,6 +68,7 @@ #include "ops.h" #include "options-usage.h" #include "ov.h" +#include "ov-classdef.h" #include "ov-range.h" #include "toplev.h" #include "parse.h" @@ -754,6 +755,8 @@ install_builtins (); + install_classdef (); + for (std::list::const_iterator it = command_line_path.begin (); it != command_line_path.end (); it++) load_path::set_command_line_path (*it); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/operators/op-b-b.cc --- a/libinterp/operators/op-b-b.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/operators/op-b-b.cc Sun May 25 10:29:05 2014 -0700 @@ -33,6 +33,7 @@ #include "ov-float.h" #include "ov-re-mat.h" #include "ov-typeinfo.h" +#include "ov-null-mat.h" #include "ops.h" #include "xdiv.h" #include "xpow.h" @@ -92,4 +93,8 @@ INSTALL_CATOP (octave_float_scalar, octave_bool, f_b); INSTALL_ASSIGNCONV (octave_bool, octave_bool, octave_bool_matrix); + + INSTALL_ASSIGNCONV (octave_bool, octave_null_matrix, octave_bool_matrix); + INSTALL_ASSIGNCONV (octave_bool, octave_null_str, octave_bool_matrix); + INSTALL_ASSIGNCONV (octave_bool, octave_null_sq_str, octave_bool_matrix); } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/operators/op-cm-sm.cc --- a/libinterp/operators/op-cm-sm.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/operators/op-cm-sm.cc Sun May 25 10:29:05 2014 -0700 @@ -106,8 +106,8 @@ const octave_sparse_matrix&); return octave_value - (elem_xpow ( SparseComplexMatrix (v1.complex_matrix_value ()), - v2.sparse_matrix_value ())); + (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()), + v2.sparse_matrix_value ())); } DEFBINOP (el_ldiv, complex_matrix, sparse_matrix) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/operators/op-int.h --- a/libinterp/operators/op-int.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/operators/op-int.h Sun May 25 10:29:05 2014 -0700 @@ -1160,7 +1160,10 @@ #define OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS(TYPE) \ INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_matrix, TYPE ## null_assign) \ INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_str, TYPE ## null_assign) \ - INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign) + INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign) \ + INSTALL_ASSIGNCONV (octave_ ## TYPE ## _scalar, octave_null_matrix, octave_ ## TYPE ## _matrix) \ + INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_str, octave_ ## TYPE ## _matrix) \ + INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_sq_str, octave_ ## TYPE ## _matrix) #define OCTAVE_INSTALL_INT_OPS(TYPE) \ OCTAVE_INSTALL_SS_INT_OPS (TYPE) \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/operators/op-pm-sm.cc --- a/libinterp/operators/op-pm-sm.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/operators/op-pm-sm.cc Sun May 25 10:29:05 2014 -0700 @@ -44,12 +44,12 @@ DEFUNOP (not, perm_matrix) { // Obviously negation of a permutation matrix destroys sparsity - return octave_value ( ! a.bool_array_value ()); + return octave_value (! a.bool_array_value ()); } DEFUNOP (uminus, perm_matrix) { - return octave_value ( - a.sparse_matrix_value ()); + return octave_value (- a.sparse_matrix_value ()); } // Most other logical operations cast to SparseBoolMatrix diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/operators/op-sbm-sbm.cc --- a/libinterp/operators/op-sbm-sbm.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/operators/op-sbm-sbm.cc Sun May 25 10:29:05 2014 -0700 @@ -49,7 +49,7 @@ DEFUNOP (uminus, sparse_bool_matrix) { CAST_UNOP_ARG (const octave_sparse_bool_matrix&); - return octave_value ( - v.sparse_matrix_value ()); + return octave_value (- v.sparse_matrix_value ()); } DEFUNOP (transpose, sparse_bool_matrix) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/lex.h Sun May 25 10:29:05 2014 -0700 @@ -261,7 +261,9 @@ looking_at_matrix_or_assign_lhs (false), looking_for_object_index (false), looking_at_indirect_ref (false), parsing_class_method (false), - maybe_classdef_get_set_method (false), parsing_classdef (false), + parsing_classdef (false), maybe_classdef_get_set_method (false), + parsing_classdef_get_method (false), + parsing_classdef_set_method (false), quote_is_transpose (false), force_script (false), reading_fcn_file (false), reading_script_file (false), reading_classdef_file (false), @@ -341,13 +343,19 @@ // true means we are parsing a class method in function or classdef file. bool parsing_class_method; + // true means we are parsing a classdef file + bool parsing_classdef; + // true means we are parsing a class method declaration line in a // classdef file and can accept a property get or set method name. // for example, "get.propertyname" is recognized as a function name. bool maybe_classdef_get_set_method; - // true means we are parsing a classdef file - bool parsing_classdef; + // TRUE means we are parsing a classdef get.method. + bool parsing_classdef_get_method; + + // TRUE means we are parsing a classdef set.method. + bool parsing_classdef_set_method; // return transpose or start a string? bool quote_is_transpose; @@ -572,6 +580,8 @@ int is_keyword_token (const std::string& s); + bool fq_identifier_contains_keyword (const std::string& s); + bool whitespace_is_significant (void); void handle_number (void); @@ -590,6 +600,8 @@ int handle_meta_identifier (void); + int handle_fq_identifier (void); + int handle_identifier (void); void maybe_warn_separator_insert (char sep); @@ -675,6 +687,8 @@ int show_token (int tok); + void enable_fq_identifier (void); + protected: std::stack start_state_stack; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/lex.ll Sun May 25 10:29:05 2014 -0700 @@ -54,6 +54,8 @@ %x DQ_STRING_START %x SQ_STRING_START +%x FQ_IDENT_START + %{ #include @@ -254,6 +256,43 @@ } \ while (0) +#define HANDLE_IDENTIFIER(pattern, get_set) \ + do \ + { \ + curr_lexer->lexer_debug (pattern); \ + \ + int tok = curr_lexer->previous_token_value (); \ + \ + if (curr_lexer->whitespace_is_significant () \ + && curr_lexer->space_follows_previous_token () \ + && ! (tok == '[' || tok == '{' \ + || curr_lexer->previous_token_is_binop ())) \ + { \ + yyless (0); \ + unput (','); \ + } \ + else \ + { \ + if (! curr_lexer->looking_at_decl_list \ + && curr_lexer->previous_token_may_be_command ()) \ + { \ + yyless (0); \ + curr_lexer->push_start_state (COMMAND_START); \ + } \ + else \ + { \ + if (get_set) \ + curr_lexer->maybe_classdef_get_set_method = false; \ + \ + int id_tok = curr_lexer->handle_identifier (); \ + \ + if (id_tok >= 0) \ + return curr_lexer->count_token_internal (id_tok); \ + } \ + } \ + } \ + while (0) + static bool Vdisplay_tokens = false; static unsigned int Vtoken_count = 0; @@ -274,6 +313,7 @@ Im [iIjJ] CCHAR [#%] IDENT ([_$a-zA-Z][_$a-zA-Z0-9]*) +FQIDENT ({IDENT}(\.{IDENT})*) EXPON ([DdEe][+-]?{D}+) NUMBER (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+)) @@ -1006,6 +1046,35 @@ } %{ +// Fully-qualified identifiers (used for classdef). +%} + +{FQIDENT} { + curr_lexer->lexer_debug ("{FQIDENT}"); + curr_lexer->pop_start_state (); + + int id_tok = curr_lexer->handle_fq_identifier (); + + if (id_tok >= 0) + { + curr_lexer->looking_for_object_index = true; + + return curr_lexer->count_token_internal (id_tok); + } + } + +{S}+ { + curr_lexer->current_input_column += yyleng; + + curr_lexer->mark_previous_token_trailing_space (); + } + +. { + yyless (0); + curr_lexer->pop_start_state (); + } + +%{ // Imaginary numbers. %} @@ -1126,46 +1195,25 @@ %{ // Identifiers. + +// Don't allow get and set to be recognized as keywords if they are +// followed by "(". %} +(set|get)/{S}*\( { + HANDLE_IDENTIFIER ("(set|get)/{S}*\\(", true); + } + {IDENT} { - curr_lexer->lexer_debug ("{IDENT}"); - - int tok = curr_lexer->previous_token_value (); - - if (curr_lexer->whitespace_is_significant () - && curr_lexer->space_follows_previous_token () - && ! (tok == '[' || tok == '{' - || curr_lexer->previous_token_is_binop ())) - { - yyless (0); - unput (','); - } - else - { - if (! curr_lexer->looking_at_decl_list - && curr_lexer->previous_token_may_be_command ()) - { - yyless (0); - curr_lexer->push_start_state (COMMAND_START); - } - else - { - int id_tok = curr_lexer->handle_identifier (); - - if (id_tok >= 0) - return curr_lexer->count_token_internal (id_tok); - } - } + HANDLE_IDENTIFIER ("{IDENT}", false); } %{ // Superclass method identifiers. %} -{IDENT}@{IDENT} | -{IDENT}@{IDENT}.{IDENT} { - curr_lexer->lexer_debug ("{IDENT}@{IDENT}|{IDENT}@{IDENT}.{IDENT}"); +{IDENT}@{FQIDENT} { + curr_lexer->lexer_debug ("{IDENT}@{FQIDENT}"); if (curr_lexer->previous_token_may_be_command ()) { @@ -1180,7 +1228,7 @@ { curr_lexer->looking_for_object_index = true; - return curr_lexer->count_token_internal (SUPERCLASSREF); + return curr_lexer->count_token_internal (id_tok); } } } @@ -1189,9 +1237,8 @@ // Metaclass query %} -\?{IDENT} | -\?{IDENT}\.{IDENT} { - curr_lexer->lexer_debug ("\\?{IDENT}|\\?{IDENT}\\.{IDENT}"); +\?{FQIDENT} { + curr_lexer->lexer_debug ("\\?{FQIDENT}"); if (curr_lexer->previous_token_may_be_command () && curr_lexer->space_follows_previous_token ()) @@ -1207,7 +1254,7 @@ { curr_lexer->looking_for_object_index = true; - return curr_lexer->count_token_internal (METAQUERY); + return curr_lexer->count_token_internal (id_tok); } } } @@ -1955,8 +2002,10 @@ looking_for_object_index = false; looking_at_indirect_ref = false; parsing_class_method = false; + parsing_classdef = false; maybe_classdef_get_set_method = false; - parsing_classdef = false; + parsing_classdef_get_method = false; + parsing_classdef_set_method = false; force_script = false; reading_fcn_file = false; reading_script_file = false; @@ -2358,20 +2407,6 @@ at_beginning_of_statement = true; break; - case static_kw: - if ((reading_fcn_file || reading_script_file - || reading_classdef_file) - && ! fcn_file_full_name.empty ()) - warning_with_id ("Octave:deprecated-keyword", - "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d of file '%s'", - input_line_number, - fcn_file_full_name.c_str ()); - else - warning_with_id ("Octave:deprecated-keyword", - "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d", - input_line_number); - // fall through ... - case persistent_kw: case global_kw: looking_at_decl_list = true; @@ -2384,10 +2419,9 @@ case end_kw: if (inside_any_object_index () - || (! reading_classdef_file - && (defining_func - && ! (looking_at_return_list - || parsed_function_name.top ())))) + || (defining_func + && ! (looking_at_return_list + || parsed_function_name.top ()))) { at_beginning_of_statement = previous_at_bos; return 0; @@ -2573,6 +2607,34 @@ } bool +octave_base_lexer::fq_identifier_contains_keyword (const std::string& s) +{ + size_t p1 = 0; + size_t p2; + + std::string s_part; + + do + { + p2 = s.find ('.', p1); + + if (p2 != std::string::npos) + { + s_part = s.substr (p1, p2 - p1); + p1 = p2 + 1; + } + else + s_part = s.substr (p1); + + if (is_keyword_token (s_part)) + return true; + } + while (p2 != std::string::npos); + + return false; +} + +bool octave_base_lexer::whitespace_is_significant (void) { return (nesting_level.is_bracket () @@ -2744,36 +2806,23 @@ int octave_base_lexer::handle_superclass_identifier (void) { - std::string pkg; - char *yytxt = flex_yytext (); - std::string meth = strip_trailing_whitespace (yytxt); + std::string meth = flex_yytext (); + size_t pos = meth.find ("@"); - std::string cls = meth.substr (pos).substr (1); - meth = meth.substr (0, pos - 1); - - pos = cls.find ("."); - if (pos != std::string::npos) - { - pkg = cls.substr (pos).substr (1); - cls = cls.substr (0, pos - 1); - } - - int kw_token = (is_keyword_token (meth) || is_keyword_token (cls) - || is_keyword_token (pkg)); + std::string cls = meth.substr (pos + 1); + meth = meth.substr (0, pos); + + bool kw_token = (is_keyword_token (meth) + || fq_identifier_contains_keyword (cls)); + if (kw_token) { - error ("method, class and package names may not be keywords"); + error ("method, class, and package names may not be keywords"); return LEXICAL_ERROR; } - symbol_table::scope_id sid = symtab_context.curr_scope (); - - push_token (new token - (SUPERCLASSREF, - meth.empty () ? 0 : &(symbol_table::insert (meth, sid)), - cls.empty () ? 0 : &(symbol_table::insert (cls, sid)), - pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)), - input_line_number, current_input_column)); + push_token (new token (SUPERCLASSREF, meth, cls, + input_line_number, current_input_column)); current_input_column += flex_yyleng (); @@ -2783,37 +2832,41 @@ int octave_base_lexer::handle_meta_identifier (void) { - std::string pkg; - char *yytxt = flex_yytext (); - std::string cls = strip_trailing_whitespace (yytxt).substr (1); - size_t pos = cls.find ("."); - - if (pos != std::string::npos) + std::string cls = std::string(flex_yytext ()).substr (1); + + if (fq_identifier_contains_keyword (cls)) { - pkg = cls.substr (pos).substr (1); - cls = cls.substr (0, pos - 1); - } - - int kw_token = is_keyword_token (cls) || is_keyword_token (pkg); - if (kw_token) - { - error ("class and package names may not be keywords"); + error ("class and package names may not be keywords"); return LEXICAL_ERROR; } - symbol_table::scope_id sid = symtab_context.curr_scope (); - - push_token (new token - (METAQUERY, - cls.empty () ? 0 : &(symbol_table::insert (cls, sid)), - pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)), - input_line_number, current_input_column)); + push_token (new token (METAQUERY, cls, input_line_number, + current_input_column)); current_input_column += flex_yyleng (); return METAQUERY; } +int +octave_base_lexer::handle_fq_identifier (void) +{ + std::string tok = flex_yytext (); + + if (fq_identifier_contains_keyword (tok)) + { + error ("function, method, class, and package names may not be keywords"); + return LEXICAL_ERROR; + } + + push_token (new token (FQ_IDENT, tok, input_line_number, + current_input_column)); + + current_input_column += flex_yyleng (); + + return FQ_IDENT; +} + // Figure out exactly what kind of token to return when we have seen // an identifier. Handles keywords. Return -1 if the identifier // should be ignored. @@ -3371,6 +3424,12 @@ return tok; } +void +octave_base_lexer::enable_fq_identifier (void) +{ + push_start_state (FQ_IDENT_START); +} + int octave_lexer::fill_flex_buffer (char *buf, unsigned max_size) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/module.mk --- a/libinterp/parse-tree/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/module.mk Sun May 25 10:29:05 2014 -0700 @@ -21,6 +21,7 @@ parse-tree/pt-cbinop.h \ parse-tree/pt-cell.h \ parse-tree/pt-check.h \ + parse-tree/pt-classdef.h \ parse-tree/pt-cmd.h \ parse-tree/pt-colon.h \ parse-tree/pt-const.h \ @@ -29,6 +30,7 @@ parse-tree/pt-except.h \ parse-tree/pt-exp.h \ parse-tree/pt-fcn-handle.h \ + parse-tree/pt-funcall.h \ parse-tree/pt-id.h \ parse-tree/pt-idx.h \ parse-tree/pt-jump.h \ @@ -52,6 +54,7 @@ parse-tree/pt-cbinop.cc \ parse-tree/pt-cell.cc \ parse-tree/pt-check.cc \ + parse-tree/pt-classdef.cc \ parse-tree/pt-cmd.cc \ parse-tree/pt-colon.cc \ parse-tree/pt-const.cc \ @@ -60,6 +63,7 @@ parse-tree/pt-except.cc \ parse-tree/pt-exp.cc \ parse-tree/pt-fcn-handle.cc \ + parse-tree/pt-funcall.cc \ parse-tree/pt-id.cc \ parse-tree/pt-idx.cc \ parse-tree/pt-jump.cc \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/oct-parse.in.yy Sun May 25 10:29:05 2014 -0700 @@ -62,6 +62,7 @@ #include "load-path.h" #include "oct-hist.h" #include "oct-map.h" +#include "ov-classdef.h" #include "ov-fcn-handle.h" #include "ov-usr-fcn.h" #include "ov-null-mat.h" @@ -70,6 +71,7 @@ #include "parse.h" #include "pt-all.h" #include "pt-eval.h" +#include "pt-funcall.h" #include "symtab.h" #include "token.h" #include "unwind-prot.h" @@ -164,6 +166,8 @@ tree_expression *tree_expression_type; tree_constant *tree_constant_type; tree_fcn_handle *tree_fcn_handle_type; + tree_funcall *tree_funcall_type; + tree_function_def *tree_function_def_type; tree_anon_fcn_handle *tree_anon_fcn_handle_type; tree_identifier *tree_identifier_type; tree_index_expression *tree_index_expression_type; @@ -183,7 +187,24 @@ tree_statement *tree_statement_type; tree_statement_list *tree_statement_list_type; octave_user_function *octave_user_function_type; - void *dummy_type; + + tree_classdef *tree_classdef_type; + tree_classdef_attribute* tree_classdef_attribute_type; + tree_classdef_attribute_list* tree_classdef_attribute_list_type; + tree_classdef_superclass* tree_classdef_superclass_type; + tree_classdef_superclass_list* tree_classdef_superclass_list_type; + tree_classdef_body* tree_classdef_body_type; + tree_classdef_property* tree_classdef_property_type; + tree_classdef_property_list* tree_classdef_property_list_type; + tree_classdef_properties_block* tree_classdef_properties_block_type; + tree_classdef_methods_list* tree_classdef_methods_list_type; + tree_classdef_methods_block* tree_classdef_methods_block_type; + tree_classdef_event* tree_classdef_event_type; + tree_classdef_events_list* tree_classdef_events_list_type; + tree_classdef_events_block* tree_classdef_events_block_type; + tree_classdef_enum* tree_classdef_enum_type; + tree_classdef_enum_list* tree_classdef_enum_list_type; + tree_classdef_enum_block* tree_classdef_enum_block_type; } // Tokens with line and column information. @@ -210,21 +231,22 @@ %token TRY CATCH %token GLOBAL PERSISTENT %token FCN_HANDLE +%token CLASSDEF %token PROPERTIES METHODS EVENTS ENUMERATION %token METAQUERY %token SUPERCLASSREF +%token FQ_IDENT %token GET SET %token FCN // Other tokens. %token END_OF_INPUT LEXICAL_ERROR -%token INPUT_FILE CLASSDEF +%token INPUT_FILE // %token VARARGIN VARARGOUT // Nonterminals we construct. -%type function_beg -%type stash_comment classdef_beg -%type properties_beg methods_beg events_beg enum_beg +%type stash_comment +%type function_beg classdef_beg %type sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep %type input %type string constant magic_colon @@ -236,18 +258,19 @@ %type primary_expr oper_expr power_expr %type simple_expr colon_expr assign_expr expression %type identifier fcn_name magic_tilde -%type superclass_identifier meta_identifier -%type function1 function2 classdef1 +%type superclass_identifier meta_identifier +%type function1 function2 %type word_list_cmd %type colon_expr1 %type arg_list word_list assign_lhs %type cell_or_matrix_row %type param_list param_list1 param_list2 %type return_list return_list1 -%type superclasses opt_superclasses %type command select_command loop_command -%type jump_command except_command function -%type file classdef +%type jump_command except_command +%type function +%type classdef +%type file %type if_command %type elseif_clause else_clause %type if_cmd_list1 if_cmd_list @@ -257,25 +280,27 @@ %type decl2 param_list_elt %type decl1 %type declaration -%type statement function_end classdef_end +%type statement function_end %type simple_list simple_list1 list list1 %type opt_list -// These types need to be specified. -%type attr -%type class_event -%type class_enum -%type class_property -%type properties_list -%type properties_block -%type methods_list -%type methods_block -%type opt_attr_list -%type attr_list -%type events_list -%type events_block -%type enum_list -%type enum_block -%type class_body +%type attr +%type attr_list opt_attr_list +%type superclass +%type superclass_list opt_superclass_list +%type class_body +%type class_property +%type property_list +%type properties_block +%type methods_list +%type methods_block +%type class_event +%type events_list +%type events_block +%type class_enum +%type enum_list +%type enum_block +%type method_decl method +%type method_decl1 // Precedence and associativity. %right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ @@ -312,6 +337,8 @@ %destructor { delete $$; } %destructor { delete $$; } %destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } %destructor { delete $$; } %destructor { delete $$; } %destructor { delete $$; } @@ -332,6 +359,24 @@ %destructor { delete $$; } %destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } + %destructor { warning_with_id ("Octave:parser-destructor", @@ -439,11 +484,23 @@ superclass_identifier : SUPERCLASSREF - { $$ = new tree_identifier ($1->line (), $1->column ()); } + { + std::string method_nm = $1->superclass_method_name (); + std::string class_nm = $1->superclass_class_name (); + + $$ = parser.make_superclass_ref + (method_nm, class_nm, + $1->line (), $1->column ()); + } ; meta_identifier : METAQUERY - { $$ = new tree_identifier ($1->line (), $1->column ()); } + { + std::string class_nm = $1->text (); + + $$ = parser.make_meta_class_query (class_nm, $1->line (), + $1->column ()); + } ; string : DQ_STRING @@ -867,8 +924,6 @@ { $$ = $1; } | file { $$ = $1; } - | classdef - { $$ = $1; } ; // ===================== @@ -1294,6 +1349,13 @@ $$ = 0; } + | INPUT_FILE opt_nl classdef opt_sep END_OF_INPUT + { + if (lexer.reading_classdef_file) + parser.classdef_object = $3; + + $$ = 0; + } ; // =================== @@ -1336,12 +1398,14 @@ { lexer.parsed_function_name.top () = true; lexer.maybe_classdef_get_set_method = false; + lexer.parsing_classdef_get_method = true; $$ = $3; } | SET '.' identifier { lexer.parsed_function_name.top () = true; lexer.maybe_classdef_get_set_method = false; + lexer.parsing_classdef_set_method = true; $$ = $3; } ; @@ -1352,6 +1416,14 @@ delete $1; + if (lexer.parsing_classdef_get_method) + fname.insert (0, "get."); + else if (lexer.parsing_classdef_set_method) + fname.insert (0, "set."); + + lexer.parsing_classdef_get_method = false; + lexer.parsing_classdef_set_method = false; + $$ = parser.frob_function (fname, $2); } ; @@ -1411,158 +1483,299 @@ // Classdef // ======== -classdef_beg : CLASSDEF stash_comment +classdef_beg : CLASSDEF { - $$ = 0; + if (! lexer.reading_classdef_file) + { + parser.bison_error ("classdef must appear inside a file containing only a class definition"); + YYABORT; + } + lexer.parsing_classdef = true; + $$ = $1; } ; -classdef_end : END +classdef : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END { lexer.parsing_classdef = false; - if (parser.end_token_ok ($1, token::classdef_end)) - $$ = parser.make_end ("endclassdef", false, - $1->line (), $1->column ()); - else - ABORT_PARSE; + if (! ($$ = parser.make_classdef ($1, $3, $4, $5, $7, $9, $2))) + { + // make_classdef deleted $3, $4, $5, and $7. + ABORT_PARSE; + } } - ; - -classdef1 : classdef_beg opt_attr_list identifier opt_superclasses - { $$ = 0; } - ; - -classdef : classdef1 opt_sep class_body opt_sep stash_comment classdef_end - { $$ = 0; } + | classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep END + { + lexer.parsing_classdef = false; + + if (! ($$ = parser.make_classdef ($1, $3, $4, $5, 0, $7, $2))) + { + // make_classdef deleted $3, $4, and $5. + ABORT_PARSE; + } + } ; opt_attr_list : // empty { $$ = 0; } | '(' attr_list ')' - { $$ = 0; } + { $$ = $2; } ; attr_list : attr - { $$ = 0; } + { $$ = new tree_classdef_attribute_list ($1); } | attr_list ',' attr - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; attr : identifier - { $$ = 0; } + { $$ = new tree_classdef_attribute ($1); } | identifier '=' decl_param_init expression - { $$ = 0; } + { + lexer.looking_at_initializer_expression = false; + $$ = new tree_classdef_attribute ($1, $4); + } | EXPR_NOT identifier - { $$ = 0; } + { $$ = new tree_classdef_attribute ($2, false); } ; -opt_superclasses +opt_superclass_list : // empty { $$ = 0; } - | superclasses - { $$ = 0; } + | superclass_list + { $$ = $1; } ; -superclasses : EXPR_LT identifier '.' identifier - { $$ = 0; } - | EXPR_LT identifier - { $$ = 0; } - | superclasses EXPR_AND identifier '.' identifier - { $$ = 0; } - | superclasses EXPR_AND identifier - { $$ = 0; } +superclass_list : EXPR_LT + { lexer.enable_fq_identifier (); } + superclass + { $$ = new tree_classdef_superclass_list ($3); } + | superclass_list EXPR_AND + { lexer.enable_fq_identifier (); } + superclass + { + $1->append ($4); + $$ = $1; + } + ; + +superclass : FQ_IDENT + { $$ = new tree_classdef_superclass ($1->text ()); } ; class_body : properties_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | methods_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | events_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | enum_block - { $$ = 0; } + { $$ = new tree_classdef_body ($1); } | class_body opt_sep properties_block - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } | class_body opt_sep methods_block - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } | class_body opt_sep events_block - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } | class_body opt_sep enum_block - { $$ = 0; } - ; - -properties_beg : PROPERTIES stash_comment - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; properties_block - : properties_beg opt_attr_list opt_sep properties_list opt_sep END - { $$ = 0; } + : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END + { + if (! ($$ = parser.make_classdef_properties_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_properties_block delete $3 and $5. + ABORT_PARSE; + } + } + | PROPERTIES stash_comment opt_attr_list opt_sep END + { + if (! ($$ = parser.make_classdef_properties_block + ($1, $3, 0, $5, $2))) + { + // make_classdef_properties_block delete $3. + ABORT_PARSE; + } + } ; -properties_list +property_list : class_property - { $$ = 0; } - | properties_list opt_sep class_property - { $$ = 0; } + { $$ = new tree_classdef_property_list ($1); } + | property_list opt_sep class_property + { + $1->append ($3); + $$ = $1; + } ; class_property : identifier - { $$ = 0; } + { $$ = new tree_classdef_property ($1); } | identifier '=' decl_param_init expression ';' - { $$ = 0; } + { + lexer.looking_at_initializer_expression = false; + $$ = new tree_classdef_property ($1, $4); + } ; -methods_beg : METHODS stash_comment - { $$ = 0; } +methods_block : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END + { + if (! ($$ = parser.make_classdef_methods_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_methods_block deleted $3 and $5. + ABORT_PARSE; + } + } + | METHODS stash_comment opt_attr_list opt_sep END + { + if (! ($$ = parser.make_classdef_methods_block + ($1, $3, 0, $5, $2))) + { + // make_classdef_methods_block deleted $3. + ABORT_PARSE; + } + } ; - -methods_block : methods_beg opt_attr_list opt_sep methods_list opt_sep END - { $$ = 0; } + ; + +method_decl1 : identifier + { + if (! ($$ = parser.start_classdef_external_method ($1, 0))) + ABORT_PARSE; + } + | identifier param_list + { + if (! ($$ = parser.start_classdef_external_method ($1, $2))) + ABORT_PARSE; + } ; -methods_list : function - { $$ = 0; } - | methods_list opt_sep function - { $$ = 0; } +method_decl : stash_comment method_decl1 + { $$ = parser.finish_classdef_external_method ($2, 0, $1); } + | stash_comment return_list '=' + { + lexer.defining_func++; + lexer.parsed_function_name.push (false); + } + method_decl1 + { + lexer.defining_func--; + lexer.parsed_function_name.pop (); + $$ = parser.finish_classdef_external_method ($5, $2, $1); + } + ; + +method : method_decl + { $$ = $1; } + | function + { $$ = $1; } ; -events_beg : EVENTS stash_comment - { $$ = 0; } +methods_list : method + { + octave_value fcn; + if ($1) + fcn = $1->function (); + delete $1; + $$ = new tree_classdef_methods_list (fcn); + } + | methods_list opt_sep method + { + octave_value fcn; + if ($3) + fcn = $3->function (); + delete $3; + + $1->append (fcn); + $$ = $1; + } ; -events_block : events_beg opt_attr_list opt_sep events_list opt_sep END - { $$ = 0; } +events_block : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END + { + if (! ($$ = parser.make_classdef_events_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_events_block deleted $3 and $5. + ABORT_PARSE; + } + } + | EVENTS stash_comment opt_attr_list opt_sep END + { + if (! ($$ = parser.make_classdef_events_block + ($1, $3, 0, $5, $2))) + { + // make_classdef_events_block deleted $3. + ABORT_PARSE; + } + } ; events_list : class_event - { $$ = 0; } + { $$ = new tree_classdef_events_list ($1); } | events_list opt_sep class_event - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; class_event : identifier - { $$ = 0; } + { $$ = new tree_classdef_event ($1); } ; -enum_beg : ENUMERATION stash_comment - { $$ = 0; } - ; - -enum_block : enum_beg opt_attr_list opt_sep enum_list opt_sep END - { $$ = 0; } +enum_block : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END + { + if (! ($$ = parser.make_classdef_enum_block + ($1, $3, $5, $7, $2))) + { + // make_classdef_enum_block deleted $3 and $5. + ABORT_PARSE; + } + } + | ENUMERATION stash_comment opt_attr_list opt_sep END + { + if (! ($$ = parser.make_classdef_enum_block + ($1, $3, 0, $5, $2))) + { + // make_classdef_enum_block deleted $3. + ABORT_PARSE; + } + } ; enum_list : class_enum - { $$ = 0; } + { $$ = new tree_classdef_enum_list ($1); } | enum_list opt_sep class_enum - { $$ = 0; } + { + $1->append ($3); + $$ = $1; + } ; class_enum : identifier '(' expression ')' - { $$ = 0; } + { $$ = new tree_classdef_enum ($1, $3); } ; // ============= @@ -1660,6 +1873,7 @@ curr_fcn_depth = 0; primary_fcn_scope = -1; curr_class_name = ""; + curr_package_name = ""; function_scopes.clear (); primary_fcn_ptr = 0; subfunction_names.clear (); @@ -1831,95 +2045,6 @@ } } -static tree_expression * -fold (tree_binary_expression *e) -{ - tree_expression *retval = e; - - unwind_protect frame; - - frame.protect_var (error_state); - frame.protect_var (warning_state); - - frame.protect_var (discard_error_messages); - frame.protect_var (discard_warning_messages); - - discard_error_messages = true; - discard_warning_messages = true; - - tree_expression *op1 = e->lhs (); - tree_expression *op2 = e->rhs (); - - if (op1->is_constant () && op2->is_constant ()) - { - octave_value tmp = e->rvalue1 (); - - if (! (error_state || warning_state)) - { - tree_constant *tc_retval - = new tree_constant (tmp, op1->line (), op1->column ()); - - std::ostringstream buf; - - tree_print_code tpc (buf); - - e->accept (tpc); - - tc_retval->stash_original_text (buf.str ()); - - delete e; - - retval = tc_retval; - } - } - - return retval; -} - -static tree_expression * -fold (tree_unary_expression *e) -{ - tree_expression *retval = e; - - unwind_protect frame; - - frame.protect_var (error_state); - frame.protect_var (warning_state); - - frame.protect_var (discard_error_messages); - frame.protect_var (discard_warning_messages); - - discard_error_messages = true; - discard_warning_messages = true; - - tree_expression *op = e->operand (); - - if (op->is_constant ()) - { - octave_value tmp = e->rvalue1 (); - - if (! (error_state || warning_state)) - { - tree_constant *tc_retval - = new tree_constant (tmp, op->line (), op->column ()); - - std::ostringstream buf; - - tree_print_code tpc (buf); - - e->accept (tpc); - - tc_retval->stash_original_text (buf.str ()); - - delete e; - - retval = tc_retval; - } - } - - return retval; -} - // Finish building a range. tree_expression * @@ -1975,8 +2100,6 @@ e->preserve_base (); delete e; - // FIXME -- need to attempt constant folding here - // too (we need a generic way to do that). retval = base; } } @@ -2189,10 +2312,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_binary_expression *e - = maybe_compound_binary_expression (op1, op2, l, c, t); - - return fold (e); + return maybe_compound_binary_expression (op1, op2, l, c, t); } // Build a boolean expression. @@ -2221,10 +2341,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_boolean_expression *e - = new tree_boolean_expression (op1, op2, l, c, t); - - return fold (e); + return new tree_boolean_expression (op1, op2, l, c, t); } // Build a prefix expression. @@ -2265,10 +2382,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_prefix_expression *e - = new tree_prefix_expression (op1, l, c, t); - - return fold (e); + return new tree_prefix_expression (op1, l, c, t); } // Build a postfix expression. @@ -2305,10 +2419,7 @@ int l = tok_val->line (); int c = tok_val->column (); - tree_postfix_expression *e - = new tree_postfix_expression (op1, l, c, t); - - return fold (e); + return new tree_postfix_expression (op1, l, c, t); } // Build an unwind-protect command. @@ -3002,6 +3113,274 @@ lexer.looking_at_parameter_list = false; } +tree_funcall * +octave_base_parser::make_superclass_ref (const std::string& method_nm, + const std::string& class_nm, + int l, int c) +{ + octave_value_list args; + + args(1) = class_nm; + args(0) = method_nm; + + octave_value fcn + = symbol_table::find_built_in_function ("__superclass_reference__"); + + return new tree_funcall (fcn, args); +} + +tree_funcall * +octave_base_parser::make_meta_class_query (const std::string& class_nm, + int l, int c) +{ + octave_value_list args; + + args(0) = class_nm; + + octave_value fcn + = symbol_table::find_built_in_function ("__meta_class_query__"); + + return new tree_funcall (fcn, args); +} + +// A CLASSDEF block defines a class that has a constructor and other +// methods, but it is not an executable command. Parsing the block +// makes some changes in the symbol table (inserting the constructor +// and methods, and adding to the list of known objects) and creates +// a parse tree containing meta information about the class. + +tree_classdef * +octave_base_parser::make_classdef (token *tok_val, + tree_classdef_attribute_list *a, + tree_identifier *id, + tree_classdef_superclass_list *sc, + tree_classdef_body *body, token *end_tok, + octave_comment_list *lc) +{ + tree_classdef *retval = 0; + + std::string cls_name = id->name (); + + std::string nm = lexer.fcn_file_name; + + size_t pos = nm.find_last_of (file_ops::dir_sep_chars ()); + + if (pos != std::string::npos) + nm = lexer.fcn_file_name.substr (pos+1); + + if (nm != cls_name) + bison_error ("invalid classdef definition, the class name must match the file name"); + else if (end_token_ok (end_tok, token::classdef_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + if (! body) + body = new tree_classdef_body (); + + retval = new tree_classdef (a, id, sc, body, lc, tc, + curr_package_name, l, c); + } + + if (! retval) + { + delete a; + delete id; + delete sc; + delete body; + } + + return retval; +} + +tree_classdef_properties_block * +octave_base_parser::make_classdef_properties_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_properties_block *retval = 0; + + if (end_token_ok (end_tok, token::properties_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + if (! plist) + plist = new tree_classdef_property_list (); + + retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c); + } + else + { + delete a; + delete plist; + } + + return retval; +} + +tree_classdef_methods_block * +octave_base_parser::make_classdef_methods_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_methods_block *retval = 0; + + if (end_token_ok (end_tok, token::methods_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + if (! mlist) + mlist = new tree_classdef_methods_list (); + + retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c); + } + else + { + delete a; + delete mlist; + } + + return retval; +} + +tree_classdef_events_block * +octave_base_parser::make_classdef_events_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_events_block *retval = 0; + + if (end_token_ok (end_tok, token::events_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + if (! elist) + elist = new tree_classdef_events_list (); + + retval = new tree_classdef_events_block (a, elist, lc, tc, l, c); + } + else + { + delete a; + delete elist; + } + + return retval; +} + +tree_classdef_enum_block * +octave_base_parser::make_classdef_enum_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + token *end_tok, + octave_comment_list *lc) +{ + tree_classdef_enum_block *retval = 0; + + if (end_token_ok (end_tok, token::enumeration_end)) + { + octave_comment_list *tc = lexer.comment_buf.get_comment (); + + int l = tok_val->line (); + int c = tok_val->column (); + + if (! elist) + elist = new tree_classdef_enum_list (); + + retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c); + } + else + { + delete a; + delete elist; + } + + return retval; +} + +octave_user_function* +octave_base_parser::start_classdef_external_method (tree_identifier *id, + tree_parameter_list *pl) +{ + octave_user_function* retval = 0; + + // External methods are only allowed within @-folders. In this case, + // curr_class_name will be non-empty. + + if (! curr_class_name.empty ()) + { + + std::string mname = id->name (); + + // Methods that cannot be declared outside the classdef file: + // - methods with '.' character (e.g. property accessors) + // - class constructor + // - `delete' + + if (mname.find_first_of (".") == std::string::npos + && mname != "delete" + && mname != curr_class_name) + { + // Create a dummy function that is used until the real method + // is loaded. + + retval = new octave_user_function (-1, pl); + + retval->stash_function_name (mname); + + int l = id->line (); + int c = id->column (); + + retval->stash_fcn_location (l, c); + } + else + bison_error ("invalid external method declaration, an external " + "method cannot be the class constructor, `delete' " + "or have a dot (.) character in its name"); + } + else + bison_error ("external methods are only allowed in @-folders"); + + if (! retval) + delete id; + + return retval; +} + +tree_function_def * +octave_base_parser::finish_classdef_external_method (octave_user_function *fcn, + tree_parameter_list *ret_list, + octave_comment_list *cl) +{ + if (ret_list) + fcn->define_ret_list (ret_list); + + if (cl) + fcn->stash_leading_comment (cl); + + int l = fcn->beginning_line (); + int c = fcn->beginning_column (); + + return new tree_function_def (fcn, l, c); +} + // Make an index expression. tree_index_expression * @@ -3024,7 +3403,8 @@ int l = expr->line (); int c = expr->column (); - expr->mark_postfix_indexed (); + if (! expr->is_postfix_indexed ()) + expr->set_postfix_index (type); if (expr->is_index_expression ()) { @@ -3051,6 +3431,9 @@ int l = expr->line (); int c = expr->column (); + if (! expr->is_postfix_indexed ()) + expr->set_postfix_index ('.'); + if (expr->is_index_expression ()) { tree_index_expression *tmp = static_cast (expr); @@ -3070,13 +3453,17 @@ // Make an indirect reference expression with dynamic field name. tree_index_expression * -octave_base_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt) +octave_base_parser::make_indirect_ref (tree_expression *expr, + tree_expression *elt) { tree_index_expression *retval = 0; int l = expr->line (); int c = expr->column (); + if (! expr->is_postfix_indexed ()) + expr->set_postfix_index ('.'); + if (expr->is_index_expression ()) { tree_index_expression *tmp = static_cast (expr); @@ -3464,6 +3851,7 @@ static octave_function * parse_fcn_file (const std::string& full_file, const std::string& file, const std::string& dispatch_type, + const std::string& package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup, const std::string& warn_for) { @@ -3497,6 +3885,7 @@ octave_parser parser (ffile); parser.curr_class_name = dispatch_type; + parser.curr_package_name = package_name; parser.autoloading = autoload; parser.fcn_file_from_relative_lookup = relative_lookup; @@ -3511,20 +3900,37 @@ fcn_ptr = parser.primary_fcn_ptr; - if (fcn_ptr) + if (status == 0) { - fcn_ptr->maybe_relocate_end (); - - if (parser.parsing_subfunctions) + if (parser.lexer.reading_classdef_file + && parser.classdef_object) { - if (! parser.endfunction_found) - parser.subfunction_names.reverse (); - - fcn_ptr->stash_subfunction_names (parser.subfunction_names); + // Convert parse tree for classdef object to + // meta.class info (and stash it in the symbol + // table?). Return pointer to constructor? + + if (fcn_ptr) + panic_impossible (); + + bool is_at_folder = ! dispatch_type.empty (); + + fcn_ptr = + parser.classdef_object->make_meta_class (is_at_folder); + } + else if (fcn_ptr) + { + fcn_ptr->maybe_relocate_end (); + + if (parser.parsing_subfunctions) + { + if (! parser.endfunction_found) + parser.subfunction_names.reverse (); + + fcn_ptr->stash_subfunction_names (parser.subfunction_names); + } } } - - if (status != 0) + else error ("parse error while reading file %s", full_file.c_str ()); } else if (require_file) @@ -3565,7 +3971,8 @@ symbol_found = true; octave_function *fcn - = parse_fcn_file (full_file, file, "", true, false, false, false, ""); + = parse_fcn_file (full_file, file, "", "", true, false, false, false, + ""); if (fcn) { @@ -3629,6 +4036,7 @@ octave_function * load_fcn_from_file (const std::string& file_name, const std::string& dir_name, const std::string& dispatch_type, + const std::string& package_name, const std::string& fcn_name, bool autoload) { octave_function *retval = 0; @@ -3676,7 +4084,8 @@ // to get the help-string to use. octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2), - nm, dispatch_type, false, + nm, dispatch_type, + package_name, false, autoload, autoload, relative_lookup, ""); @@ -3688,13 +4097,14 @@ } else if (len > 2) { - retval = parse_fcn_file (file, nm, dispatch_type, true, autoload, - autoload, relative_lookup, ""); + retval = parse_fcn_file (file, nm, dispatch_type, package_name, true, + autoload, autoload, relative_lookup, ""); } if (retval) { retval->stash_dir_name (dir_name); + retval->stash_package_name (package_name); if (retval->is_user_function ()) { @@ -3904,7 +4314,7 @@ if (! error_state) { octave_function *fcn = parse_fcn_file (file_full_name, file_name, - "", require_file, true, + "", "", require_file, true, false, false, warn_for); if (! error_state) @@ -4635,7 +5045,7 @@ if (nargin == 2) octave_stdout << "parsing " << full_file << std::endl; - octave_function *fcn = parse_fcn_file (full_file, file, "", + octave_function *fcn = parse_fcn_file (full_file, file, "", "", true, false, false, false, "__parse_file__"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/octave.gperf --- a/libinterp/parse-tree/octave.gperf Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/octave.gperf Sun May 25 10:29:05 2014 -0700 @@ -64,7 +64,6 @@ properties_kw, return_kw, set_kw, - static_kw, switch_kw, try_kw, until_kw, @@ -111,7 +110,6 @@ properties, PROPERTIES, properties_kw return, FUNC_RET, return_kw set, SET, set_kw -static, PERSISTENT, static_kw switch, SWITCH, switch_kw try, TRY, try_kw until, UNTIL, until_kw diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/parse.h Sun May 25 10:29:05 2014 -0700 @@ -43,6 +43,18 @@ class tree_argument_list; class tree_array_list; class tree_cell; +class tree_classdef; +class tree_classdef_attribute_list; +class tree_classdef_body; +class tree_classdef_enum_block; +class tree_classdef_enum_list; +class tree_classdef_events_block; +class tree_classdef_events_list; +class tree_classdef_methods_block; +class tree_classdef_methods_list; +class tree_classdef_properties_block; +class tree_classdef_property_list; +class tree_classdef_superclass_list; class tree_colon_expression; class tree_command; class tree_constant; @@ -50,6 +62,7 @@ class tree_decl_init_list; class tree_expression; class tree_fcn_handle; +class tree_funcall; class tree_function_def; class tree_identifier; class tree_if_clause; @@ -92,6 +105,7 @@ load_fcn_from_file (const std::string& file_name, const std::string& dir_name = std::string (), const std::string& dispatch_type = std::string (), + const std::string& package_name = std::string (), const std::string& fcn_name = std::string (), bool autoload = false); @@ -136,9 +150,9 @@ autoloading (false), fcn_file_from_relative_lookup (false), parsing_subfunctions (false), max_fcn_depth (0), curr_fcn_depth (0), primary_fcn_scope (-1), - curr_class_name (), function_scopes (), primary_fcn_ptr (0), - subfunction_names (), stmt_list (0), - lexer (lxr) + curr_class_name (), curr_package_name (), function_scopes (), + primary_fcn_ptr (0), subfunction_names (), classdef_object (0), + stmt_list (0), lexer (lxr) { } ~octave_base_parser (void); @@ -284,6 +298,54 @@ void recover_from_parsing_function (void); + tree_funcall * + make_superclass_ref (const std::string& method_nm, + const std::string& class_nm, + int l, int c); + + tree_funcall * + make_meta_class_query (const std::string& class_nm, + int l, int c); + + tree_classdef * + make_classdef (token *tok_val, tree_classdef_attribute_list *a, + tree_identifier *id, tree_classdef_superclass_list *sc, + tree_classdef_body *body, token *end_tok, + octave_comment_list *lc); + + tree_classdef_properties_block * + make_classdef_properties_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + token *end_tok, octave_comment_list *lc); + + tree_classdef_methods_block * + make_classdef_methods_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + token *end_tok, octave_comment_list *lc); + + tree_classdef_events_block * + make_classdef_events_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, + token *end_tok, octave_comment_list *lc); + + tree_classdef_enum_block * + make_classdef_enum_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + token *end_tok, octave_comment_list *lc); + + octave_user_function * + start_classdef_external_method (tree_identifier *id, + tree_parameter_list *pl); + + tree_function_def * + finish_classdef_external_method (octave_user_function *fcn, + tree_parameter_list *ret_list, + octave_comment_list *cl); + // Make an index expression. tree_index_expression * make_index_expression (tree_expression *expr, @@ -372,6 +434,10 @@ // constructors. std::string curr_class_name; + // Name of the current package when we are parsing an element contained + // in a package directory (+-directory). + std::string curr_package_name; + // A stack holding the nested function scopes being parsed. // We don't use std::stack, because we want the clear method. Also, we // must access one from the top @@ -385,6 +451,9 @@ // file. Eventually stashed in the primary function object. std::list subfunction_names; + // Pointer to the classdef object we just parsed, if any. + tree_classdef *classdef_object; + // Result of parsing input. tree_statement_list *stmt_list; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-all.h --- a/libinterp/parse-tree/pt-all.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-all.h Sun May 25 10:29:05 2014 -0700 @@ -30,6 +30,7 @@ #include "pt-binop.h" #include "pt-cbinop.h" #include "pt-check.h" +#include "pt-classdef.h" #include "pt-cmd.h" #include "pt-colon.h" #include "pt-const.h" @@ -37,6 +38,7 @@ #include "pt-except.h" #include "pt-exp.h" #include "pt-fcn-handle.h" +#include "pt-funcall.h" #include "pt-id.h" #include "pt-idx.h" #include "pt-jump.h" diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-bp.cc --- a/libinterp/parse-tree/pt-bp.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-bp.cc Sun May 25 10:29:05 2014 -0700 @@ -293,6 +293,12 @@ } void +tree_breakpoint::visit_funcall (tree_funcall&) +{ + panic_impossible (); +} + +void tree_breakpoint::visit_parameter_list (tree_parameter_list&) { panic_impossible (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-bp.h --- a/libinterp/parse-tree/pt-bp.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-bp.h Sun May 25 10:29:05 2014 -0700 @@ -106,6 +106,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-cbinop.cc --- a/libinterp/parse-tree/pt-cbinop.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-cbinop.cc Sun May 25 10:29:05 2014 -0700 @@ -162,7 +162,8 @@ maybe_compound_binary_expression (tree_expression *a, tree_expression *b, int l, int c, octave_value::binary_op t) { - tree_expression *ca = a, *cb = b; + tree_expression *ca = a; + tree_expression *cb = b; octave_value::compound_binary_op ct; switch (t) diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-check.cc --- a/libinterp/parse-tree/pt-check.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-check.cc Sun May 25 10:29:05 2014 -0700 @@ -357,6 +357,11 @@ } void +tree_checker::visit_funcall (tree_funcall& /* fc */) +{ +} + +void tree_checker::visit_parameter_list (tree_parameter_list& lst) { tree_parameter_list::iterator p = lst.begin (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-check.h --- a/libinterp/parse-tree/pt-check.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-check.h Sun May 25 10:29:05 2014 -0700 @@ -91,6 +91,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-classdef.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-classdef.cc Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,259 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ov-classdef.h" +#include "pt-classdef.h" + +// Classdef attribute + +void +tree_classdef_attribute::accept (tree_walker& tw) +{ + tw.visit_classdef_attribute (*this); +} + +// Classdef attribute_list + +tree_classdef_attribute_list::~tree_classdef_attribute_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_attribute_list::accept (tree_walker& tw) +{ + tw.visit_classdef_attribute_list (*this); +} + +// Classdef superclass + +void +tree_classdef_superclass::accept (tree_walker& tw) +{ + tw.visit_classdef_superclass (*this); +} + +// Classdef superclass_list + +tree_classdef_superclass_list::~tree_classdef_superclass_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_superclass_list::accept (tree_walker& tw) +{ + tw.visit_classdef_superclass_list (*this); +} + +// Classdef property + +void +tree_classdef_property::accept (tree_walker& tw) +{ + tw.visit_classdef_property (*this); +} + +// Classdef property_list + +tree_classdef_property_list::~tree_classdef_property_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_property_list::accept (tree_walker& tw) +{ + tw.visit_classdef_property_list (*this); +} + +// Classdef properties_block + +void +tree_classdef_properties_block::accept (tree_walker& tw) +{ + tw.visit_classdef_properties_block (*this); +} + +// Classdef methods_list + +void +tree_classdef_methods_list::accept (tree_walker& tw) +{ + tw.visit_classdef_methods_list (*this); +} + +// Classdef methods_block + +void +tree_classdef_methods_block::accept (tree_walker& tw) +{ + tw.visit_classdef_methods_block (*this); +} + +// Classdef event + +void +tree_classdef_event::accept (tree_walker& tw) +{ + tw.visit_classdef_event (*this); +} + +// Classdef events_list + +tree_classdef_events_list::~tree_classdef_events_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_events_list::accept (tree_walker& tw) +{ + tw.visit_classdef_events_list (*this); +} + +// Classdef events_block + +void +tree_classdef_events_block::accept (tree_walker& tw) +{ + tw.visit_classdef_events_block (*this); +} + +// Classdef enum + +void +tree_classdef_enum::accept (tree_walker& tw) +{ + tw.visit_classdef_enum (*this); +} + +// Classdef enum_list + +tree_classdef_enum_list::~tree_classdef_enum_list (void) +{ + while (! empty ()) + { + iterator p = begin (); + delete *p; + erase (p); + } +} + +void +tree_classdef_enum_list::accept (tree_walker& tw) +{ + tw.visit_classdef_enum_list (*this); +} + +// Classdef enum_block + +void +tree_classdef_enum_block::accept (tree_walker& tw) +{ + tw.visit_classdef_enum_block (*this); +} + +// Classdef body + +tree_classdef_body::~tree_classdef_body (void) +{ + while (! properties_lst.empty ()) + { + properties_list_iterator p = properties_lst.begin (); + delete *p; + properties_lst.erase (p); + } + + while (! methods_lst.empty ()) + { + methods_list_iterator p = methods_lst.begin (); + delete *p; + methods_lst.erase (p); + } + + while (! events_lst.empty ()) + { + events_list_iterator p = events_lst.begin (); + delete *p; + events_lst.erase (p); + } + + while (! enum_lst.empty ()) + { + enum_list_iterator p = enum_lst.begin (); + delete *p; + enum_lst.erase (p); + } +} + +// Classdef + +octave_function* +tree_classdef::make_meta_class (bool is_at_folder) +{ + octave_value retval; + cdef_class cls = cdef_class::make_meta_class (this, is_at_folder); + + if (cls.ok ()) + return cls.get_constructor_function (); + + return 0; +} + +tree_classdef * +tree_classdef::dup (symbol_table::scope_id, + symbol_table::context_id) const +{ + // FIXME + return 0; +} + +void +tree_classdef::accept (tree_walker& tw) +{ + tw.visit_classdef (*this); +} diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-classdef.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-classdef.h Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,653 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if !defined (octave_tree_classdef_h) +#define octave_tree_classdef_h 1 + +class octave_value; + +class tree_walker; + +#include "pt-cmd.h" +#include "pt-exp.h" +#include "pt-id.h" + +#include "base-list.h" + +#include + +class tree_classdef_attribute +{ +public: + + tree_classdef_attribute (tree_identifier *i = 0, tree_expression *e = 0) + : id (i), expr (e), neg (false) { } + + tree_classdef_attribute (tree_identifier *i, bool b) + : id (i), expr (0), neg (b) { } + + ~tree_classdef_attribute (void) + { + delete id; + delete expr; + } + + tree_identifier *ident (void) { return id; } + + tree_expression *expression (void) { return expr; } + + bool negate (void) { return neg; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + tree_expression *expr; + bool neg; + + // No copying! + + tree_classdef_attribute (const tree_classdef_attribute&); + + tree_classdef_attribute& operator = (const tree_classdef_attribute&); +}; + +class tree_classdef_attribute_list : public octave_base_list +{ +public: + + tree_classdef_attribute_list (void) { } + + tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); } + + tree_classdef_attribute_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_attribute_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_attribute_list (const tree_classdef_attribute_list&); + + tree_classdef_attribute_list& operator = (const tree_classdef_attribute_list&); +}; + +class tree_classdef_superclass +{ +public: + + tree_classdef_superclass (const std::string& cname) + : cls_name (cname) { } + + ~tree_classdef_superclass (void) { } + + std::string class_name (void) { return cls_name; } + + void accept (tree_walker&); + +private: + + std::string cls_name; + + // No copying! + + tree_classdef_superclass (const tree_classdef_superclass&); + + tree_classdef_superclass& operator = (const tree_classdef_superclass&); +}; + +class tree_classdef_superclass_list : public octave_base_list +{ +public: + + tree_classdef_superclass_list (void) { } + + tree_classdef_superclass_list (tree_classdef_superclass *sc) { append (sc); } + + tree_classdef_superclass_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_superclass_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_superclass_list (const tree_classdef_superclass_list&); + + tree_classdef_superclass_list& operator = (const tree_classdef_superclass_list&); +}; + +template +class tree_classdef_element : public tree +{ +public: + + tree_classdef_element (tree_classdef_attribute_list *a, + octave_base_list *elist, + octave_comment_list *lc, octave_comment_list *tc, + int l = -1, int c = -1) + : tree (l, c), attr_list (a), elt_list (elist), + lead_comm (lc), trail_comm (tc) + { } + + ~tree_classdef_element (void) + { + delete attr_list; + delete elt_list; + delete lead_comm; + delete trail_comm; + } + + tree_classdef_attribute_list *attribute_list (void) { return attr_list; } + + octave_base_list *element_list (void) { return elt_list; } + + octave_comment_list *leading_comment (void) { return lead_comm; } + + octave_comment_list *trailing_comment (void) { return trail_comm; } + + void accept (tree_walker&) { } + +private: + + // List of attributes that apply to this class. + tree_classdef_attribute_list *attr_list; + + // The list of objects contained in this block. + octave_base_list *elt_list; + + // Comment preceding the token marking the beginning of the block. + octave_comment_list *lead_comm; + + // Comment preceding END token. + octave_comment_list *trail_comm; + + // No copying! + + tree_classdef_element (const tree_classdef_element&); + + tree_classdef_element& operator = (const tree_classdef_element&); +}; + +class tree_classdef_property +{ +public: + + tree_classdef_property (tree_identifier *i = 0, tree_expression *e = 0) + : id (i), expr (e) { } + + ~tree_classdef_property (void) + { + delete id; + delete expr; + } + + tree_identifier *ident (void) { return id; } + + tree_expression *expression (void) { return expr; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + tree_expression *expr; + + // No copying! + + tree_classdef_property (const tree_classdef_property&); + + tree_classdef_property& operator = (const tree_classdef_property&); +}; + +class tree_classdef_property_list : public octave_base_list +{ +public: + + tree_classdef_property_list (void) { } + + tree_classdef_property_list (tree_classdef_property* p) { append (p); } + + tree_classdef_property_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_property_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_property_list (const tree_classdef_property_list&); + + tree_classdef_property_list& operator = (const tree_classdef_property_list&); +}; + +class tree_classdef_properties_block + : public tree_classdef_element +{ +public: + + tree_classdef_properties_block (tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + octave_comment_list *lc, + octave_comment_list *tc, + int l = -1, int c = -1) + : tree_classdef_element (a, plist, lc, tc, l, c) { } + + ~tree_classdef_properties_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_properties_block (const tree_classdef_properties_block&); + + tree_classdef_properties_block& operator = (const tree_classdef_properties_block&); +}; + +class tree_classdef_methods_list : public octave_base_list +{ +public: + + tree_classdef_methods_list (void) { } + + tree_classdef_methods_list (const octave_value& f) { append (f); } + + tree_classdef_methods_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_methods_list (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_methods_list (const tree_classdef_methods_list&); + + tree_classdef_methods_list& operator = (const tree_classdef_methods_list&); +}; + +class tree_classdef_methods_block : public tree_classdef_element +{ +public: + + tree_classdef_methods_block (tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + octave_comment_list *lc, + octave_comment_list *tc, int l = -1, int c = -1) + : tree_classdef_element (a, mlist, lc, tc, l, c) { } + + ~tree_classdef_methods_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_methods_block (const tree_classdef_methods_block&); + + tree_classdef_methods_block& operator = (const tree_classdef_methods_block&); +}; + +class tree_classdef_event +{ +public: + + tree_classdef_event (tree_identifier *i = 0) : id (i) { } + + ~tree_classdef_event (void) + { + delete id; + } + + tree_identifier *ident (void) { return id; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + + // No copying! + + tree_classdef_event (const tree_classdef_event&); + + tree_classdef_event& operator = (const tree_classdef_event&); +}; + +class tree_classdef_events_list : public octave_base_list +{ +public: + + tree_classdef_events_list (void) { } + + tree_classdef_events_list (tree_classdef_event *e) { append (e); } + + tree_classdef_events_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_events_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_events_list (const tree_classdef_events_list&); + + tree_classdef_events_list& operator = (const tree_classdef_events_list&); +}; + +class tree_classdef_events_block + : public tree_classdef_element +{ +public: + + tree_classdef_events_block (tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, + octave_comment_list *lc, + octave_comment_list *tc, int l = -1, int c = -1) + : tree_classdef_element (a, elist, lc, tc, l, c) { } + + ~tree_classdef_events_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_events_block (const tree_classdef_events_block&); + + tree_classdef_events_block& operator = (const tree_classdef_events_block&); +}; + +class tree_classdef_enum +{ +public: + + tree_classdef_enum (void) : id (0), expr (0) { } + + tree_classdef_enum (tree_identifier *i, tree_expression *e) + : id (i), expr (e) { } + + ~tree_classdef_enum (void) + { + delete id; + delete expr; + } + + tree_identifier *ident (void) { return id; } + + tree_expression *expression (void) { return expr; } + + void accept (tree_walker&); + +private: + + tree_identifier *id; + tree_expression *expr; + + // No copying! + + tree_classdef_enum (const tree_classdef_enum&); + + tree_classdef_enum& operator = (const tree_classdef_enum&); +}; + +class tree_classdef_enum_list : public octave_base_list +{ +public: + + tree_classdef_enum_list (void) { } + + tree_classdef_enum_list (tree_classdef_enum *e) { append (e); } + + tree_classdef_enum_list (const octave_base_list& a) + : octave_base_list (a) { } + + ~tree_classdef_enum_list (void); + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_enum_list (const tree_classdef_enum_list&); + + tree_classdef_enum_list& operator = (const tree_classdef_enum_list&); +}; + +class tree_classdef_enum_block + : public tree_classdef_element +{ +public: + + tree_classdef_enum_block (tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + octave_comment_list *lc, + octave_comment_list *tc, int l = -1, int c = -1) + : tree_classdef_element (a, elist, lc, tc, l, c) { } + + ~tree_classdef_enum_block (void) { } + + void accept (tree_walker&); + +private: + + // No copying! + + tree_classdef_enum_block (const tree_classdef_enum_block&); + + tree_classdef_enum_block& operator = (const tree_classdef_enum_block&); +}; + +class tree_classdef_body +{ +public: + + typedef std::list::iterator properties_list_iterator; + typedef std::list::const_iterator properties_list_const_iterator; + + typedef std::list::iterator methods_list_iterator; + typedef std::list::const_iterator methods_list_const_iterator; + + typedef std::list::iterator events_list_iterator; + typedef std::list::const_iterator events_list_const_iterator; + + typedef std::list::iterator enum_list_iterator; + typedef std::list::const_iterator enum_list_const_iterator; + + tree_classdef_body (void) + : properties_lst (), methods_lst (), events_lst (), enum_lst () { } + + tree_classdef_body (tree_classdef_properties_block *pb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (pb); + } + + tree_classdef_body (tree_classdef_methods_block *mb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (mb); + } + + tree_classdef_body (tree_classdef_events_block *evb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (evb); + } + + tree_classdef_body (tree_classdef_enum_block *enb) + : properties_lst (), methods_lst (), events_lst (), enum_lst () + { + append (enb); + } + + ~tree_classdef_body (void); + + void append (tree_classdef_properties_block *pb) + { + properties_lst.push_back (pb); + } + + void append (tree_classdef_methods_block *mb) + { + methods_lst.push_back (mb); + } + + void append (tree_classdef_events_block *evb) + { + events_lst.push_back (evb); + } + + void append (tree_classdef_enum_block *enb) + { + enum_lst.push_back (enb); + } + + std::list properties_list (void) + { + return properties_lst; + } + + std::list methods_list (void) + { + return methods_lst; + } + + std::list events_list (void) + { + return events_lst; + } + + std::list enum_list (void) + { + return enum_lst; + } + + void accept (tree_walker&); + +private: + + std::list properties_lst; + + std::list methods_lst; + + std::list events_lst; + + std::list enum_lst; + + // No copying! + + tree_classdef_body (const tree_classdef_body&); + + tree_classdef_body& operator = (const tree_classdef_body&); +}; + +// Classdef definition. + +class tree_classdef : public tree_command +{ +public: + + tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i, + tree_classdef_superclass_list *sc, + tree_classdef_body *b, octave_comment_list *lc, + octave_comment_list *tc, + const std::string& pn = std::string (), int l = -1, + int c = -1) + : tree_command (l, c), attr_list (a), id (i), + supclass_list (sc), element_list (b), lead_comm (lc), trail_comm (tc), + pack_name (pn) { } + + ~tree_classdef (void) + { + delete attr_list; + delete id; + delete supclass_list; + delete element_list; + delete lead_comm; + delete trail_comm; + } + + tree_classdef_attribute_list *attribute_list (void) { return attr_list; } + + tree_identifier *ident (void) { return id; } + + tree_classdef_superclass_list *superclass_list (void) { return supclass_list; } + + tree_classdef_body *body (void) { return element_list; } + + octave_comment_list *leading_comment (void) { return lead_comm; } + octave_comment_list *trailing_comment (void) { return trail_comm; } + + const std::string& package_name (void) const { return pack_name; } + + octave_function* make_meta_class (bool is_at_folder = false); + + tree_classdef *dup (symbol_table::scope_id scope, + symbol_table::context_id context) const; + + void accept (tree_walker& tw); + +private: + + tree_classdef_attribute_list *attr_list; + + tree_identifier *id; + + tree_classdef_superclass_list *supclass_list; + + tree_classdef_body *element_list; + + octave_comment_list *lead_comm; + octave_comment_list *trail_comm; + + std::string pack_name; + + // No copying! + + tree_classdef (const tree_classdef&); + + tree_classdef& operator = (const tree_classdef&); +}; + +#endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-eval.cc Sun May 25 10:29:05 2014 -0700 @@ -379,7 +379,8 @@ dim_vector dv = rhs.dims ().redim (2); - octave_idx_type nrows = dv(0), steps = dv(1); + octave_idx_type nrows = dv(0); + octave_idx_type steps = dv(1); if (steps > 0) { @@ -637,6 +638,12 @@ } void +tree_evaluator::visit_funcall (tree_funcall&) +{ + panic_impossible (); +} + +void tree_evaluator::visit_parameter_list (tree_parameter_list&) { panic_impossible (); @@ -1114,6 +1121,11 @@ if (error_state) return; +#if HAVE_LLVM + if (tree_jit::execute (cmd)) + return; +#endif + unwind_protect frame; frame.protect_var (in_loop_command); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-eval.h --- a/libinterp/parse-tree/pt-eval.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-eval.h Sun May 25 10:29:05 2014 -0700 @@ -102,6 +102,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-exp.h --- a/libinterp/parse-tree/pt-exp.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-exp.h Sun May 25 10:29:05 2014 -0700 @@ -40,7 +40,7 @@ public: tree_expression (int l = -1, int c = -1) - : tree (l, c), num_parens (0), postfix_indexed (false), + : tree (l, c), num_parens (0), postfix_index_type ('\0'), print_flag (false) { } virtual ~tree_expression (void) { } @@ -87,7 +87,9 @@ int paren_count (void) const { return num_parens; } - bool is_postfix_indexed (void) const { return postfix_indexed; } + bool is_postfix_indexed (void) const { return (postfix_index_type != '\0'); } + + char postfix_index (void) const { return postfix_index_type; } // Check if the result of the expression should be printed. // Should normally be used in conjunction with @@ -108,9 +110,9 @@ return this; } - tree_expression *mark_postfix_indexed (void) + tree_expression *set_postfix_index (char type) { - postfix_indexed = true; + postfix_index_type = type; return this; } @@ -123,7 +125,7 @@ virtual void copy_base (const tree_expression& e) { num_parens = e.num_parens; - postfix_indexed = e.postfix_indexed; + postfix_index_type = e.postfix_index_type; print_flag = e.print_flag; } @@ -137,9 +139,10 @@ // ==> 0 for expression e2 int num_parens; - // A flag that says whether this expression has an index associated - // with it. See the code in tree_identifier::rvalue for the rationale. - bool postfix_indexed; + // The first index type associated with this expression. This field + // is 0 (character '\0') if the expression has no associated index. + // See the code in tree_identifier::rvalue for the rationale. + char postfix_index_type; // Print result of rvalue for this expression? bool print_flag; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-funcall.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-funcall.cc Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,110 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "ov-fcn.h" +#include "pt-funcall.h" +#include "pt-walk.h" + +// Function call objects. + +void +tree_funcall::print (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + print_raw (os, pr_as_read_syntax, pr_orig_text); +} + +void +tree_funcall::print_raw (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + if (pr_orig_text) + { + os << original_text (); + } + else + { + octave_function *fp = fcn.function_value (); + std::string nm = fp ? fp->name () : std::string (""); + + os << nm << " ("; + + octave_idx_type len = args.length (); + for (octave_idx_type i = 0; i < len; i++) + { + args(i).print_raw (os, pr_as_read_syntax); + + if (i < len - 1) + os << ", "; + } + + os << ")"; + } +} + +tree_funcall * +tree_funcall::dup (symbol_table::scope_id, symbol_table::context_id) const +{ + tree_funcall *new_fc = new tree_funcall (fcn, args, line (), column ()); + + new_fc->copy_base (*new_fc); + + return new_fc; +} + +void +tree_funcall::accept (tree_walker& tw) +{ + tw.visit_funcall (*this); +} + +octave_value_list +tree_funcall::rvalue (int nargout) +{ + octave_value_list retval; + + retval = feval (fcn.function_value (), args, nargout); + + if (retval.length () == 1 && retval(0).is_function ()) + { + // The return object is a function. We may need to re-index it using the + // same logic as for identifier. This is primarily used for superclass + // references in classdef. + + octave_value val = retval(0); + octave_function *f = val.function_value (true); + + if (f && ! (is_postfix_indexed () + && f->is_postfix_index_handled (postfix_index ()))) + { + octave_value_list tmp_args; + + retval = val.do_multi_index_op (nargout, tmp_args); + } + } + + return retval; +} diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-funcall.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-funcall.h Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,98 @@ +/* + +Copyright (C) 2012-2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if !defined (octave_tree_funcall_h) +#define octave_tree_funcall_h 1 + +#include "ov.h" +#include "oct-obj.h" +#include "parse.h" +#include "pt-exp.h" + +// Function call. This class only represents function calls that have +// known functions (most useful for calls to built-in functions that +// are generated by the parser) and fixed argument lists, known at +// compile time. + +class +tree_funcall : public tree_expression +{ +public: + + tree_funcall (const octave_value& f, const octave_value_list& a, + int l = -1, int c = -1) + : tree_expression (l, c), fcn (f), args (a) + { + if (! fcn.is_function ()) + error ("tree_funcall: invalid function"); + } + + ~tree_funcall (void) { } + + bool has_magic_end (void) const { return false; } + + void print (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); + + void print_raw (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); + + tree_funcall *dup (symbol_table::scope_id, + symbol_table::context_id context) const; + + octave_value rvalue1 (int nargout) + { + octave_value retval; + + const octave_value_list tmp = rvalue (nargout); + + if (! tmp.empty ()) + retval = tmp(0); + + return retval; + } + + octave_value_list rvalue (int nargout); + + octave_value function (void) const { return fcn; } + + octave_value_list arguments (void) const { return args; } + + void accept (tree_walker& tw); + +private: + + // Function to call. Error if not a valid function at time of + // construction. + octave_value fcn; + + // Argument list. + octave_value_list args; + + // No copying! + + tree_funcall (const tree_funcall&); + + tree_funcall& operator = (const tree_funcall&); +}; + +#endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-id.cc --- a/libinterp/parse-tree/pt-id.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-id.cc Sun May 25 10:29:05 2014 -0700 @@ -76,13 +76,19 @@ // // If this identifier refers to a function, we need to know // whether it is indexed so that we can do the same thing - // for 'f' and 'f()'. If the index is present, return the - // function object and let tree_index_expression::rvalue - // handle indexing. Otherwise, arrange to call the function - // here, so that we don't return the function definition as - // a value. + // for 'f' and 'f()'. If the index is present and the function + // object declares it can handle it, return the function object + // and let tree_index_expression::rvalue handle indexing. + // Otherwise, arrange to call the function here, so that we don't + // return the function definition as a value. - if (val.is_function () && ! is_postfix_indexed ()) + octave_function *fcn = 0; + + if (val.is_function ()) + fcn = val.function_value (true); + + if (fcn && ! (is_postfix_indexed () + && fcn->is_postfix_index_handled (postfix_index ()))) { octave_value_list tmp_args; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-id.h --- a/libinterp/parse-tree/pt-id.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-id.h Sun May 25 10:29:05 2014 -0700 @@ -32,6 +32,7 @@ class tree_walker; +#include "oct-lvalue.h" #include "pt-bp.h" #include "pt-exp.h" #include "symtab.h" diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-idx.cc --- a/libinterp/parse-tree/pt-idx.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-idx.cc Sun May 25 10:29:05 2014 -0700 @@ -363,7 +363,7 @@ // that argument list so we can pass the appropriate // value to the built-in end function. - const octave_value_list tmp_list + octave_value_list tmp_list = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout); tmp = tmp_list.length () ? tmp_list(0) : octave_value (); @@ -375,6 +375,26 @@ if (error_state) break; + + if (tmp.is_function ()) + { + octave_function *fcn = tmp.function_value (true); + + if (fcn && ! fcn->is_postfix_index_handled (type[i])) + { + octave_value_list empty_args; + + tmp_list = tmp.do_multi_index_op (1, empty_args); + tmp = (tmp_list.length () + ? tmp_list(0) : octave_value ()); + + if (tmp.is_cs_list ()) + gripe_indexed_cs_list (); + + if (error_state) + break; + } + } } } @@ -412,8 +432,27 @@ } if (! error_state) - retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout, - lvalue_list); + { + retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout, + lvalue_list); + + octave_value val = retval.length () ? retval(0) : octave_value (); + + if (! error_state && val.is_function ()) + { + octave_function *fcn = val.function_value (true); + + if (fcn) + { + octave_value_list empty_args; + + retval = (lvalue_list + ? val.do_multi_index_op (nargout, empty_args, + lvalue_list) + : val.do_multi_index_op (nargout, empty_args)); + } + } + } } return retval; diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-mat.cc --- a/libinterp/parse-tree/pt-mat.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-mat.cc Sun May 25 10:29:05 2014 -0700 @@ -683,7 +683,8 @@ single_type_concat (Array& result, tm_const& tmp) { - octave_idx_type r = 0, c = 0; + octave_idx_type r = 0; + octave_idx_type c = 0; for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) { @@ -753,7 +754,8 @@ return; } - octave_idx_type ncols = row.length (), i = 0; + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; OCTAVE_LOCAL_BUFFER (Array, array_list, ncols); for (tm_row_const::iterator q = row.begin (); @@ -791,12 +793,14 @@ // Sparse matrices require preallocation for efficient indexing; besides, // only horizontal concatenation can be efficiently handled by indexing. // So we just cat all rows through liboctave, then cat the final column. - octave_idx_type nrows = tmp.length (), j = 0; + octave_idx_type nrows = tmp.length (); + octave_idx_type j = 0; OCTAVE_LOCAL_BUFFER (Sparse, sparse_row_list, nrows); for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) { tm_row_const row = *p; - octave_idx_type ncols = row.length (), i = 0; + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; OCTAVE_LOCAL_BUFFER (Sparse, sparse_list, ncols); for (tm_row_const::iterator q = row.begin (); @@ -829,12 +833,14 @@ return; } - octave_idx_type nrows = tmp.length (), j = 0; + octave_idx_type nrows = tmp.length (); + octave_idx_type j = 0; OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows); for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++) { tm_row_const row = *p; - octave_idx_type ncols = row.length (), i = 0; + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols); for (tm_row_const::iterator q = row.begin (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-pr-code.cc --- a/libinterp/parse-tree/pt-pr-code.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-pr-code.cc Sun May 25 10:29:05 2014 -0700 @@ -749,6 +749,18 @@ } void +tree_print_code::visit_funcall (tree_funcall& fc) +{ + indent (); + + print_parens (fc, "("); + + fc.print_raw (os, true, print_original_text); + + print_parens (fc, ")"); +} + +void tree_print_code::visit_parameter_list (tree_parameter_list& lst) { tree_parameter_list::iterator p = lst.begin (); @@ -1144,7 +1156,7 @@ indent (); - os << "until"; + os << "until "; tree_expression *expr = cmd.condition (); @@ -1188,10 +1200,7 @@ } } -// Each print_code() function should call this before printing -// anything. -// -// This doesn't need to be fast, but isn't there a better way? +// Each print_code() function should call this before printing anything. void tree_print_code::indent (void) @@ -1202,8 +1211,7 @@ { os << prefix; - for (int i = 0; i < curr_print_indent_level; i++) - os << " "; + os << std::string (curr_print_indent_level, ' '); beginning_of_line = false; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-pr-code.h --- a/libinterp/parse-tree/pt-pr-code.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-pr-code.h Sun May 25 10:29:05 2014 -0700 @@ -109,6 +109,8 @@ void visit_fcn_handle (tree_fcn_handle&); + void visit_funcall (tree_funcall&); + void visit_parameter_list (tree_parameter_list&); void visit_postfix_expression (tree_postfix_expression&); diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-select.cc --- a/libinterp/parse-tree/pt-select.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-select.cc Sun May 25 10:29:05 2014 -0700 @@ -123,7 +123,7 @@ { octave_value label_value = label->rvalue1 (); - if (! error_state && label_value.is_defined () ) + if (! error_state && label_value.is_defined ()) { if (label_value.is_cell ()) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/pt-walk.h --- a/libinterp/parse-tree/pt-walk.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/pt-walk.h Sun May 25 10:29:05 2014 -0700 @@ -52,6 +52,7 @@ class tree_no_op_command; class tree_constant; class tree_fcn_handle; +class tree_funcall; class tree_parameter_list; class tree_postfix_expression; class tree_prefix_expression; @@ -65,6 +66,24 @@ class tree_while_command; class tree_do_until_command; +class tree_classdef_attribute; +class tree_classdef_attribute_list; +class tree_classdef_superclass; +class tree_classdef_superclass_list; +class tree_classdef_property; +class tree_classdef_property_list; +class tree_classdef_properties_block; +class tree_classdef_methods_list; +class tree_classdef_methods_block; +class tree_classdef_event; +class tree_classdef_events_list; +class tree_classdef_events_block; +class tree_classdef_enum; +class tree_classdef_enum_list; +class tree_classdef_enum_block; +class tree_classdef_body; +class tree_classdef; + class tree_walker { @@ -158,6 +177,9 @@ visit_fcn_handle (tree_fcn_handle&) = 0; virtual void + visit_funcall (tree_funcall&) = 0; + + virtual void visit_parameter_list (tree_parameter_list&) = 0; virtual void @@ -193,6 +215,57 @@ virtual void visit_do_until_command (tree_do_until_command&) = 0; + virtual void + visit_classdef_attribute (tree_classdef_attribute&) { } /* = 0; */ + + virtual void + visit_classdef_attribute_list (tree_classdef_attribute_list&) { } /* = 0; */ + + virtual void + visit_classdef_superclass (tree_classdef_superclass&) { } /* = 0; */ + + virtual void + visit_classdef_superclass_list (tree_classdef_superclass_list&) { } /* = 0; */ + + virtual void + visit_classdef_property (tree_classdef_property&) { } /* = 0; */ + + virtual void + visit_classdef_property_list (tree_classdef_property_list&) { } /* = 0; */ + + virtual void + visit_classdef_properties_block (tree_classdef_properties_block&) { } /* = 0; */ + + virtual void + visit_classdef_methods_list (tree_classdef_methods_list&) { } /* = 0; */ + + virtual void + visit_classdef_methods_block (tree_classdef_methods_block&) { } /* = 0; */ + + virtual void + visit_classdef_event (tree_classdef_event&) { } /* = 0; */ + + virtual void + visit_classdef_events_list (tree_classdef_events_list&) { } /* = 0; */ + + virtual void + visit_classdef_events_block (tree_classdef_events_block&) { } /* = 0; */ + + virtual void + visit_classdef_enum (tree_classdef_enum&) { } /* = 0; */ + + virtual void + visit_classdef_enum_list (tree_classdef_enum_list&) { } /* = 0; */ + + virtual void + visit_classdef_enum_block (tree_classdef_enum_block&) { } /* = 0; */ + + virtual void + visit_classdef_body (tree_classdef_body&) { } /* = 0; */ + + virtual void + visit_classdef (tree_classdef&) { } /* = 0; */ + protected: tree_walker (void) { } diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/token.cc --- a/libinterp/parse-tree/token.cc Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/token.cc Sun May 25 10:29:05 2014 -0700 @@ -97,38 +97,29 @@ sr = s; } -token::token (int tv, symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l, int c) +token::token (int tv, const std::string& mth, const std::string& cls, + int l, int c) { maybe_cmd = false; tspc = false; line_num = l; column_num = c; tok_val = tv; - type_tag = meta_rec_token; - mc.cr = cls; - mc.pr = pkg; -} - -token::token (int tv, symbol_table::symbol_record *mth, - symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l, int c) -{ - maybe_cmd = false; - tspc = false; - line_num = l; - column_num = c; - tok_val = tv; - type_tag = scls_rec_token; - sc.mr = mth; - sc.cr = cls; - sc.pr = pkg; + type_tag = scls_name_token; + sc.method_nm = new std::string (mth); + sc.class_nm = new std::string (cls); } token::~token (void) { if (type_tag == string_token) delete str; + + if (type_tag == scls_name_token) + { + delete sc.method_nm; + delete sc.class_nm; + } } std::string @@ -172,39 +163,18 @@ return sr; } -symbol_table::symbol_record * -token::method_rec (void) +std::string +token::superclass_method_name (void) { - assert (type_tag == scls_rec_token); - return sc.mr; -} - -symbol_table::symbol_record * -token::class_rec (void) -{ - assert (type_tag == scls_rec_token); - return sc.cr; + assert (type_tag == scls_name_token); + return *sc.method_nm; } -symbol_table::symbol_record * -token::package_rec (void) -{ - assert (type_tag == scls_rec_token); - return sc.pr; -} - -symbol_table::symbol_record * -token::meta_class_rec (void) +std::string +token::superclass_class_name (void) { - assert (type_tag == meta_rec_token); - return mc.cr; -} - -symbol_table::symbol_record * -token::meta_package_rec (void) -{ - assert (type_tag == meta_rec_token); - return mc.pr; + assert (type_tag == scls_name_token); + return *sc.class_nm; } std::string diff -r bd1fd4ed3d67 -r 888f8ce79bbe libinterp/parse-tree/token.h --- a/libinterp/parse-tree/token.h Sun May 25 10:26:18 2014 -0700 +++ b/libinterp/parse-tree/token.h Sun May 25 10:29:05 2014 -0700 @@ -40,8 +40,7 @@ double_token, ettype_token, sym_rec_token, - scls_rec_token, - meta_rec_token + scls_name_token, }; enum end_tok_type @@ -69,11 +68,8 @@ int l = -1, int c = -1); token (int tv, end_tok_type t, int l = -1, int c = -1); token (int tv, symbol_table::symbol_record *s, int l = -1, int c = -1); - token (int tv, symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l = -1, int c = -1); - token (int tv, symbol_table::symbol_record *mth, - symbol_table::symbol_record *cls, - symbol_table::symbol_record *pkg, int l = -1, int c = -1); + token (int tv, const std::string& mth, const std::string& cls, + int l = -1, int c = -1); ~token (void); @@ -106,12 +102,8 @@ end_tok_type ettype (void) const; symbol_table::symbol_record *sym_rec (void); - symbol_table::symbol_record *method_rec (void); - symbol_table::symbol_record *class_rec (void); - symbol_table::symbol_record *package_rec (void); - - symbol_table::symbol_record *meta_class_rec (void); - symbol_table::symbol_record *meta_package_rec (void); + std::string superclass_method_name (void); + std::string superclass_class_name (void); std::string text_rep (void); @@ -137,15 +129,9 @@ symbol_table::symbol_record *sr; struct { - symbol_table::symbol_record *mr; - symbol_table::symbol_record *cr; - symbol_table::symbol_record *pr; + std::string *method_nm; + std::string *class_nm; } sc; - struct - { - symbol_table::symbol_record *cr; - symbol_table::symbol_record *pr; - } mc; }; std::string orig_text; }; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/Array.cc --- a/liboctave/array/Array.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/Array.cc Sun May 25 10:29:05 2014 -0700 @@ -688,9 +688,9 @@ } else { - octave_idx_type sd = sext[lev-1]; - octave_idx_type dd = dext[lev-1]; - octave_idx_type k; + octave_idx_type sd, dd, k; + sd = sext[lev-1]; + dd = dext[lev-1]; for (k = 0; k < cext[lev]; k++) do_resize_fill (src + k * sd, dest + k * dd, rfv, lev - 1); @@ -2571,9 +2571,8 @@ d.xelem (i) = elem (i, i); } } - else - (*current_liboctave_error_handler) - ("diag: requested diagonal out of range"); + else // Matlab returns [] 0x1 for out-of-range diagonal + d.resize (dim_vector (0, 1)); } else { diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/CDiagMatrix.cc --- a/liboctave/array/CDiagMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/CDiagMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -383,7 +383,7 @@ } ComplexDiagMatrix -ComplexDiagMatrix::pseudo_inverse (void) const +ComplexDiagMatrix::pseudo_inverse (double tol) const { octave_idx_type r = rows (); octave_idx_type c = cols (); @@ -393,10 +393,11 @@ for (octave_idx_type i = 0; i < len; i++) { - if (elem (i, i) != 0.0) + double val = std::abs (elem (i, i)); + if (val < tol || val == 0.0) + retval.elem (i, i) = 0.0; + else retval.elem (i, i) = 1.0 / elem (i, i); - else - retval.elem (i, i) = 0.0; } return retval; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/CDiagMatrix.h --- a/liboctave/array/CDiagMatrix.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/CDiagMatrix.h Sun May 25 10:29:05 2014 -0700 @@ -116,7 +116,7 @@ ComplexDiagMatrix inverse (octave_idx_type& info) const; ComplexDiagMatrix inverse (void) const; - ComplexDiagMatrix pseudo_inverse (void) const; + ComplexDiagMatrix pseudo_inverse (double tol = 0.0) const; bool all_elements_are_real (void) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/CMatrix.cc --- a/liboctave/array/CMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/CMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -1722,7 +1722,7 @@ double ComplexMatrix::rcond (MatrixType &mattype) const { - double rcon; + double rcon = octave_NaN; octave_idx_type nr = rows (); octave_idx_type nc = cols (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/CSparse.cc --- a/liboctave/array/CSparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/CSparse.cc Sun May 25 10:29:05 2014 -0700 @@ -1118,7 +1118,6 @@ { // Matrix is either singular or not positive definite mattype.mark_as_unsymmetric (); - typ = MatrixType::Full; } } @@ -4529,7 +4528,7 @@ m_band(ridx (i) - j + n_lower + n_upper, j) = data (i); // Calculate the norm of the matrix, for later use. - double anorm; + double anorm = 0.0; if (calc_cond) { for (octave_idx_type j = 0; j < nr; j++) @@ -4811,7 +4810,7 @@ m_band(ridx (i) - j + n_lower + n_upper, j) = data (i); // Calculate the norm of the matrix, for later use. - double anorm; + double anorm = 0.0; if (calc_cond) { for (octave_idx_type j = 0; j < nr; j++) @@ -5096,7 +5095,7 @@ m_band(ridx (i) - j + n_lower + n_upper, j) = data (i); // Calculate the norm of the matrix, for later use. - double anorm; + double anorm = 0.0; if (calc_cond) { for (octave_idx_type j = 0; j < nr; j++) @@ -5383,7 +5382,7 @@ m_band(ridx (i) - j + n_lower + n_upper, j) = data (i); // Calculate the norm of the matrix, for later use. - double anorm; + double anorm = 0.0; if (calc_cond) { for (octave_idx_type j = 0; j < nr; j++) @@ -7688,87 +7687,85 @@ { SparseComplexMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0) - return SparseComplexMatrix (a_nr, a_nc); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + Complex tmp = xmin (a.data (ja), 0.); + if (tmp != 0.) { - Complex tmp = xmin (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) + { + Complex tmp = xmin (0., b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmin (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + Complex tmp = xmin (a.data (ja), b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmin (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + } return r; } @@ -7808,91 +7805,85 @@ { SparseComplexMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr == 0 || b_nc == 0) - return SparseComplexMatrix (a_nr, a_nc); - if (a.nnz () == 0) - return SparseComplexMatrix (b); - if (b.nnz () == 0) - return SparseComplexMatrix (a); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + Complex tmp = xmax (a.data (ja), 0.); + if (tmp != 0.) { - Complex tmp = xmax (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) + { + Complex tmp = xmax (0., b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmax (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + Complex tmp = xmax (a.data (ja), b.data (jb)); + if (tmp != 0.) { - Complex tmp = xmax (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("max", a_nr, a_nc, b_nr, b_nc); + } return r; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/DiagArray2.cc --- a/liboctave/array/DiagArray2.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/DiagArray2.cc Sun May 25 10:29:05 2014 -0700 @@ -66,9 +66,8 @@ d = Array (dim_vector (std::min (cols () - k, rows ()), 1), T ()); else if (k < 0 && -k < rows ()) d = Array (dim_vector (std::min (rows () + k, cols ()), 1), T ()); - else - (*current_liboctave_error_handler) - ("diag: requested diagonal out of range"); + else // Matlab returns [] 0x1 for out-of-range diagonal + d.resize (dim_vector (0, 1)); return d; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/MSparse.cc --- a/liboctave/array/MSparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/MSparse.cc Sun May 25 10:29:05 2014 -0700 @@ -68,7 +68,7 @@ octave_idx_type jb_max = b.cidx (i+1); bool jb_lt_max = jb < jb_max; - while (ja_lt_max || jb_lt_max ) + while (ja_lt_max || jb_lt_max) { octave_quit (); if ((! jb_lt_max) || @@ -80,8 +80,8 @@ ja++; ja_lt_max= ja < ja_max; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) { r.ridx (jx) = b.ridx (jb); r.data (jx) = op (0., b.data (jb)); @@ -340,7 +340,7 @@ octave_idx_type jb_max = b.cidx (i+1); bool jb_lt_max = jb < jb_max; - while (ja_lt_max || jb_lt_max ) + while (ja_lt_max || jb_lt_max) { octave_quit (); if ((! jb_lt_max) || @@ -352,8 +352,8 @@ ja++; ja_lt_max= ja < ja_max; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) { r.ridx (jx) = b.ridx (jb); r.data (jx) = op (0., b.data (jb)); @@ -462,7 +462,7 @@ octave_idx_type jb_max = b.cidx (i+1); bool jb_lt_max = jb < jb_max; - while (ja_lt_max || jb_lt_max ) + while (ja_lt_max || jb_lt_max) { octave_quit (); if ((! jb_lt_max) || @@ -470,8 +470,8 @@ { ja++; ja_lt_max= ja < ja_max; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) { jb++; jb_lt_max= jb < jb_max; } @@ -569,7 +569,7 @@ gripe_nonconformant ("quotient", a_nr, a_nc, b_nr, b_nc); else { - r = MSparse( a_nr, a_nc, (Zero / Zero)); + r = MSparse (a_nr, a_nc, (Zero / Zero)); for (octave_idx_type i = 0 ; i < a_nc ; i++) { @@ -581,7 +581,7 @@ octave_idx_type jb_max = b.cidx (i+1); bool jb_lt_max = jb < jb_max; - while (ja_lt_max || jb_lt_max ) + while (ja_lt_max || jb_lt_max) { octave_quit (); if ((! jb_lt_max) || @@ -590,8 +590,8 @@ r.elem (a.ridx (ja),i) = a.data (ja) / Zero; ja++; ja_lt_max= ja < ja_max; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) { r.elem (b.ridx (jb),i) = Zero / b.data (jb); jb++; jb_lt_max= jb < jb_max; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/MatrixType.cc --- a/liboctave/array/MatrixType.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/MatrixType.cc Sun May 25 10:29:05 2014 -0700 @@ -119,7 +119,7 @@ MatrixType::matrix_type matrix_complex_probe (const MArray >& a) { - MatrixType::matrix_type typ; + MatrixType::matrix_type typ = MatrixType::Unknown; octave_idx_type nrows = a.rows (); octave_idx_type ncols = a.cols (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/Sparse.cc --- a/liboctave/array/Sparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/Sparse.cc Sun May 25 10:29:05 2014 -0700 @@ -2435,7 +2435,7 @@ if (elem (i, i+k) != 0.) nel++; } - else if ( k < 0) + else if (k < 0) { for (octave_idx_type i = 0; i < ndiag; i++) if (elem (i-k, i) != 0.) @@ -2465,7 +2465,7 @@ } } } - else if ( k < 0) + else if (k < 0) { for (octave_idx_type i = 0; i < ndiag; i++) { @@ -2491,8 +2491,15 @@ } } else - (*current_liboctave_error_handler) - ("diag: requested diagonal out of range"); + { + // Matlab returns [] 0x1 for out-of-range diagonal + + octave_idx_type nr = 0; + octave_idx_type nc = 1; + octave_idx_type nz = 0; + + d = Sparse (nr, nc, nz); + } } else if (nnr != 0 && nnc != 0) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/dDiagMatrix.cc --- a/liboctave/array/dDiagMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/dDiagMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -292,7 +292,7 @@ } DiagMatrix -DiagMatrix::pseudo_inverse (void) const +DiagMatrix::pseudo_inverse (double tol) const { octave_idx_type r = rows (); octave_idx_type c = cols (); @@ -302,10 +302,11 @@ for (octave_idx_type i = 0; i < len; i++) { - if (elem (i, i) != 0.0) + double val = std::abs (elem (i, i)); + if (val < tol || val == 0.0) + retval.elem (i, i) = 0.0; + else retval.elem (i, i) = 1.0 / elem (i, i); - else - retval.elem (i, i) = 0.0; } return retval; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/dDiagMatrix.h --- a/liboctave/array/dDiagMatrix.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/dDiagMatrix.h Sun May 25 10:29:05 2014 -0700 @@ -98,7 +98,7 @@ DiagMatrix inverse (void) const; DiagMatrix inverse (octave_idx_type& info) const; - DiagMatrix pseudo_inverse (void) const; + DiagMatrix pseudo_inverse (double tol = 0.0) const; // other operations diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/dMatrix.cc --- a/liboctave/array/dMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/dMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -1382,7 +1382,7 @@ double Matrix::rcond (MatrixType &mattype) const { - double rcon; + double rcon = octave_NaN; octave_idx_type nr = rows (); octave_idx_type nc = cols (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/dSparse.cc --- a/liboctave/array/dSparse.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/dSparse.cc Sun May 25 10:29:05 2014 -0700 @@ -777,7 +777,7 @@ octave_idx_type jb_max = y.cidx (i+1); bool jb_lt_max = jb < jb_max; - while (ja_lt_max || jb_lt_max ) + while (ja_lt_max || jb_lt_max) { octave_quit (); if ((! jb_lt_max) || @@ -789,8 +789,8 @@ ja++; ja_lt_max= ja < ja_max; } - else if (( !ja_lt_max ) || - (jb_lt_max && (y.ridx (jb) < x.ridx (ja)) ) ) + else if ((! ja_lt_max) || + (jb_lt_max && (y.ridx (jb) < x.ridx (ja)))) { jb++; jb_lt_max= jb < jb_max; @@ -1216,7 +1216,6 @@ { // Matrix is either singular or not positive definite mattype.mark_as_unsymmetric (); - typ = MatrixType::Full; } } @@ -4646,7 +4645,7 @@ m_band(ridx (i) - j + n_lower + n_upper, j) = data (i); // Calculate the norm of the matrix, for later use. - double anorm; + double anorm = 0.0; if (calc_cond) { for (octave_idx_type j = 0; j < nr; j++) @@ -7801,84 +7800,85 @@ { SparseMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + double tmp = xmin (a.data (ja), 0.); + if (tmp != 0.) { - double tmp = xmin (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) + { + double tmp = xmin (0., b.data (jb)); + if (tmp != 0.) { - double tmp = xmin (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + double tmp = xmin (a.data (ja), b.data (jb)); + if (tmp != 0.) { - double tmp = xmin (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); + } return r; } @@ -7951,84 +7951,85 @@ { SparseMatrix r; - if ((a.rows () == b.rows ()) && (a.cols () == b.cols ())) + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + if (a_nr == b_nr && a_nc == b_nc) { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - if (a_nr != b_nr || a_nc != b_nc) - gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc); - else + r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); + + octave_idx_type jx = 0; + r.cidx (0) = 0; + for (octave_idx_type i = 0 ; i < a_nc ; i++) { - r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ())); - - octave_idx_type jx = 0; - r.cidx (0) = 0; - for (octave_idx_type i = 0 ; i < a_nc ; i++) - { - octave_idx_type ja = a.cidx (i); - octave_idx_type ja_max = a.cidx (i+1); - bool ja_lt_max= ja < ja_max; - - octave_idx_type jb = b.cidx (i); - octave_idx_type jb_max = b.cidx (i+1); - bool jb_lt_max = jb < jb_max; - - while (ja_lt_max || jb_lt_max ) - { - octave_quit (); - if ((! jb_lt_max) || - (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + octave_idx_type ja = a.cidx (i); + octave_idx_type ja_max = a.cidx (i+1); + bool ja_lt_max= ja < ja_max; + + octave_idx_type jb = b.cidx (i); + octave_idx_type jb_max = b.cidx (i+1); + bool jb_lt_max = jb < jb_max; + + while (ja_lt_max || jb_lt_max) + { + octave_quit (); + if ((! jb_lt_max) || + (ja_lt_max && (a.ridx (ja) < b.ridx (jb)))) + { + double tmp = xmax (a.data (ja), 0.); + if (tmp != 0.) { - double tmp = xmax (a.data (ja), 0.); - if (tmp != 0.) - { - r.ridx (jx) = a.ridx (ja); - r.data (jx) = tmp; - jx++; - } - ja++; - ja_lt_max= ja < ja_max; + r.ridx (jx) = a.ridx (ja); + r.data (jx) = tmp; + jx++; } - else if (( !ja_lt_max ) || - (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) ) + ja++; + ja_lt_max= ja < ja_max; + } + else if ((! ja_lt_max) || + (jb_lt_max && (b.ridx (jb) < a.ridx (ja)))) + { + double tmp = xmax (0., b.data (jb)); + if (tmp != 0.) { - double tmp = xmax (0., b.data (jb)); - if (tmp != 0.) - { - r.ridx (jx) = b.ridx (jb); - r.data (jx) = tmp; - jx++; - } - jb++; - jb_lt_max= jb < jb_max; + r.ridx (jx) = b.ridx (jb); + r.data (jx) = tmp; + jx++; } - else + jb++; + jb_lt_max= jb < jb_max; + } + else + { + double tmp = xmax (a.data (ja), b.data (jb)); + if (tmp != 0.) { - double tmp = xmax (a.data (ja), b.data (jb)); - if (tmp != 0.) - { - r.data (jx) = tmp; - r.ridx (jx) = a.ridx (ja); - jx++; - } - ja++; - ja_lt_max= ja < ja_max; - jb++; - jb_lt_max= jb < jb_max; + r.data (jx) = tmp; + r.ridx (jx) = a.ridx (ja); + jx++; } - } - r.cidx (i+1) = jx; - } - - r.maybe_compress (); + ja++; + ja_lt_max= ja < ja_max; + jb++; + jb_lt_max= jb < jb_max; + } + } + r.cidx (i+1) = jx; } + + r.maybe_compress (); } else - (*current_liboctave_error_handler) ("matrix size mismatch"); + { + if (a_nr == 0 || a_nc == 0) + r.resize (a_nr, a_nc); + else if (b_nr == 0 || b_nc == 0) + r.resize (b_nr, b_nc); + else + gripe_nonconformant ("max", a_nr, a_nc, b_nr, b_nc); + } return r; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fCDiagMatrix.cc --- a/liboctave/array/fCDiagMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fCDiagMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -387,7 +387,7 @@ } FloatComplexDiagMatrix -FloatComplexDiagMatrix::pseudo_inverse (void) const +FloatComplexDiagMatrix::pseudo_inverse (float tol) const { octave_idx_type r = rows (); octave_idx_type c = cols (); @@ -397,10 +397,11 @@ for (octave_idx_type i = 0; i < len; i++) { - if (elem (i, i) != 0.0f) + float val = std::abs (elem (i, i)); + if (val < tol || val == 0.0f) + retval.elem (i, i) = 0.0f; + else retval.elem (i, i) = 1.0f / elem (i, i); - else - retval.elem (i, i) = 0.0f; } return retval; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fCDiagMatrix.h --- a/liboctave/array/fCDiagMatrix.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fCDiagMatrix.h Sun May 25 10:29:05 2014 -0700 @@ -122,7 +122,7 @@ FloatComplexDiagMatrix inverse (octave_idx_type& info) const; FloatComplexDiagMatrix inverse (void) const; - FloatComplexDiagMatrix pseudo_inverse (void) const; + FloatComplexDiagMatrix pseudo_inverse (float tol = 0.0f) const; bool all_elements_are_real (void) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fCMatrix.cc --- a/liboctave/array/fCMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fCMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -1727,7 +1727,7 @@ float FloatComplexMatrix::rcond (MatrixType &mattype) const { - float rcon; + float rcon = octave_NaN; octave_idx_type nr = rows (); octave_idx_type nc = cols (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fCNDArray.cc --- a/liboctave/array/fCNDArray.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fCNDArray.cc Sun May 25 10:29:05 2014 -0700 @@ -616,6 +616,12 @@ return do_mx_red_op (*this, dim, mx_inline_prod); } +ComplexNDArray +FloatComplexNDArray::dprod (int dim) const +{ + return do_mx_red_op (*this, dim, mx_inline_dprod); +} + FloatComplexNDArray FloatComplexNDArray::sum (int dim) const { diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fCNDArray.h --- a/liboctave/array/fCNDArray.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fCNDArray.h Sun May 25 10:29:05 2014 -0700 @@ -83,6 +83,7 @@ FloatComplexNDArray cumprod (int dim = -1) const; FloatComplexNDArray cumsum (int dim = -1) const; FloatComplexNDArray prod (int dim = -1) const; + ComplexNDArray dprod (int dim = -1) const; FloatComplexNDArray sum (int dim = -1) const; ComplexNDArray dsum (int dim = -1) const; FloatComplexNDArray sumsq (int dim = -1) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fDiagMatrix.cc --- a/liboctave/array/fDiagMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fDiagMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -292,7 +292,7 @@ } FloatDiagMatrix -FloatDiagMatrix::pseudo_inverse (void) const +FloatDiagMatrix::pseudo_inverse (float tol) const { octave_idx_type r = rows (); octave_idx_type c = cols (); @@ -302,10 +302,11 @@ for (octave_idx_type i = 0; i < len; i++) { - if (elem (i, i) != 0.0f) + float val = std::abs (elem (i, i)); + if (val < tol || val == 0.0f) + retval.elem (i, i) = 0.0f; + else retval.elem (i, i) = 1.0f / elem (i, i); - else - retval.elem (i, i) = 0.0f; } return retval; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fDiagMatrix.h --- a/liboctave/array/fDiagMatrix.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fDiagMatrix.h Sun May 25 10:29:05 2014 -0700 @@ -99,7 +99,7 @@ FloatDiagMatrix inverse (void) const; FloatDiagMatrix inverse (octave_idx_type& info) const; - FloatDiagMatrix pseudo_inverse (void) const; + FloatDiagMatrix pseudo_inverse (float tol = 0.0f) const; // other operations diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fMatrix.cc --- a/liboctave/array/fMatrix.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fMatrix.cc Sun May 25 10:29:05 2014 -0700 @@ -1390,7 +1390,7 @@ float FloatMatrix::rcond (MatrixType &mattype) const { - float rcon; + float rcon = octave_NaN; octave_idx_type nr = rows (); octave_idx_type nc = cols (); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fNDArray.cc --- a/liboctave/array/fNDArray.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fNDArray.cc Sun May 25 10:29:05 2014 -0700 @@ -627,6 +627,12 @@ return do_mx_red_op (*this, dim, mx_inline_prod); } +NDArray +FloatNDArray::dprod (int dim) const +{ + return do_mx_red_op (*this, dim, mx_inline_dprod); +} + FloatNDArray FloatNDArray::sum (int dim) const { diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/fNDArray.h --- a/liboctave/array/fNDArray.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/fNDArray.h Sun May 25 10:29:05 2014 -0700 @@ -90,6 +90,7 @@ FloatNDArray cumprod (int dim = -1) const; FloatNDArray cumsum (int dim = -1) const; FloatNDArray prod (int dim = -1) const; + NDArray dprod (int dim = -1) const; FloatNDArray sum (int dim = -1) const; NDArray dsum (int dim = -1) const; FloatNDArray sumsq (int dim = -1) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/intNDArray.cc --- a/liboctave/array/intNDArray.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/intNDArray.cc Sun May 25 10:29:05 2014 -0700 @@ -213,6 +213,13 @@ template intNDArray +intNDArray::prod (int dim) const +{ + return do_mx_red_op (*this, dim, mx_inline_prod); +} + +template +intNDArray intNDArray::sum (int dim) const { return do_mx_red_op (*this, dim, mx_inline_sum); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/array/intNDArray.h --- a/liboctave/array/intNDArray.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/array/intNDArray.h Sun May 25 10:29:05 2014 -0700 @@ -89,6 +89,7 @@ intNDArray cummin (int dim = -1) const; intNDArray cummin (Array& index, int dim = -1) const; + intNDArray prod (int dim) const; intNDArray sum (int dim) const; NDArray dsum (int dim) const; intNDArray cumsum (int dim) const; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/numeric/DASPK-opts.in --- a/liboctave/numeric/DASPK-opts.in Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/numeric/DASPK-opts.in Sun May 25 10:29:05 2014 -0700 @@ -209,7 +209,7 @@ A vector of the same length as the state vector. A nonzero element indicates that the corresponding element of the state vector is an algebraic variable (i.e., its derivative does not appear explicitly -in the equation set. +in the equation set). This option is required by the @qcode{\"compute consistent initial condition\"} and diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/numeric/bsxfun.h --- a/liboctave/numeric/bsxfun.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/numeric/bsxfun.h Sun May 25 10:29:05 2014 -0700 @@ -41,7 +41,7 @@ octave_idx_type xk = dx(i); octave_idx_type yk = dy(i); // Check the three conditions for valid bsxfun dims - if (! ( (xk == yk) || (xk == 1 && yk > 1) || (xk > 1 && yk == 1))) + if (! ((xk == yk) || (xk == 1 && yk > 1) || (xk > 1 && yk == 1))) return false; } @@ -71,7 +71,7 @@ octave_idx_type xk = dx(i); // Only two valid canditions to check; can't stretch rk - if (! ( (rk == xk) || (rk > 1 && xk == 1))) + if (! ((rk == xk) || (rk > 1 && xk == 1))) return false; } diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/numeric/lo-specfun.cc --- a/liboctave/numeric/lo-specfun.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/numeric/lo-specfun.cc Sun May 25 10:29:05 2014 -0700 @@ -2578,12 +2578,8 @@ err = false; if (a < 0.0 || x < 0.0) - { - (*current_liboctave_error_handler) - ("gammainc: A and X must be non-negative"); - - err = true; - } + (*current_liboctave_error_handler) + ("gammainc: A and X must be non-negative"); else F77_XFCN (xgammainc, XGAMMAINC, (a, x, retval)); @@ -2783,12 +2779,8 @@ err = false; if (a < 0.0 || x < 0.0) - { - (*current_liboctave_error_handler) - ("gammainc: A and X must be non-negative"); - - err = true; - } + (*current_liboctave_error_handler) + ("gammainc: A and X must be non-negative"); else F77_XFCN (xsgammainc, XSGAMMAINC, (a, x, retval)); @@ -3641,7 +3633,7 @@ double sqrt_eps = sqrt (std::numeric_limits::epsilon ()); if (m < sqrt_eps) { - // For small m, ( Abramowitz and Stegun, Section 16.13 ) + // For small m, (Abramowitz and Stegun, Section 16.13) si_u = sin (u); co_u = cos (u); t = 0.25*m*(u - si_u*co_u); @@ -3651,7 +3643,7 @@ } else if ((1 - m) < sqrt_eps) { - // For m1 = (1-m) small ( Abramowitz and Stegun, Section 16.15 ) + // For m1 = (1-m) small (Abramowitz and Stegun, Section 16.15) m1 = 1 - m; si_u = sinh (u); co_u = cosh (u); @@ -3663,8 +3655,8 @@ } else { - // Arithmetic-Geometric Mean (AGM) algorithm - // ( Abramowitz and Stegun, Section 16.4 ) + // Arithmetic-Geometric Mean (AGM) algorithm + // (Abramowitz and Stegun, Section 16.4) a[0] = 1; b = sqrt (1 - m); c[0] = sqrt (m); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/operators/Sparse-op-defs.h --- a/liboctave/operators/Sparse-op-defs.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/operators/Sparse-op-defs.h Sun May 25 10:29:05 2014 -0700 @@ -456,7 +456,7 @@ octave_idx_type jb_max = m2.cidx (i+1); \ bool jb_lt_max = jb < jb_max; \ \ - while (ja_lt_max || jb_lt_max ) \ + while (ja_lt_max || jb_lt_max) \ { \ octave_quit (); \ if ((! jb_lt_max) || \ @@ -468,8 +468,8 @@ ja++; \ ja_lt_max= ja < ja_max; \ } \ - else if (( !ja_lt_max ) || \ - (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \ + else if ((! ja_lt_max) || \ + (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \ { \ r.ridx (jx) = m2.ridx (jb); \ r.data (jx) = 0. OP m2.data (jb); \ @@ -564,7 +564,7 @@ octave_idx_type jb_max = m2.cidx (i+1); \ bool jb_lt_max = jb < jb_max; \ \ - while (ja_lt_max || jb_lt_max ) \ + while (ja_lt_max || jb_lt_max) \ { \ octave_quit (); \ if ((! jb_lt_max) || \ @@ -572,8 +572,8 @@ { \ ja++; ja_lt_max= ja < ja_max; \ } \ - else if (( !ja_lt_max ) || \ - (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \ + else if ((! ja_lt_max) || \ + (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \ { \ jb++; jb_lt_max= jb < jb_max; \ } \ @@ -680,7 +680,7 @@ octave_idx_type jb_max = m2.cidx (i+1); \ bool jb_lt_max = jb < jb_max; \ \ - while (ja_lt_max || jb_lt_max ) \ + while (ja_lt_max || jb_lt_max) \ { \ octave_quit (); \ if ((! jb_lt_max) || \ @@ -691,8 +691,8 @@ ja++; \ ja_lt_max= ja < ja_max; \ } \ - else if (( !ja_lt_max ) || \ - (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \ + else if ((! ja_lt_max) || \ + (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \ { \ /* keep those kludges coming */ \ r.elem (m2.ridx (jb),i) = Complex () OP m2.data (jb); \ @@ -1836,7 +1836,7 @@ #define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, false, !=, true) -#define SPARSE_SPARSE_MUL( RET_TYPE, RET_EL_TYPE, EL_TYPE ) \ +#define SPARSE_SPARSE_MUL(RET_TYPE, RET_EL_TYPE, EL_TYPE) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ @@ -2005,7 +2005,7 @@ } \ } -#define SPARSE_FULL_MUL( RET_TYPE, EL_TYPE, ZERO ) \ +#define SPARSE_FULL_MUL(RET_TYPE, EL_TYPE, ZERO) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ @@ -2040,7 +2040,7 @@ return retval; \ } -#define SPARSE_FULL_TRANS_MUL( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \ +#define SPARSE_FULL_TRANS_MUL(RET_TYPE, EL_TYPE, ZERO, CONJ_OP) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ @@ -2076,7 +2076,7 @@ return retval; \ } -#define FULL_SPARSE_MUL( RET_TYPE, EL_TYPE, ZERO ) \ +#define FULL_SPARSE_MUL(RET_TYPE, EL_TYPE, ZERO) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ @@ -2112,7 +2112,7 @@ return retval; \ } -#define FULL_SPARSE_MUL_TRANS( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \ +#define FULL_SPARSE_MUL_TRANS(RET_TYPE, EL_TYPE, ZERO, CONJ_OP) \ octave_idx_type nr = m.rows (); \ octave_idx_type nc = m.cols (); \ \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/operators/mx-inlines.cc --- a/liboctave/operators/mx-inlines.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/operators/mx-inlines.cc Sun May 25 10:29:05 2014 -0700 @@ -485,6 +485,14 @@ #define OP_RED_SUMSQ(ac, el) ac += el*el #define OP_RED_SUMSQC(ac, el) ac += cabsq (el) +inline void op_dble_prod (double& ac, float el) +{ ac *= el; } +inline void op_dble_prod (Complex& ac, const FloatComplex& el) +{ ac *= el; } // FIXME: guaranteed? +template +inline void op_dble_prod (double& ac, const octave_int& el) +{ ac *= el.double_value (); } + inline void op_dble_sum (double& ac, float el) { ac += el; } inline void op_dble_sum (Complex& ac, const FloatComplex& el) @@ -514,6 +522,7 @@ OP_RED_FCN (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0) OP_RED_FCN (mx_inline_count, bool, T, OP_RED_SUM, 0) OP_RED_FCN (mx_inline_prod, T, T, OP_RED_PROD, 1) +OP_RED_FCN (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 1) OP_RED_FCN (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0) OP_RED_FCN (mx_inline_sumsq, std::complex, T, OP_RED_SUMSQC, 0) OP_RED_FCN (mx_inline_any, T, bool, OP_RED_ANYC, false) @@ -539,6 +548,7 @@ OP_RED_FCN2 (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0) OP_RED_FCN2 (mx_inline_count, bool, T, OP_RED_SUM, 0) OP_RED_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1) +OP_RED_FCN2 (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 0.0) OP_RED_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0) OP_RED_FCN2 (mx_inline_sumsq, std::complex, T, OP_RED_SUMSQC, 0) @@ -612,6 +622,7 @@ OP_RED_FCNN (mx_inline_dsum, T, PROMOTE_DOUBLE(T)) OP_RED_FCNN (mx_inline_count, bool, T) OP_RED_FCNN (mx_inline_prod, T, T) +OP_RED_FCNN (mx_inline_dprod, T, PROMOTE_DOUBLE(T)) OP_RED_FCNN (mx_inline_sumsq, T, T) OP_RED_FCNN (mx_inline_sumsq, std::complex, T) OP_RED_FCNN (mx_inline_any, T, bool) @@ -1345,8 +1356,8 @@ inline T mx_inline_xsum (const T *v, octave_idx_type n) { - T s = 0; - T e = 0; + T s, e; + s = e = 0; for (octave_idx_type i = 0; i < n; i++) twosum_accum (s, e, v[i]); diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/system/module.mk --- a/liboctave/system/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/system/module.mk Sun May 25 10:29:05 2014 -0700 @@ -18,10 +18,6 @@ system/sysdir.h \ system/syswait.h -SYSTEM_C_SRC = \ - system/tempnam.c \ - system/tempname.c - SYSTEM_SRC = \ system/dir-ops.cc \ system/file-ops.cc \ @@ -33,8 +29,7 @@ system/oct-passwd.cc \ system/oct-syscalls.cc \ system/oct-time.cc \ - system/oct-uname.cc \ - $(SYSTEM_C_SRC) + system/oct-uname.cc noinst_LTLIBRARIES += system/libsystem.la diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/system/tempnam.c --- a/liboctave/system/tempnam.c Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifndef HAVE_TEMPNAM - -#include -#include -#include -#include - -extern char *__stdio_gen_tempname (const char *dir, const char *pfx, - int dir_search, size_t *lenptr, - FILE **streamptr); - -/* Generate a unique temporary filename using up to five characters of PFX - if it is not NULL. The directory to put this file in is searched for - as follows: First the environment variable "TMPDIR" is checked. - If it contains the name of a writable directory, that directory is used. - If not and if DIR is not NULL, that value is checked. If that fails, - P_tmpdir is tried and finally "/tmp". The storage for the filename - is allocated by `malloc'. */ -char * -tempnam (const char *dir, const char *pfx) -{ - size_t len; - register char *s; - register char *t = __stdio_gen_tempname (dir, pfx, 1, &len, (FILE **) NULL); - - if (t == NULL) - return NULL; - - s = (char *) malloc (len); - if (s == NULL) - return NULL; - - (void) memcpy (s, t, len); - return s; -} - -#endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/system/tempname.c --- a/liboctave/system/tempname.c Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public -License along with the GNU C Library; see the file COPYING. If -not, write to the Free Software Foundation, Inc., 51 Franklin Street, -Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifndef HAVE_TEMPNAM - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "statdefs.h" - -#ifndef FILENAME_MAX -#ifdef MAXPATHLEN -#define FILENAME_MAX MAXPATHLEN -#else -#define FILENAME_MAX 1024 -#endif -#endif - -#ifndef P_tmpdir -#define P_tmpdir "/usr/tmp/" -#endif - -/* Return nonzero if DIR is an existent directory. */ -static int -diraccess (const char *dir) -{ - struct stat buf; - return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode); -} - -/* Return nonzero if FILE exists. */ -static int -exists (const char *file) -{ - /* We can stat the file even if we can't read its data. */ - struct stat st; - int save = errno; - if (stat (file, &st) == 0) - return 1; - else - { - /* We report that the file exists if stat failed for a reason other - than nonexistence. In this case, it may or may not exist, and we - don't know; but reporting that it does exist will never cause any - trouble, while reporting that it doesn't exist when it does would - violate the interface of __stdio_gen_tempname. */ - int exists = errno != ENOENT; - errno = save; - return exists; - } -} - - -/* These are the characters used in temporary filenames. */ -static const char letters[] = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -/* Generate a temporary filename and return it (in a static buffer). If - STREAMPTR is not NULL, open a stream "w+b" on the file and set - *STREAMPTR to it. If DIR_SEARCH is nonzero, DIR and PFX are used as - described for tempnam. If not, a temporary filename in P_tmpdir with no - special prefix is generated. If LENPTR is not NULL, *LENPTR is set the - to length (including the terminating '\0') of the resultant filename, - which is returned. This goes through a cyclic pattern of all possible - filenames consisting of five decimal digits of the current pid and three - of the characters in `letters'. Data for tempnam and tmpnam is kept - separate, but when tempnam is using P_tmpdir and no prefix (i.e, it is - identical to tmpnam), the same data is used. Each potential filename is - tested for an already-existing file of the same name, and no name of an - existing file will be returned. When the cycle reaches its end - (12345ZZZ), NULL is returned. */ -char * -__stdio_gen_tempname (const char *dir, const char *pfx, - int dir_search, size_t *lenptr, - FILE **streamptr) -{ - int saverrno = errno; - static const char tmpdir[] = P_tmpdir; - static size_t indices[2]; - size_t *idx; - static char buf[FILENAME_MAX]; - static pid_t oldpid = (pid_t) 0; - pid_t pid = getpid (); - register size_t len, plen, dlen; - - if (dir_search) - { - register const char *d = getenv ("TMPDIR"); - if (d != NULL && !diraccess (d)) - d = NULL; - if (d == NULL && dir != NULL && diraccess (dir)) - d = dir; - if (d == NULL && diraccess (tmpdir)) - d = tmpdir; - if (d == NULL && diraccess ("/tmp")) - d = "/tmp"; - if (d == NULL) - { - errno = ENOENT; - return NULL; - } - dir = d; - } - else - dir = tmpdir; - - dlen = strlen (dir); - - /* Remove trailing slashes from the directory name. */ - while (dlen > 1 && dir[dlen - 1] == '/') - --dlen; - - if (pfx != NULL && *pfx != '\0') - { - plen = strlen (pfx); - if (plen > 5) - plen = 5; - } - else - plen = 0; - - if (dir != tmpdir && !strcmp (dir, tmpdir)) - dir = tmpdir; - idx = &indices[(plen == 0 && dir == tmpdir) ? 1 : 0]; - - if (pid != oldpid) - { - oldpid = pid; - indices[0] = indices[1] = 0; - } - - len = dlen + 1 + plen + 5 + 3; - for (; *idx < ((sizeof (letters) - 1) * (sizeof (letters) - 1) * - (sizeof (letters) - 1)); - ++*idx) - { - /* Construct a file name and see if it already exists. - - We use a single counter in *IDX to cycle each of three - character positions through each of 62 possible letters. */ - - if (sizeof (buf) < len) - return NULL; - - sprintf (buf, "%.*s/%.*s%.5d%c%c%c", - (int) dlen, dir, (int) plen, - pfx, pid % 100000, - letters[*idx - % (sizeof (letters) - 1)], - letters[(*idx / (sizeof (letters) - 1)) - % (sizeof (letters) - 1)], - letters[(*idx / ((sizeof (letters) - 1) * - (sizeof (letters) - 1))) - % (sizeof (letters) - 1)] - ); - - if (! buf || strlen (buf) != (int) len) - return NULL; - - if (streamptr != NULL) - abort (); - else if (exists (buf)) - continue; - - /* If the file already existed we have continued the loop above, - so we only get here when we have a winning name to return. */ - - errno = saverrno; - - if (lenptr != NULL) - *lenptr = len + 1; - return buf; - } - - /* We got out of the loop because we ran out of combinations to try. */ - errno = EEXIST; /* ? */ - return NULL; -} - -#endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/util/base-list.h --- a/liboctave/util/base-list.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/util/base-list.h Sun May 25 10:29:05 2014 -0700 @@ -104,8 +104,6 @@ // For backward compatibility. void append (const elt_type& s) { lst.push_back (s); } -protected: - octave_base_list (void) : lst () { } octave_base_list (const std::list& l) : lst (l) { } diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/util/caseless-str.h --- a/liboctave/util/caseless-str.h Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/util/caseless-str.h Sun May 25 10:29:05 2014 -0700 @@ -57,16 +57,16 @@ char lp1 = std::tolower (*p1); char lp2 = std::tolower (*p2); - if ( lp1 > lp2 ) + if (lp1 > lp2) return false; - if ( lp1 < lp2) + if (lp1 < lp2) return true; p1++; p2++; } - if ( length () >= s.length ()) + if (length () >= s.length ()) return false; else return true; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/util/data-conv.cc --- a/liboctave/util/data-conv.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/util/data-conv.cc Sun May 25 10:29:05 2014 -0700 @@ -409,8 +409,6 @@ if (input_is_output) { - input_is_output = false; - s1 = s.substr (1, pos-1); (*current_liboctave_warning_handler) @@ -587,7 +585,7 @@ if (len > 0) \ { \ OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \ - std::streamsize n_bytes = size * len; \ + std::streamsize n_bytes = size * static_cast (len); \ stream.read (reinterpret_cast (ptr), n_bytes); \ if (swap) \ swap_bytes< size > (ptr, len); \ @@ -610,7 +608,7 @@ OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \ for (octave_idx_type i = 0; i < len; i++) \ ptr[i] = static_cast (data[i]); \ - std::streamsize n_bytes = size * len; \ + std::streamsize n_bytes = size * static_cast (len); \ stream.write (reinterpret_cast (ptr), n_bytes); \ } \ } \ @@ -809,7 +807,7 @@ case LS_FLOAT: { OCTAVE_LOCAL_BUFFER (float, ptr, len); - std::streamsize n_bytes = 4 * len; + std::streamsize n_bytes = 4 * static_cast (len); is.read (reinterpret_cast (ptr), n_bytes); do_float_format_conversion (ptr, len, fmt); for (octave_idx_type i = 0; i < len; i++) @@ -867,7 +865,7 @@ case LS_FLOAT: // No conversion necessary. { - std::streamsize n_bytes = 4 * len; + std::streamsize n_bytes = 4 * static_cast (len); is.read (reinterpret_cast (data), n_bytes); do_float_format_conversion (data, len, fmt); } @@ -876,7 +874,7 @@ case LS_DOUBLE: { OCTAVE_LOCAL_BUFFER (double, ptr, len); - std::streamsize n_bytes = 8 * len; + std::streamsize n_bytes = 8 * static_cast (len); is.read (reinterpret_cast (ptr), n_bytes); do_double_format_conversion (ptr, len, fmt); for (octave_idx_type i = 0; i < len; i++) @@ -974,7 +972,7 @@ { char tmp_type = static_cast (type); os.write (&tmp_type, 1); - std::streamsize n_bytes = 4 * len; + std::streamsize n_bytes = 4 * static_cast (len); os.write (reinterpret_cast (data), n_bytes); } break; diff -r bd1fd4ed3d67 -r 888f8ce79bbe liboctave/util/str-vec.cc --- a/liboctave/util/str-vec.cc Sun May 25 10:26:18 2014 -0700 +++ b/liboctave/util/str-vec.cc Sun May 25 10:29:05 2014 -0700 @@ -250,14 +250,10 @@ nc = 1; // Calculate the number of rows that will be in each column except - // possibly for a short column on the right. + // possibly for a short column on the right. octave_idx_type nr = total_names / nc + (total_names % nc != 0); - // Recalculate columns based on rows. - - nc = total_names / nr + (total_names % nr != 0); - octave_idx_type count; for (octave_idx_type row = 0; row < nr; row++) { diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/bicubic.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/deprecated/bicubic.m Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,260 @@ +## Copyright (C) 2005-2013 Hoxide Ma +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{zi} =} bicubic (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}, @var{extrapval}) +## +## @code{bicubic} is deprecated and will be removed in Octave version 4.6. +## Use @code{interp2 (@dots{}, "spline")} for the equivalent functionality. +## +## Return a matrix @var{zi} corresponding to the bicubic +## interpolations at @var{xi} and @var{yi} of the data supplied +## as @var{x}, @var{y} and @var{z}. Points outside the grid are set +## to @var{extrapval}. +## +## See @url{http://wiki.woodpecker.org.cn/moin/Octave/Bicubic} +## for further information. +## @seealso{interp2} +## @end deftypefn + +## Bicubic interpolation method. +## Author: Hoxide Ma + +## Deprecated in version 4.2 + +function zi = bicubic (x, y, z, xi, yi, extrapval, spline_alpha) + + persistent warned = false; + if (! warned) + warned = true; + warning ("Octave:deprecated-function", + "bicubic is obsolete and will be removed from a future version of Octave, please use interp2 instead"); + endif + + if (nargin < 1 || nargin > 7) + print_usage (); + endif + + if (nargin == 7 && isscalar (spline_alpha)) + a = spline_alpha; + else + a = 0.5; + endif + + if (nargin < 6) + extrapval = NaN; + endif + + if (isa (x, "single") || isa (y, "single") || isa (z, "single") + || isa (xi, "single") || isa (yi, "single")) + myeps = eps ("single"); + else + myeps = eps (); + endif + + if (nargin <= 2) + ## bicubic (z) or bicubic (z, 2) + if (nargin == 1) + n = 1; + else + n = y; + endif + z = x; + x = []; + [rz, cz] = size (z); + s = linspace (1, cz, (cz-1) * pow2 (n) + 1); + t = linspace (1, rz, (rz-1) * pow2 (n) + 1); + elseif (nargin == 3) + if (! isvector (x) || ! isvector (y)) + error ("bicubic: XI and YI must be vector"); + endif + s = y; + t = z; + z = x; + [rz, cz] = size (z); + elseif (nargin == 5 || nargin == 6) + [rz, cz] = size (z) ; + if (isvector (x) && isvector (y)) + if (rz != length (y) || cz != length (x)) + error ("bicubic: length of X and Y must match the size of Z"); + endif + elseif (size_equal (x, y) && size_equal (x, z)) + x = x(1,:); + y = y(:,1); + else + error ("bicubic: X, Y and Z must be equal size matrices of same size"); + endif + + if (all (diff (x) < 0)) + flipx = true; + x = fliplr (x); + elseif (all (diff (x) > 0)) + flipx = false; + else + error ("bicubic:nonmonotonic", "bicubic: X values must be monotonic"); + endif + if (all (diff (y) < 0)) + flipy = true; + y = flipud (y); + elseif (all (diff (y) > 0)) + flipy = false; + else + error ("bicubic:nonmonotonic", "bicubic: Y values must be monotonic"); + endif + + ## Mark values outside the lookup table. + xfirst_ind = find (xi < x(1)); + xlast_ind = find (xi > x(cz)); + yfirst_ind = find (yi < y(1)); + ylast_ind = find (yi > y(rz)); + ## Set value outside the table preliminary to min max index. + xi(xfirst_ind) = x(1); + xi(xlast_ind) = x(cz); + yi(yfirst_ind) = y(1); + yi(ylast_ind) = y(rz); + + x = reshape (x, 1, cz); + x(cz) *= 1 + sign (x(cz)) * myeps; + if (x(cz) == 0) + x(cz) = myeps; + endif; + xi = reshape (xi, 1, length (xi)); + [m, i] = sort ([x, xi]); + o = cumsum (i <= cz); + xidx = o(find (i > cz)); + + y = reshape (y, rz, 1); + y(rz) *= 1 + sign (y(rz)) * myeps; + if (y(rz) == 0) + y(rz) = myeps; + endif; + yi = reshape (yi, length (yi), 1); + [m, i] = sort ([y; yi]); + o = cumsum (i <= rz); + yidx = o([find(i > rz)]); + + ## Set s and t used follow codes. + s = xidx + ((xi .- x(xidx)) ./ (x(xidx+1) .- x(xidx))); + t = yidx + ((yi - y(yidx)) ./ (y(yidx+1) - y(yidx))); + + if (flipx) + s = fliplr (s); + endif + if (flipy) + t = flipud (t); + endif + else + print_usage (); + endif + + if (rz < 3 || cz < 3) + error ("bicubic: Z at least a 3 by 3 matrices"); + endif + + inds = floor (s); + d = find (s == cz); + s = s - floor (s); + inds(d) = cz-1; + s(d) = 1.0; + + d = []; + indt = floor (t); + d = find (t == rz); + t = t - floor (t); + indt(d) = rz-1; + t(d) = 1.0; + d = []; + + p = zeros (size (z) + 2); + p(2:rz+1,2:cz+1) = z; + p(1,:) = (6*(1-a))*p(2,:) - 3*p(3,:) + (6*a-2)*p(4,:); + p(rz+2,:) = (6*(1-a))*p(rz+1,:) - 3*p(rz,:) + (6*a-2)*p(rz-1,:); + p(:,1) = (6*(1-a))*p(:,2) - 3*p(:,3) + (6*a-2)*p(:,4); + p(:,cz+2) = (6*(1-a))*p(:,cz+1) - 3*p(:,cz) + (6*a-2)*p(:,cz-1); + + ## Calculte the C1(t) C2(t) C3(t) C4(t) and C1(s) C2(s) C3(s) C4(s). + t2 = t.*t; + t3 = t2.*t; + + ct0 = -a .* t3 + (2 * a) .* t2 - a .* t ; # -a G0 + ct1 = (2-a) .* t3 + (-3+a) .* t2 + 1 ; # F0 - a G1 + ct2 = (a-2) .* t3 + (-2 *a + 3) .* t2 + a .* t ; # F1 + a G0 + ct3 = a .* t3 - a .* t2; # a G1 + t = []; t2 = []; t3 = []; + + s2 = s.*s; + s3 = s2.*s; + + cs0 = -a .* s3 + (2 * a) .* s2 - a .*s ; # -a G0 + cs1 = (2-a) .* s3 + (-3 + a) .* s2 + 1 ; # F0 - a G1 + cs2 = (a-2) .* s3 + (-2 *a + 3) .* s2 + a .*s ; # F1 + a G0 + cs3 = a .* s3 - a .* s2; # a G1 + s = []; s2 = []; s3 = []; + + cs0 = cs0([1,1,1,1],:); + cs1 = cs1([1,1,1,1],:); + cs2 = cs2([1,1,1,1],:); + cs3 = cs3([1,1,1,1],:); + + lent = length (ct0); + lens = columns (cs0); + zi = zeros (lent, lens); + + for i = 1:lent + it = indt(i); + int = [it, it+1, it+2, it+3]; + zi(i,:) = ([ct0(i),ct1(i),ct2(i),ct3(i)] + * (p(int,inds) .* cs0 + p(int,inds+1) .* cs1 + + p(int,inds+2) .* cs2 + p(int,inds+3) .* cs3)); + endfor + + ## Set points outside the table to extrapval. + if (! (isempty (xfirst_ind) && isempty (xlast_ind))) + zi(:, [xfirst_ind, xlast_ind]) = extrapval; + endif + if (! (isempty (yfirst_ind) && isempty (ylast_ind))) + zi([yfirst_ind; ylast_ind], :) = extrapval; + endif + +endfunction + + +%!demo +%! clf; +%! colormap ("default"); +%! A = [13,-1,12;5,4,3;1,6,2]; +%! x = [0,1,4]+10; +%! y = [-10,-9,-8]; +%! xi = linspace (min (x), max (x), 17); +%! yi = linspace (min (y), max (y), 26)'; +%! mesh (xi, yi, bicubic (x,y,A,xi,yi)); +%! [x,y] = meshgrid (x,y); +%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; + +%!test +%! x = linspace (1, -1, 10); +%! [xx, yy] = meshgrid (x); +%! z = cos (6 * xx) + sin (6 * yy); +%! x = linspace (1, -1, 30); +%! [xx2, yy2] = meshgrid (x); +%! z1 = interp2 (xx, yy, z, xx2, yy2, "spline"); +%! z2 = interp2 (fliplr (xx), flipud (yy), fliplr (flipud(z)), +%! fliplr (xx2), flipud (yy2), "spline"); +%! z2 = fliplr (flipud (z2)); +%! assert (z1, z2, 100 * eps ()) + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/default_save_options.m --- a/scripts/deprecated/default_save_options.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} default_save_options () -## @deftypefnx {Built-in Function} {@var{old_val} =} default_save_options (@var{new_val}) -## @deftypefnx {Built-in Function} {} default_save_options (@var{new_val}, "local") -## This function has been deprecated. Use @code{@file{save_default_options}} -## instead. -## @seealso{save_default_options} -## @end deftypefn - -## Deprecated in 3.8 - -function retval = default_save_options (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "default_save_options is obsolete and will be removed from a future version of Octave, please use save_default_options instead"); - endif - - retval = save_default_options (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/find_dir_in_path.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/deprecated/find_dir_in_path.m Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,40 @@ +## Copyright (C) 2013 John W. Eaton +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Built-in Function} {} find_dir_in_path (@var{dir}) +## @deftypefnx {Built-in Function} {} find_dir_in_path (@var{dir}, "all") +## This function has been deprecated. Use @code{dir_in_loadpath} instead. +## @seealso{dir_in_loadpath} +## @end deftypefn + +## Deprecated in version 4.2 + +function retval = find_dir_in_path (varargin) + + persistent warned = false; + if (! warned) + warned = true; + warning ("Octave:deprecated-function", + "find_dir_in_path is obsolete and will be removed from a future version of Octave, please use dir_in_loadpath instead"); + endif + + retval = dir_in_loadpath (varargin{:}); + +endfunction + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/gen_doc_cache.m --- a/scripts/deprecated/gen_doc_cache.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} gen_doc_cache (@var{out_file}, @var{directory}) -## This function has been deprecated. Use @code{doc_cache_create} instead. -## @seealso{doc_cache_create} -## @end deftypefn - -## Deprecated in 3.8 - -function gen_doc_cache (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "gen_doc_cache is obsolete and will be removed from a future version of Octave, please use doc_cache_create instead"); - endif - - doc_cache_create (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/interp1q.m --- a/scripts/deprecated/interp1q.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -## Copyright (C) 2008-2013 David Bateman -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{yi} =} interp1q (@var{x}, @var{y}, @var{xi}) -## One-dimensional linear interpolation without error checking. -## Interpolates @var{y}, defined at the points @var{x}, at the points -## @var{xi}. The sample points @var{x} must be a strictly monotonically -## increasing column vector. If @var{y} is a matrix or an N-dimensional -## array, the interpolation is performed on each column of @var{y}. If -## @var{y} is a vector, it must be a column vector of the same length as -## @var{x}. -## -## Values of @var{xi} beyond the endpoints of the interpolation result -## in NA being returned. -## -## Note that the error checking is only a significant portion of the -## execution time of this @code{interp1} if the size of the input arguments -## is relatively small. Therefore, the benefit of using @code{interp1q} -## is relatively small. -## @seealso{interp1} -## @end deftypefn - -function yi = interp1q (x, y, xi) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "interp1q is obsolete and will be removed from a future version of Octave; use interp1 instead"); - endif - - x = x(:); - nx = rows (x); - szy = size (y); - y = y(:,:); - [ny, nc] = size (y); - szx = size (xi); - xi = xi (:); - dy = diff (y); - dx = diff (x); - idx = lookup (x, xi, "lr"); - s = (xi - x (idx)) ./ dx (idx); - yi = bsxfun (@times, s, dy(idx,:)) + y(idx,:); - range = xi < x(1) | !(xi <= x(nx)); - yi(range,:) = NA; - if (length (szx) == 2 && any (szx == 1)) - yi = reshape (yi, [max(szx), szy(2:end)]); - else - yi = reshape (yi, [szx, szy(2:end)]); - endif -endfunction - - -%!shared xp, yp, xi, yi -%! xp = [0:2:10].'; yp = sin (2*pi*xp/5); -%! xi = [-1; 0; 2.2; 4; 6.6; 10; 11]; -%! yi = interp1 (xp,yp,xi); -%!assert (interp1q (xp,yp, [min(xp)-1; max(xp)+1]), [NA; NA]); -%!assert (interp1q (xp,yp,xp), yp, 100*eps); -%!assert (isempty (interp1q (xp,yp,[]))); -%!assert (interp1q (xp,yp,xi), yi); -%!assert (interp1q (xp,[yp,yp],xi), [yi, yi]); -%!assert (interp1q (xp,yp,[xi,xi]), [yi, yi]); -%!assert (interp1q (xp,[yp,yp],[xi,xi]), cat (3, [yi, yi], [yi, yi])); - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/isequalwithequalnans.m --- a/scripts/deprecated/isequalwithequalnans.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -## Copyright (C) 2005-2013 William Poetra Yoga Hadisoeseno -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} isequalwithequalnans (@var{x1}, @var{x2}, @dots{}) -## This function has been deprecated. Use @code{@file{isequaln}} instead. -## @seealso{isequaln} -## @end deftypefn - -## Deprecated in 3.8 - -function retval = isequalwithequalnans (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "isequalwithequalnans is obsolete and will be removed from a future version of Octave, please use isequaln instead"); - endif - - retval = isequaln (varargin{:}); - -endfunction - - -## test for equality -%!assert (isequalwithequalnans ({1,2,NaN,4},{1,2,NaN,4}), true) -%!assert (isequalwithequalnans ([1,2,NaN,4],[1,2,NaN,4]), true) -## test for inequality -%!assert (isequalwithequalnans ([1,2,NaN,4],[1,NaN,3,4]), false) -%!assert (isequalwithequalnans ([1,2,NaN,4],[1,2,3,4]), false) -## test for equality (struct) -%!assert (isequalwithequalnans (struct ('a',NaN,'b',2),struct ('a',NaN,'b',2),struct ('a',NaN,'b',2)), true) -%!assert (isequalwithequalnans (1,2,1), false) - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/java_convert_matrix.m --- a/scripts/deprecated/java_convert_matrix.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} java_convert_matrix () -## @deftypefnx {Built-in Function} {@var{old_val} =} java_convert_matrix (@var{new_val}) -## @deftypefnx {Built-in Function} {} java_convert_matrix (@var{new_val}, "local") -## Query or set the internal variable that controls whether Java arrays are -## automatically converted to Octave matrices. The default value is false. -## -## When called from inside a function with the @qcode{"local"} option, the -## variable is changed locally for the function and any subroutines it calls. -## The original variable value is restored when exiting the function. -## @seealso{java_matrix_autoconversion, java_unsigned_conversion, java_debug} -## @end deftypefn - -function old_val = java_convert_matrix (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_convert_matrix is obsolete and will be removed from a future version of Octave; use java_matrix_autoconversion instead"); - endif - - if (nargin > 2) - print_usage (); - endif - - old_val = java_matrix_autoconversion (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/java_debug.m --- a/scripts/deprecated/java_debug.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} java_debug () -## @deftypefnx {Built-in Function} {@var{old_val} =} java_debug (@var{new_val}) -## @deftypefnx {Built-in Function} {} java_debug (@var{new_val}, "local") -## Query or set the internal variable that determines whether extra debugging -## information regarding the initialization of the JVM and any Java exceptions -## is printed. -## -## When called from inside a function with the @qcode{"local"} option, the -## variable is changed locally for the function and any subroutines it calls. -## The original variable value is restored when exiting the function. -## @seealso{debug_java, java_convert_matrix, java_unsigned_conversion} -## @end deftypefn - -function old_val = java_debug (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_debug is obsolete and will be removed from a future version of Octave; use debug_java instead"); - endif - - if (nargin > 2) - print_usage (); - endif - - old_val = debug_java (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/java_get.m --- a/scripts/deprecated/java_get.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Loadable Function} {@var{val} =} java_get (@var{obj}, @var{name}) -## Get the value of the field @var{name} of the Java object @var{obj}. For -## static fields, @var{obj} can be a string representing the fully qualified -## name of the corresponding class. -## -## When @var{obj} is a regular Java object, structure-like indexing can be -## used as a shortcut syntax. For instance, the two following statements are -## equivalent -## -## @example -## @group -## java_get (x, "field1") -## x.field1 -## @end group -## @end example -## -## @seealso{java_set, javaMethod, javaObject} -## @end deftypefn - -function retval = java_get (obj, name) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_get is obsolete and will be removed from a future version of Octave; use structure-like indexing instead"); - endif - - if (nargin != 2) - print_usage (); - endif - - if (isjava (obj)) - retval = obj.(name); - elseif (ischar (obj)) - ## FIXME: Need a solution for getting static fields of class - ## which does not depend on __java_get__ which will be removed. - retval = __java_get__ (obj, name); - else - error ("java_get: OBJ must be a Java object"); - endif - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/java_invoke.m --- a/scripts/deprecated/java_invoke.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -## Copyright (C) 2007, 2013 Michael Goffioul -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{ret} =} java_invoke (@var{obj}, @var{methodname}) -## @deftypefnx {Built-in Function} {@var{ret} =} java_invoke (@var{obj}, @var{methodname}, @var{arg1}, @dots{}) -## Invoke the method @var{methodname} on the Java object @var{obj} with the -## arguments @var{arg1}, @dots{} For static methods, @var{obj} can be a -## string representing the fully qualified name of the corresponding class. -## The function returns the result of the method invocation. -## -## When @var{obj} is a regular Java object, structure-like indexing can be -## used as a shortcut syntax. For instance, the two following statements are -## equivalent -## -## @example -## @group -## ret = java_invoke (x, "method1", 1.0, "a string") -## ret = x.method1 (1.0, "a string") -## @end group -## @end example -## -## @seealso{javaMethod, javaObject} -## @end deftypefn - -function retval = java_invoke (obj, methodname, varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_invoke is obsolete and will be removed from a future version of Octave, please use javaMethod instead"); - endif - - if (nargin < 2) - print_usage (); - endif - - retval = javaMethod (methodname, obj, varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/java_set.m --- a/scripts/deprecated/java_set.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Loadable Function} {@var{obj} =} java_set (@var{obj}, @var{name}, @var{val}) -## Set the value of the field @var{name} of the Java object @var{obj} to -## @var{val}. For static fields, @var{obj} can be a string representing the -## fully qualified named of the corresponding Java class. -## -## When @var{obj} is a regular Java object, structure-like indexing can be -## used as a shortcut syntax. For instance, the two following statements are -## equivalent -## -## @example -## @group -## java_set (x, "field1", val) -## x.field1 = val -## @end group -## @end example -## -## @seealso{java_get, javaMethod, javaObject} -## @end deftypefn - -function retval = java_set (obj, name, val) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_set is obsolete and will be removed from a future version of Octave; use structure-like indexing instead"); - endif - - if (nargin != 3) - print_usage (); - endif - - if (isjava (obj)) - obj.(name) = val; - elseif (ischar (obj)) - ## FIXME: Need a solution for getting static fields of class - ## which does not depend on __java_set__ which will be removed. - retval = __java_set__ (obj, name, val); - else - error ("java_set: OBJ must be a Java object"); - endif - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/java_unsigned_conversion.m --- a/scripts/deprecated/java_unsigned_conversion.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -## Copyright (C) 2012-2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} java_unsigned_conversion () -## @deftypefnx {Built-in Function} {@var{old_val} =} java_unsigned_conversion (@var{new_val}) -## @deftypefnx {Built-in Function} {} java_unsigned_conversion (@var{new_val}, "local") -## Query or set the internal variable that controls how integer classes are -## converted when Java matrix autoconversion is enabled. When enabled, Java -## arrays of class Byte or Integer are converted to matrices of class uint8 or -## uint32 respectively. -## -## When called from inside a function with the @qcode{"local"} option, the -## variable is changed locally for the function and any subroutines it calls. -## The original variable value is restored when exiting the function. -## @seealso{java_unsigned_autoconversion, java_convert_matrix, debug_java} -## @end deftypefn - -function old_val = java_unsigned_conversion (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_unsigned_conversion is obsolete and will be removed from a future version of Octave; use java_unsigned_autoconversion instead"); - endif - - if (nargin > 2) - print_usage (); - endif - - old_val = java_unsigned_autoconversion (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/javafields.m --- a/scripts/deprecated/javafields.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -## Copyright (C) 2007, 2013 Michael Goffioul -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} javafields (@var{javaobj}) -## @deftypefnx {Function File} {} javafields ("@var{classname}") -## @deftypefnx {Function File} {@var{fld_names} =} javafields (@dots{}) -## Return the fields of a Java object or Java class in the form of a cell -## array of strings. If no output is requested, print the result -## to the standard output. -## @seealso{fieldnames, methods, javaObject} -## @end deftypefn - -function fld_names = javafields (javaobj) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "javafields is obsolete and will be removed from a future version of Octave, please use fieldnames instead"); - endif - - if (nargin != 1) - print_usage (); - endif - - c_methods = javaMethod ("getFields", "org.octave.ClassHelper", javaobj); - method_list = ostrsplit (c_methods, ';'); - - if (nargout == 0) - if (! isempty (method_list)) - disp (method_list); - endif - else - fld_names = cellstr (method_list); - endif - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/javamethods.m --- a/scripts/deprecated/javamethods.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -## Copyright (C) 2007, 2013 Michael Goffioul -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} javamethods (@var{javaobj}) -## @deftypefnx {Function File} {} javamethods ("@var{classname}") -## @deftypefnx {Function File} {@var{mtd_names} =} javamethods (@dots{}) -## Return the methods of a Java object or Java class in the form of a cell -## array of strings. If no output is requested, print the result to the -## standard output. -## @seealso{methods, fieldnames, javaMethod, javaObject} -## @end deftypefn - -function mtd_names = javamethods (classname) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "javamethods is obsolete and will be removed from a future version of Octave, please use methods instead"); - endif - - if (nargin != 1) - print_usage (); - endif - - cls_methods = javaMethod ("getMethods", "org.octave.ClassHelper", classname); - method_list = ostrsplit (cls_methods, ';'); - - if (nargout == 0) - if (! isempty (method_list)) - disp (method_list); - endif - else - mtd_names = cellstr (method_list); - endif - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/module.mk --- a/scripts/deprecated/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/scripts/deprecated/module.mk Sun May 25 10:29:05 2014 -0700 @@ -1,23 +1,10 @@ FCN_FILE_DIRS += deprecated deprecated_FCN_FILES = \ - deprecated/default_save_options.m \ - deprecated/gen_doc_cache.m \ - deprecated/interp1q.m \ - deprecated/isequalwithequalnans.m \ + deprecated/bicubic.m \ + deprecated/find_dir_in_path.m \ deprecated/isstr.m \ - deprecated/java_convert_matrix.m \ - deprecated/java_debug.m \ - deprecated/java_get.m \ - deprecated/java_invoke.m \ - deprecated/java_new.m \ - deprecated/java_unsigned_conversion.m \ - deprecated/java_set.m \ - deprecated/javafields.m \ - deprecated/javamethods.m \ - deprecated/re_read_readline_init_file.m \ - deprecated/read_readline_init_file.m \ - deprecated/saving_history.m + deprecated/nfields.m FCN_FILES += $(deprecated_FCN_FILES) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/nfields.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/deprecated/nfields.m Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,44 @@ +## Copyright (C) 2014 Rik Wehbring +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} nfields (@var{s}) +## Return the number of fields of the structure @var{s}. +## +## @strong{Warning:} @code{nfields} is scheduled for removal in version 4.6. +## Use @code{numfields} instead. +## @seealso{numfields, fieldnames} +## @end deftypefn + +function retval = nfields (varargin) + + persistent warned = false; + if (! warned) + warned = true; + warning ("Octave:deprecated-function", + "nfields is obsolete and will be removed from a future version of Octave; please use numfields instead"); + endif + + if (nargin < 1) + print_usage (); + endif + + retval = numfields (varargin{:}); + +endfunction + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/re_read_readline_init_file.m --- a/scripts/deprecated/re_read_readline_init_file.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {} re_read_readline_init_file (@var{file}) -## This function has been deprecated. Use -## @code{@file{readline_re_read_init_file}} instead. -## @seealso{readline_read_init_file} -## @end deftypefn - -## Deprecated in 3.8 - -function re_read_readline_init_file (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "re_read_readline_init_file is obsolete and will be removed from a future version of Octave, please use readline_re_read_init_file instead"); - endif - - readline_re_read_init_file (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/read_readline_init_file.m --- a/scripts/deprecated/read_readline_init_file.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {} read_readline_init_file (@var{file}) -## This function has been deprecated. Use -## @code{@file{readline_read_init_file}} instead. -## @seealso{readline_read_init_file} -## @end deftypefn - -## Deprecated in 3.8 - -function read_readline_init_file (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "read_readline_init_file is obsolete and will be removed from a future version of Octave, please use readline_read_init_file instead"); - endif - - readline_read_init_file (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/deprecated/saving_history.m --- a/scripts/deprecated/saving_history.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -## Copyright (C) 2013 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Built-in Function} {@var{val} =} saving_history () -## @deftypefnx {Built-in Function} {@var{old_val} =} saving_history (@var{new_val}) -## @deftypefnx {Built-in Function} {} saving_history (@var{new_val}, "local") -## This function has been deprecated. Use @code{@file{history_save}} instead. -## @seealso{history_save} -## @end deftypefn - -## Deprecated in 3.8 - -function retval = saving_history (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "saving_history is obsolete and will be removed from a future version of Octave, please use history_save instead"); - endif - - retval = save_default_options (varargin{:}); - -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/bicubic.m --- a/scripts/general/bicubic.m Sun May 25 10:26:18 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,248 +0,0 @@ -## Copyright (C) 2005-2013 Hoxide Ma -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{zi} =} bicubic (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}, @var{extrapval}) -## -## Return a matrix @var{zi} corresponding to the bicubic -## interpolations at @var{xi} and @var{yi} of the data supplied -## as @var{x}, @var{y} and @var{z}. Points outside the grid are set -## to @var{extrapval}. -## -## See @url{http://wiki.woodpecker.org.cn/moin/Octave/Bicubic} -## for further information. -## @seealso{interp2} -## @end deftypefn - -## Bicubic interpolation method. -## Author: Hoxide Ma - -function zi = bicubic (x, y, z, xi, yi, extrapval, spline_alpha) - - if (nargin < 1 || nargin > 7) - print_usage (); - endif - - if (nargin == 7 && isscalar (spline_alpha)) - a = spline_alpha; - else - a = 0.5; - endif - - if (nargin < 6) - extrapval = NaN; - endif - - if (isa (x, "single") || isa (y, "single") || isa (z, "single") - || isa (xi, "single") || isa (yi, "single")) - myeps = eps ("single"); - else - myeps = eps (); - endif - - if (nargin <= 2) - ## bicubic (z) or bicubic (z, 2) - if (nargin == 1) - n = 1; - else - n = y; - endif - z = x; - x = []; - [rz, cz] = size (z); - s = linspace (1, cz, (cz-1) * pow2 (n) + 1); - t = linspace (1, rz, (rz-1) * pow2 (n) + 1); - elseif (nargin == 3) - if (! isvector (x) || ! isvector (y)) - error ("bicubic: XI and YI must be vector"); - endif - s = y; - t = z; - z = x; - [rz, cz] = size (z); - elseif (nargin == 5 || nargin == 6) - [rz, cz] = size (z) ; - if (isvector (x) && isvector (y)) - if (rz != length (y) || cz != length (x)) - error ("bicubic: length of X and Y must match the size of Z"); - endif - elseif (size_equal (x, y) && size_equal (x, z)) - x = x(1,:); - y = y(:,1); - else - error ("bicubic: X, Y and Z must be equal size matrices of same size"); - endif - - if (all (diff (x) < 0)) - flipx = true; - x = fliplr (x); - elseif (all (diff (x) > 0)) - flipx = false; - else - error ("bicubic:nonmonotonic", "bicubic: X values must be monotonic"); - endif - if (all (diff (y) < 0)) - flipy = true; - y = flipud (y); - elseif (all (diff (y) > 0)) - flipy = false; - else - error ("bicubic:nonmonotonic", "bicubic: Y values must be monotonic"); - endif - - ## Mark values outside the lookup table. - xfirst_ind = find (xi < x(1)); - xlast_ind = find (xi > x(cz)); - yfirst_ind = find (yi < y(1)); - ylast_ind = find (yi > y(rz)); - ## Set value outside the table preliminary to min max index. - xi(xfirst_ind) = x(1); - xi(xlast_ind) = x(cz); - yi(yfirst_ind) = y(1); - yi(ylast_ind) = y(rz); - - x = reshape (x, 1, cz); - x(cz) *= 1 + sign (x(cz)) * myeps; - if (x(cz) == 0) - x(cz) = myeps; - endif; - xi = reshape (xi, 1, length (xi)); - [m, i] = sort ([x, xi]); - o = cumsum (i <= cz); - xidx = o(find (i > cz)); - - y = reshape (y, rz, 1); - y(rz) *= 1 + sign (y(rz)) * myeps; - if (y(rz) == 0) - y(rz) = myeps; - endif; - yi = reshape (yi, length (yi), 1); - [m, i] = sort ([y; yi]); - o = cumsum (i <= rz); - yidx = o([find(i > rz)]); - - ## Set s and t used follow codes. - s = xidx + ((xi .- x(xidx)) ./ (x(xidx+1) .- x(xidx))); - t = yidx + ((yi - y(yidx)) ./ (y(yidx+1) - y(yidx))); - - if (flipx) - s = fliplr (s); - endif - if (flipy) - t = flipud (t); - endif - else - print_usage (); - endif - - if (rz < 3 || cz < 3) - error ("bicubic: Z at least a 3 by 3 matrices"); - endif - - inds = floor (s); - d = find (s == cz); - s = s - floor (s); - inds(d) = cz-1; - s(d) = 1.0; - - d = []; - indt = floor (t); - d = find (t == rz); - t = t - floor (t); - indt(d) = rz-1; - t(d) = 1.0; - d = []; - - p = zeros (size (z) + 2); - p(2:rz+1,2:cz+1) = z; - p(1,:) = (6*(1-a))*p(2,:) - 3*p(3,:) + (6*a-2)*p(4,:); - p(rz+2,:) = (6*(1-a))*p(rz+1,:) - 3*p(rz,:) + (6*a-2)*p(rz-1,:); - p(:,1) = (6*(1-a))*p(:,2) - 3*p(:,3) + (6*a-2)*p(:,4); - p(:,cz+2) = (6*(1-a))*p(:,cz+1) - 3*p(:,cz) + (6*a-2)*p(:,cz-1); - - ## Calculte the C1(t) C2(t) C3(t) C4(t) and C1(s) C2(s) C3(s) C4(s). - t2 = t.*t; - t3 = t2.*t; - - ct0 = -a .* t3 + (2 * a) .* t2 - a .* t ; # -a G0 - ct1 = (2-a) .* t3 + (-3+a) .* t2 + 1 ; # F0 - a G1 - ct2 = (a-2) .* t3 + (-2 *a + 3) .* t2 + a .* t ; # F1 + a G0 - ct3 = a .* t3 - a .* t2; # a G1 - t = []; t2 = []; t3 = []; - - s2 = s.*s; - s3 = s2.*s; - - cs0 = -a .* s3 + (2 * a) .* s2 - a .*s ; # -a G0 - cs1 = (2-a) .* s3 + (-3 + a) .* s2 + 1 ; # F0 - a G1 - cs2 = (a-2) .* s3 + (-2 *a + 3) .* s2 + a .*s ; # F1 + a G0 - cs3 = a .* s3 - a .* s2; # a G1 - s = []; s2 = []; s3 = []; - - cs0 = cs0([1,1,1,1],:); - cs1 = cs1([1,1,1,1],:); - cs2 = cs2([1,1,1,1],:); - cs3 = cs3([1,1,1,1],:); - - lent = length (ct0); - lens = columns (cs0); - zi = zeros (lent, lens); - - for i = 1:lent - it = indt(i); - int = [it, it+1, it+2, it+3]; - zi(i,:) = ([ct0(i),ct1(i),ct2(i),ct3(i)] - * (p(int,inds) .* cs0 + p(int,inds+1) .* cs1 - + p(int,inds+2) .* cs2 + p(int,inds+3) .* cs3)); - endfor - - ## Set points outside the table to extrapval. - if (! (isempty (xfirst_ind) && isempty (xlast_ind))) - zi(:, [xfirst_ind, xlast_ind]) = extrapval; - endif - if (! (isempty (yfirst_ind) && isempty (ylast_ind))) - zi([yfirst_ind; ylast_ind], :) = extrapval; - endif - -endfunction - - -%!demo -%! clf; -%! colormap ("default"); -%! A = [13,-1,12;5,4,3;1,6,2]; -%! x = [0,1,4]+10; -%! y = [-10,-9,-8]; -%! xi = linspace (min (x), max (x), 17); -%! yi = linspace (min (y), max (y), 26)'; -%! mesh (xi, yi, bicubic (x,y,A,xi,yi)); -%! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; - -%!test -%! x = linspace (1, -1, 10); -%! [xx, yy] = meshgrid (x); -%! z = cos (6 * xx) + sin (6 * yy); -%! x = linspace (1, -1, 30); -%! [xx2, yy2] = meshgrid (x); -%! z1 = interp2 (xx, yy, z, xx2, yy2, "cubic"); -%! z2 = interp2 (fliplr (xx), flipud (yy), fliplr (flipud(z)), -%! fliplr (xx2), flipud (yy2), "cubic"); -%! z2 = fliplr (flipud (z2)); -%! assert (z1, z2, 100 * eps ()) - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/bincoeff.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/cell2mat.m --- a/scripts/general/cell2mat.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/cell2mat.m Sun May 25 10:29:05 2014 -0700 @@ -32,15 +32,14 @@ print_usage (); endif - if (! iscell (c)) - error ("cell2mat: C is not a cell array"); - endif - nb = numel (c); if (nb == 0) m = []; else + if (! iscell (c)) + error ("cell2mat: C must be a cell array"); + endif ## Check first for valid matrix types valid = cellfun ("isnumeric", c); @@ -94,6 +93,7 @@ %! cell2mat (C) %!assert (cell2mat ({}), []); +%!assert (cell2mat ([]), []); %!test %! C = {[1], [2 3 4]; [5; 9], [6 7 8; 10 11 12]}; %! D = C; D(:,:,2) = C; @@ -115,7 +115,7 @@ %!error cell2mat () %!error cell2mat (1,2) -%!error cell2mat ([1,2]) +%!error cell2mat ([1,2]) %!error cell2mat ({[1], struct()}) %!error cell2mat ({[1], {1}}) %!error cell2mat ({struct(), {1}}) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/cplxpair.m --- a/scripts/general/cplxpair.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/cplxpair.m Sun May 25 10:29:05 2014 -0700 @@ -23,7 +23,7 @@ ## Sort the numbers @var{z} into complex conjugate pairs ordered by ## increasing real part. Place the negative imaginary complex number ## first within each pair. Place all the real numbers (those with -## @code{abs (imag (@var{z}) / @var{z}) < @var{tol})}) after the +## @code{abs (imag (@var{z}) / @var{z}) < @var{tol}}) after the ## complex pairs. ## ## If @var{tol} is unspecified the default value is 100*@code{eps}. diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/del2.m --- a/scripts/general/del2.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/del2.m Sun May 25 10:29:05 2014 -0700 @@ -158,3 +158,164 @@ D = D ./ nd; endfunction + +## 3x3 constant test +%!test +%! a = ones (3,3); +%! b = del2 (a); +%! assert (b(:,1), [0.00;0.00;0.00]); +%! assert (b(:,2), [0.00;0.00;0.00]); +%! assert (b(:,3), [0.00;0.00;0.00]); + +## 3x3 planar test +%!test +%! a = [1,2,3;2,3,4;3,4,5]; +%! b = del2 (a); +%! assert (b(:,1), [0.00;0.00;0.00]); +%! assert (b(:,2), [0.00;0.00;0.00]); +%! assert (b(:,3), [0.00;0.00;0.00]); + +## 3x3 corner test +%!test +%! a = zeros (3,3); +%! a(1,1) = 1.0; +%! b = 2*del2 (a); +%! assert (b(:,1), [1.00;0.50;0.50]); +%! assert (b(:,2), [0.50;0.00;0.00]); +%! assert (b(:,3), [0.50;0.00;0.00]); +%! assert (b, flipud (2*del2 (flipud (a)))); +%! assert (b, fliplr (2*del2 (fliplr (a)))); +%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a)))))); + +## 3x3 boundary test +%!test +%! a = zeros (3,3); +%! a(2,1)=1.0; +%! b = 2*del2 (a); +%! assert (b(:,1), [-1.00;-0.50;-1.00]); +%! assert (b(:,2), [0.00;0.50;0.00]); +%! assert (b(:,3), [0.00;0.50;0.00]); +%! assert (b, flipud (2*del2 (flipud (a)))); +%! assert (b, fliplr (2*del2 (fliplr (a)))); +%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a)))))); + +## 3x3 center test +%!test +%! a = zeros (3,3); +%! a(2,2) = 1.0; +%! b = del2 (a); +%! assert (b(:,1), [0.00;-0.50;0.00]); +%! assert (b(:,2), [-0.50;-1.00;-0.50]); +%! assert (b(:,3), [0.00;-0.50;0.00]); + +## 4x4 constant test +%!test +%! a = ones (4,4); +%! b = del2 (a); +%! assert (b(:,1), [0.00;0.00;0.00;0.00]); +%! assert (b(:,2), [0.00;0.00;0.00;0.00]); +%! assert (b(:,3), [0.00;0.00;0.00;0.00]); +%! assert (b(:,4), [0.00;0.00;0.00;0.00]); + +## 4x4 planar test +%!test +%! a = [1,2,3,4;2,3,4,5;3,4,5,6;4,5,6,7]; +%! b = del2 (a); +%! assert (b(:,1), [0.00;0.00;0.00;0.00]); +%! assert (b(:,2), [0.00;0.00;0.00;0.00]); +%! assert (b(:,3), [0.00;0.00;0.00;0.00]); +%! assert (b(:,4), [0.00;0.00;0.00;0.00]); + +## 4x4 corner test +%!test +%! a = zeros (4,4); +%! a(1,1) = 1.0; +%! b = 2*del2 (a); +%! assert (b(:,1), [2.00;0.50;0.00;-0.50]); +%! assert (b(:,2), [0.50;0.00;0.00;0.00]); +%! assert (b(:,3), [0.00;0.00;0.00;0.00]); +%! assert (b(:,4), [-0.50;0.00;0.00;0.00]); +%! assert (b, flipud (2*del2 (flipud (a)))); +%! assert (b, fliplr (2*del2 (fliplr (a)))); +%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a)))))); + +## 9x9 center test +%!test +%! a = zeros (9,9); +%! a(5,5) = 1.0; +%! b = 2*del2 (a); +%! assert (b(:,1), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]); +%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]); +%! assert (b(:,3), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]); +%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]); +%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]); +%! assert (b(:,6), b(:,4)); +%! assert (b(:,7), b(:,3)); +%! assert (b(:,8), b(:,2)); +%! assert (b(:,9), b(:,1)); + +## 9x9 boundary test +%!test +%! a = zeros (9,9); +%! a(1,5) = 1.0; +%! b = 2*del2 (a); +%! assert (b(1,:), [0.00,0.00,0.00,0.50,0.00,0.50,0.00,0.00,0.00]); +%! assert (b(2,:), [0.00,0.00,0.00,0.00,0.50,0.00,0.00,0.00,0.00]); +%! assert (b(3:9,:), zeros (7,9)); +%! a(1,5) = 0.0; +%! a(5,1) = 1.0; +%! b = 2*del2 (a); +%! assert (b(:,1), [0.00;0.00;0.00;0.50;0.00;0.50;0.00;0.00;0.00]); +%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]); +%! assert (b(:,3:9), zeros (9,7)); + +## 9x9 dh center test +%!test +%! a = zeros (9,9); +%! a(5,5) = 1.0; +%! b = 8*del2 (a,2); +%! assert (b(:,1:3), zeros (9,3)); +%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]); +%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]); +%! assert (b(:,6), b(:,4)); +%! assert (b(:,7:9), zeros (9,3)); + +## 9x9 dx test +%!test +%! a = zeros (9,9); +%! a(5,5) = 1.0; +%! b = 4*del2 (a,2,1); +%! assert (b(1:3,:), zeros (3,9)); +%! assert (b(4,:), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]'); +%! assert (b(5,:), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]'); +%! assert (b(6,:), b(4,:)); +%! assert (b(7:9,:), zeros (3,9)); + +## 9x9 dy test +%!test +%! a = zeros (9,9); +%! a(5,5) = 1.0; +%! b = 4*del2 (a,1,2); +%! assert (b(:,1:3), zeros (9,3)); +%! assert (b(:,4), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]); +%! assert (b(:,5), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]); +%! assert (b(:,6), b(:,4)); +%! assert (b(:,7:9), zeros (9,3)); + +## 3D test +%!test +%! a = zeros (9,9,9); +%! a(5,5,5) = 1.0; +%! b = 8*3*del2 (a,2); +%! assert (b(:,:,1:3), zeros (9,9,3)); +%! assert (b(:,1:3,:), zeros (9,3,9)); +%! assert (b(1:3,:,:), zeros (3,9,9)); +%! assert (b(4:5,4,4), [0.0,0.0]'); +%! assert (b(5,5,4), 1.00); +%! assert (b(4,4,5), 0.00); +%! assert (b(5,4,5), 1.00); +%! assert (b(5,5,5),-6.00); +%! assert (b, flipdim (b,1)); +%! assert (b, flipdim (b,2)); +%! assert (b, flipdim (b,3)); + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/fieldnames.m --- a/scripts/general/fieldnames.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/fieldnames.m Sun May 25 10:29:05 2014 -0700 @@ -33,7 +33,7 @@ ## When the input is a Java object @var{javaobj} or Java classname ## @var{jclassname} the name are the public data elements of the object or ## class. -## @seealso{nfields, isfield, orderfields, struct, methods} +## @seealso{numfields, isfield, orderfields, struct, methods} ## @end deftypefn function names = fieldnames (obj) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/interp1.m --- a/scripts/general/interp1.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/interp1.m Sun May 25 10:29:05 2014 -0700 @@ -29,28 +29,29 @@ ## One-dimensional interpolation. ## ## Interpolate input data to determine the value of @var{yi} at the points -## @var{xi}. If not specified, @var{x} is taken to be the indices of @var{y}. -## If @var{y} is a matrix or an N-dimensional array, the interpolation is -## performed on each column of @var{y}. +## @var{xi}. If not specified, @var{x} is taken to be the indices of @var{y} +## (@code{1:length (@var{y})}). If @var{y} is a matrix or an N-dimensional +## array, the interpolation is performed on each column of @var{y}. ## -## Method is one of: +## The interpolation @var{method} is one of: ## ## @table @asis ## @item @qcode{"nearest"} -## Return the nearest neighbor +## Return the nearest neighbor. ## -## @item @qcode{"linear"} -## Linear interpolation from nearest neighbors +## @item @qcode{"linear"} (default) +## Linear interpolation from nearest neighbors. ## ## @item @qcode{"pchip"} -## Piecewise cubic Hermite interpolating polynomial +## Piecewise cubic Hermite interpolating polynomial---shape-preserving +## interpolation with smooth first derivative. ## ## @item @qcode{"cubic"} -## Cubic interpolation (same as @code{pchip}) +## Cubic interpolation (same as @qcode{"pchip"}). ## ## @item @qcode{"spline"} ## Cubic spline interpolation---smooth first and second derivatives -## throughout the curve +## throughout the curve. ## @end table ## ## Adding '*' to the start of any method above forces @code{interp1} @@ -61,7 +62,7 @@ ## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values ## beyond the endpoints using the current @var{method}. If @var{extrap} is a ## number, then replace values beyond the endpoints with that number. When -## unspecified, @var{extrap} defaults to NA. +## unspecified, @var{extrap} defaults to @code{NA}. ## ## If the string argument @qcode{"pp"} is specified, then @var{xi} should not ## be supplied and @code{interp1} returns a piecewise polynomial object. This @@ -91,16 +92,16 @@ ## xp = [0:10]; ## yp = sin (2*pi*xp/5); ## lin = interp1 (xp, yp, xf); +## near = interp1 (xp, yp, xf, "nearest"); +## pch = interp1 (xp, yp, xf, "pchip"); ## spl = interp1 (xp, yp, xf, "spline"); -## cub = interp1 (xp, yp, xf, "cubic"); -## near = interp1 (xp, yp, xf, "nearest"); -## plot (xf, yf, "r", xf, lin, "g", xf, spl, "b", -## xf, cub, "c", xf, near, "m", xp, yp, "r*"); -## legend ("original", "linear", "spline", "cubic", "nearest"); +## plot (xf,yf,"r", xf,near,"g", xf,lin,"b", xf,pch,"c", xf,spl,"m", +## xp,yp,"r*"); +## legend ("original", "nearest", "linear", "pchip", "spline"); ## @end group ## @end example ## -## @seealso{interpft, interp2, interp3, interpn} +## @seealso{pchip, spline, interpft, interp2, interp3, interpn} ## @end deftypefn ## Author: Paul Kienzle @@ -130,17 +131,18 @@ arg = varargin{i}; if (ischar (arg)) arg = tolower (arg); - if (strcmp ("extrap", arg)) - extrap = "extrap"; - elseif (strcmp ("pp", arg)) - ispp = true; - elseif (strcmp (arg, "right") || strcmp (arg, "-right")) - rightcontinuous = true; - elseif (strcmp (arg, "left") || strcmp (arg, "-left")) - rightcontinuous = false; - else - method = arg; - endif + switch (arg) + case "extrap" + extrap = "extrap"; + case "pp" + ispp = true; + case {"right", "-right"} + rightcontinuous = true; + case {"left", "-left"} + rightcontinuous = false; + otherwise + method = arg; + endswitch else if (firstnumeric) xi = arg; @@ -177,7 +179,7 @@ ## determine sizes if (nx < 2 || ny < 2) - error ("interp1: table too short"); + error ("interp1: minimum of 2 points required in each dimension"); endif ## check whether x is sorted; sort if not. @@ -193,10 +195,8 @@ else rightcontinuous = true; endif - endif - - if ((rightcontinuous && (x(end) < x(1))) - || (! rightcontinuous && (x(end) > x(1)))) + elseif ((rightcontinuous && (x(end) < x(1))) + || (! rightcontinuous && (x(end) > x(1)))) ## Switch between left-continuous and right-continuous x = flipud (x); y = flipud (y); @@ -215,7 +215,8 @@ warning ("interp1: multiple discontinuities at the same X value"); endif else - error ("interp1: discontinuities not supported for method '%s'", method); + error ("interp1: discontinuities not supported for method '%s'", + method); endif endif endif @@ -238,6 +239,7 @@ pp = mkpp ([x(1), x(1)+[0.5:(nx-1)]*dx, x(nx)], shiftdim (y, 1), szy(2:end)); pp.orient = "first"; + if (ispp) yi = pp; else @@ -245,7 +247,6 @@ endif case "linear" - xx = x; nxx = nx; yy = y; @@ -323,13 +324,13 @@ endswitch - if (! ispp && ! ischar (extrap)) + if (! ispp && isnumeric (extrap)) ## determine which values are out of range and set them to extrap, ## unless extrap == "extrap". minx = min (x(1), x(nx)); maxx = max (x(1), x(nx)); - outliers = xi < minx | ! (xi <= maxx); # this even catches NaNs + outliers = xi < minx | ! (xi <= maxx); # this even catches NaNs if (size_equal (outliers, yi)) yi(outliers) = extrap; yi = reshape (yi, szx); @@ -347,12 +348,13 @@ %! clf; %! xf = 0:0.05:10; yf = sin (2*pi*xf/5); %! xp = 0:10; yp = sin (2*pi*xp/5); -%! lin = interp1 (xp,yp,xf, "linear"); -%! spl = interp1 (xp,yp,xf, "spline"); -%! cub = interp1 (xp,yp,xf, "pchip"); -%! near= interp1 (xp,yp,xf, "nearest"); -%! plot (xf,yf,"r",xf,near,"g",xf,lin,"b",xf,cub,"c",xf,spl,"m",xp,yp,"r*"); -%! legend ("original", "nearest", "linear", "pchip", "spline"); +%! lin = interp1 (xp,yp,xf, 'linear'); +%! spl = interp1 (xp,yp,xf, 'spline'); +%! pch = interp1 (xp,yp,xf, 'pchip'); +%! near= interp1 (xp,yp,xf, 'nearest'); +%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*'); +%! legend ('original', 'nearest', 'linear', 'pchip', 'spline'); +%! title ('Interpolation of continuous function sin (x) w/various methods'); %! %-------------------------------------------------------- %! % confirm that interpolated function matches the original @@ -360,36 +362,50 @@ %! clf; %! xf = 0:0.05:10; yf = sin (2*pi*xf/5); %! xp = 0:10; yp = sin (2*pi*xp/5); -%! lin = interp1 (xp,yp,xf, "*linear"); -%! spl = interp1 (xp,yp,xf, "*spline"); -%! cub = interp1 (xp,yp,xf, "*cubic"); -%! near= interp1 (xp,yp,xf, "*nearest"); -%! plot (xf,yf,"r",xf,near,"g",xf,lin,"b",xf,cub,"c",xf,spl,"m",xp,yp,"r*"); -%! legend ("*original", "*nearest", "*linear", "*cubic", "*spline"); +%! lin = interp1 (xp,yp,xf, '*linear'); +%! spl = interp1 (xp,yp,xf, '*spline'); +%! pch = interp1 (xp,yp,xf, '*pchip'); +%! near= interp1 (xp,yp,xf, '*nearest'); +%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*'); +%! legend ('*original', '*nearest', '*linear', '*pchip', '*spline'); +%! title ('Interpolation of continuous function sin (x) w/various *methods'); %! %-------------------------------------------------------- %! % confirm that interpolated function matches the original %!demo %! clf; +%! fstep = @(x) x > 1; +%! xf = 0:0.05:2; yf = fstep (xf); +%! xp = linspace (0,2,10); yp = fstep (xp); +%! pch = interp1 (xp,yp,xf, 'pchip'); +%! spl = interp1 (xp,yp,xf, 'spline'); +%! plot (xf,yf,'r',xf,pch,'b',xf,spl,'m',xp,yp,'r*'); +%! title ({'Interpolation of step function with discontinuity at x==1', ... +%! 'Note: "pchip" is shape-preserving, "spline" (continuous 1st, 2nd derivatives) is not'}); +%! legend ('original', 'pchip', 'spline'); + +%!demo +%! clf; %! t = 0 : 0.3 : pi; dt = t(2)-t(1); %! n = length (t); k = 100; dti = dt*n/k; %! ti = t(1) + [0 : k-1]*dti; %! y = sin (4*t + 0.3) .* cos (3*t - 0.1); -%! ddyc = diff (diff (interp1 (t,y,ti, "cubic")) ./dti)./dti; -%! ddys = diff (diff (interp1 (t,y,ti, "spline"))./dti)./dti; -%! ddyp = diff (diff (interp1 (t,y,ti, "pchip")) ./dti)./dti; -%! plot (ti(2:end-1),ddyc,'g+', ti(2:end-1),ddys,'b*', ti(2:end-1),ddyp,'c^'); -%! legend ("cubic", "spline", "pchip"); -%! title ("Second derivative of interpolated 'sin (4*t + 0.3) .* cos (3*t - 0.1)'"); +%! ddys = diff (diff (interp1 (t,y,ti, 'spline'))./dti)./dti; +%! ddyp = diff (diff (interp1 (t,y,ti, 'pchip')) ./dti)./dti; +%! ddyc = diff (diff (interp1 (t,y,ti, 'cubic')) ./dti)./dti; +%! plot (ti(2:end-1),ddys,'b*', ti(2:end-1),ddyp,'c^', ti(2:end-1),ddyc,'g+'); +%! title ({'Second derivative of interpolated "sin (4*t + 0.3) .* cos (3*t - 0.1)"', ... +%! 'Note: "spline" has continous 2nd derivative, others do not'}); +%! legend ('spline', 'pchip', 'cubic'); %!demo %! clf; %! xf = 0:0.05:10; yf = sin (2*pi*xf/5) - (xf >= 5); %! xp = [0:.5:4.5,4.99,5:.5:10]; yp = sin (2*pi*xp/5) - (xp >= 5); -%! lin = interp1 (xp,yp,xf, "linear"); -%! near= interp1 (xp,yp,xf, "nearest"); -%! plot (xf,yf,"r", xf,near,"g", xf,lin,"b", xp,yp,"r*"); -%! legend ("original", "nearest", "linear"); +%! lin = interp1 (xp,yp,xf, 'linear'); +%! near= interp1 (xp,yp,xf, 'nearest'); +%! plot (xf,yf,'r', xf,near,'g', xf,lin,'b', xp,yp,'r*'); +%! legend ('original', 'nearest', 'linear'); %! %-------------------------------------------------------- %! % confirm that interpolated function matches the original @@ -410,7 +426,7 @@ %! %-------------------------------------------------------- %! % red curve is left-continuous and blue is right-continuous at x = 2 -##FIXME: add test for n-d arguments here +##FIXME: add test for N-d arguments here ## For each type of interpolated test, confirm that the interpolated ## value at the knots match the values at the knots. Points away @@ -638,12 +654,12 @@ %% Test input validation %!error interp1 () %!error interp1 (1,2,3,4,5,6,7) -%!error interp1 (1,1,1, "linear") -%!error
interp1 (1,1,1, "*nearest") -%!error
interp1 (1,1,1, "*linear") +%!error interp1 (1,1,1, "linear") +%!error interp1 (1,1,1, "*nearest") +%!error interp1 (1,1,1, "*linear") %!warning interp1 ([1 1 1 2], [1 2 3 4], 1); %!error interp1 ([1 1],[1 2],1, "pchip") %!error interp1 ([1 1],[1 2],1, "cubic") %!error interp1 ([1 1],[1 2],1, "spline") -%!error interp1 (1:2,1:2,1, "bogus") +%!error interp1 (1:2,1:2,1, "bogus") diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/interp2.m --- a/scripts/general/interp2.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/interp2.m Sun May 25 10:29:05 2014 -0700 @@ -19,63 +19,63 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {@var{zi} =} interp2 (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}) -## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{Z}, @var{xi}, @var{yi}) -## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{Z}, @var{n}) +## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z}, @var{xi}, @var{yi}) +## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z}, @var{n}) +## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z}) ## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}) -## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrapval}) +## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrap}) +## +## Two-dimensional interpolation. ## -## Two-dimensional interpolation. @var{x}, @var{y} and @var{z} describe a -## surface function. If @var{x} and @var{y} are vectors their length -## must correspondent to the size of @var{z}. @var{x} and @var{y} must be -## monotonic. If they are matrices they must have the @code{meshgrid} -## format. -## -## @table @code -## @item interp2 (@var{x}, @var{y}, @var{Z}, @var{xi}, @var{yi}, @dots{}) -## Returns a matrix corresponding to the points described by the -## matrices @var{xi}, @var{yi}. +## Interpolate reference data @var{x}, @var{y}, @var{z} to determine @var{zi} +## at the coordinates @var{xi}, @var{yi}. The reference data @var{x}, @var{y} +## can be matrices, as returned by @code{meshgrid}, in which case the sizes of +## @var{x}, @var{y}, and @var{z} must be equal. If @var{x}, @var{y} are +## vectors describing a grid then @code{length (@var{x}) == columns (@var{z})} +## and @code{length (@var{y}) == rows (@var{z})}. In either case the input +## data must be strictly monotonic. ## -## If the last argument is a string, the interpolation method can -## be specified. The method can be @qcode{"linear"}, @qcode{"nearest"} or -## @qcode{"cubic"}. If it is omitted @qcode{"linear"} interpolation is -## assumed. +## If called without @var{x}, @var{y}, and just a single reference data matrix +## @var{z}, the 2-D region +## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})} is assumed. +## This saves memory if the grid is regular and the distance between points is +## not important. ## -## @item interp2 (@var{z}, @var{xi}, @var{yi}) -## Assumes @code{@var{x} = 1:rows (@var{z})} and @code{@var{y} = -## 1:columns (@var{z})} +## If called with a single reference data matrix @var{z} and a refinement +## value @var{n}, then perform interpolation over a grid where each original +## interval has been recursively subdivided @var{n} times. This results in +## @code{2^@var{n}-1} additional points for every interval in the original +## grid. If @var{n} is omitted a value of 1 is used. As an example, the +## interval [0,1] with @code{@var{n}==2} results in a refined interval with +## points at [0, 1/4, 1/2, 3/4, 1]. ## -## @item interp2 (@var{z}, @var{n}) -## Interleaves the matrix @var{z} n-times. If @var{n} is omitted a value -## of @code{@var{n} = 1} is assumed. -## @end table -## -## The variable @var{method} defines the method to use for the -## interpolation. It can take one of the following values +## The interpolation @var{method} is one of: ## ## @table @asis ## @item @qcode{"nearest"} ## Return the nearest neighbor. ## -## @item @qcode{"linear"} +## @item @qcode{"linear"} (default) ## Linear interpolation from nearest neighbors. ## ## @item @qcode{"pchip"} -## Piecewise cubic Hermite interpolating polynomial. +## Piecewise cubic Hermite interpolating polynomial---shape-preserving +## interpolation with smooth first derivative. ## ## @item @qcode{"cubic"} -## Cubic interpolation from four nearest neighbors. +## Cubic interpolation (same as @qcode{"pchip"}). ## ## @item @qcode{"spline"} ## Cubic spline interpolation---smooth first and second derivatives ## throughout the curve. ## @end table ## -## If a scalar value @var{extrapval} is defined as the final value, then -## values outside the mesh as set to this value. Note that in this case -## @var{method} must be defined as well. If @var{extrapval} is not -## defined then NA is assumed. -## -## @seealso{interp1} +## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values +## beyond the endpoints using the current @var{method}. If @var{extrap} is a +## number, then replace values beyond the endpoints with that number. When +## unspecified, @var{extrap} defaults to @code{NA}. Note that if @var{extrap} +## is used, @var{method} must be specified as well. +## @seealso{interp1, interp3, interpn, meshgrid} ## @end deftypefn ## Author: Kai Habel @@ -94,10 +94,14 @@ ## "meshgridded") to be consistent with the help message ## above and for compatibility. +## FIXME: Need better input validation. +## E.g, interp2 (1,1,1) => A(I): index out of bounds + function ZI = interp2 (varargin) + Z = X = Y = XI = YI = n = []; method = "linear"; - extrapval = NA; + extrap = NA; switch (nargin) case 1 @@ -120,36 +124,41 @@ if (ischar (varargin{4})) [Z, XI, YI, method] = deal (varargin{:}); else - [Z, n, method, extrapval] = deal (varargin{:}); + [Z, n, method, extrap] = deal (varargin{:}); endif case 5 if (ischar (varargin{4})) - [Z, XI, YI, method, extrapval] = deal (varargin{:}); + [Z, XI, YI, method, extrap] = deal (varargin{:}); else [X, Y, Z, XI, YI] = deal (varargin{:}); endif case 6 [X, Y, Z, XI, YI, method] = deal (varargin{:}); case 7 - [X, Y, Z, XI, YI, method, extrapval] = deal (varargin{:}); + [X, Y, Z, XI, YI, method, extrap] = deal (varargin{:}); otherwise print_usage (); endswitch - ## Type checking. - if (!ismatrix (Z)) - error ("interp2: Z must be a matrix"); + ## Type checking + if (! (ismatrix (Z) && ndims (Z) == 2)) + error ("interp2: Z must be a 2-D matrix"); endif - if (!isempty (n) && !isscalar (n)) - error ("interp2: N must be a scalar"); + if (! isempty (n) && ! (isscalar (n) && n >= 0 && n == fix (n))) + error ("interp2: N must be an integer >= 0"); endif - if (!ischar (method)) + if (! ischar (method)) error ("interp2: METHOD must be a string"); + elseif (method(1) == "*") + warning ("interp2: ignoring unsupported '*' flag to METHOD"); + method(1) = []; endif - if (ischar (extrapval) || strcmp (extrapval, "extrap")) - extrapval = []; - elseif (!isscalar (extrapval)) - error ("interp2: EXTRAPVAL must be a scalar"); + if (isnumeric (extrap) && isscalar (extrap)) + ## Typical case + elseif (strcmp (extrap, "extrap")) + extrap = []; + else + error ('interp2: EXTRAP must be a numeric scalar or "extrap"'); endif ## Define X, Y, XI, YI if needed @@ -171,21 +180,32 @@ error ("interp2: XI, YI must be numeric"); endif - - if (strcmp (method, "linear") || strcmp (method, "nearest") ... - || strcmp (method, "pchip")) + if (isvector (X) && isvector (Y)) + X = X(:); Y = Y(:); + elseif (size_equal (X, Y)) + X = X(1,:).'; Y = Y(:,1); + else + error ("interp2: X and Y must be matrices of equal size"); + endif + if (columns (Z) != length (X) || rows (Z) != length (Y)) + error ("interp2: X and Y size must match the dimensions of Z"); + endif + dx = diff (X); + if (all (dx < 0)) + X = flipud (X); + Z = fliplr (Z); + elseif (any (dx <= 0)) + error ("interp2: X must be strictly monotonic"); + endif + dy = diff (Y); + if (all (dy < 0)) + Y = flipud (Y); + Z = flipud (Z); + elseif (any (dy <= 0)) + error ("interp2: Y must be strictly monotonic"); + endif - ## If X and Y vectors produce a grid from them - if (isvector (X) && isvector (Y)) - X = X(:); Y = Y(:); - elseif (size_equal (X, Y)) - X = X(1,:)'; Y = Y(:,1); - else - error ("interp2: X and Y must be matrices of same size"); - endif - if (columns (Z) != length (X) || rows (Z) != length (Y)) - error ("interp2: X and Y size must match the dimensions of Z"); - endif + if (any (strcmp (method, {"nearest", "linear", "pchip", "cubic"}))) ## If Xi and Yi are vectors of different orientation build a grid if ((rows (XI) == 1 && columns (YI) == 1) @@ -244,10 +264,11 @@ idx = sub2ind (size (Z), yidx+jj, xidx+ii); ZI = Z(idx); - elseif (strcmp (method, "pchip")) + elseif (strcmp (method, "pchip") || strcmp (method, "cubic")) if (length (X) < 2 || length (Y) < 2) - error ("interp2: pchip2 requires at least 2 points in each dimension"); + error ("interp2: %s requires at least 2 points in each dimension", + method); endif ## first order derivatives @@ -303,121 +324,114 @@ endif - if (! isempty (extrapval)) - ## set points outside the table to 'extrapval' - if (X (1) < X (end)) - if (Y (1) < Y (end)) - ZI (XI < X(1,1) | XI > X(end) | YI < Y(1,1) | YI > Y(end)) = ... - extrapval; + if (! isempty (extrap)) + ## set points outside the table to 'extrap' + if (X(1) < X(end)) + if (Y(1) < Y(end)) + ZI(XI < X(1,1) | XI > X(end) | YI < Y(1,1) | YI > Y(end)) = ... + extrap; else - ZI (XI < X(1) | XI > X(end) | YI < Y(end) | YI > Y(1)) = ... - extrapval; + ZI(XI < X(1) | XI > X(end) | YI < Y(end) | YI > Y(1)) = ... + extrap; endif else - if (Y (1) < Y (end)) - ZI (XI < X(end) | XI > X(1) | YI < Y(1) | YI > Y(end)) = ... - extrapval; + if (Y(1) < Y(end)) + ZI(XI < X(end) | XI > X(1) | YI < Y(1) | YI > Y(end)) = ... + extrap; else - ZI (XI < X(1,end) | XI > X(1) | YI < Y(end) | YI > Y(1)) = ... - extrapval; + ZI(XI < X(1,end) | XI > X(1) | YI < Y(end) | YI > Y(1)) = ... + extrap; endif endif endif else - ## Check dimensions of X and Y - if (isvector (X) && isvector (Y)) - X = X(:).'; - Y = Y(:); - if (!isequal ([length(Y), length(X)], size(Z))) - error ("interp2: X and Y size must match the dimensions of Z"); - endif - elseif (!size_equal (X, Y)) - error ("interp2: X and Y must be matrices of equal size"); - if (! size_equal (X, Z)) - error ("interp2: X and Y size must match the dimensions of Z"); - endif - endif - ## Check dimensions of XI and YI if (isvector (XI) && isvector (YI) && ! size_equal (XI, YI)) - XI = XI(:).'; - YI = YI(:); - [XI, YI] = meshgrid (XI, YI); + XI = XI(:).'; YI = YI(:); elseif (! size_equal (XI, YI)) error ("interp2: XI and YI must be matrices of equal size"); endif + ## FIXME: Previously used algorithm for cubic. + ## This produced results within a few eps of "spline". + ## Matlab compatibility requires "cubic" to be a C1 algorithm + ## equivalent to "pchip" so this was commented out 2014/03/30. + ## This can be removed completely in the future if no problems are + ## encountered. + #{ if (strcmp (method, "cubic")) if (isgriddata (XI) && isgriddata (YI')) - ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrapval); + ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrap); elseif (isgriddata (X) && isgriddata (Y')) ## Allocate output ZI = zeros (size (X)); ## Find inliers - inside = !(XI < X (1) | XI > X (end) | YI < Y (1) | YI > Y (end)); + inside = !(XI < X(1) | XI > X(end) | YI < Y(1) | YI > Y(end)); ## Scale XI and YI to match indices of Z - XI = (columns (Z) - 1) * (XI - X (1)) / (X (end) - X (1)) + 1; - YI = (rows (Z) - 1) * (YI - Y (1)) / (Y (end) - Y (1)) + 1; + XI = (columns (Z) - 1) * (XI - X(1)) / (X(end) - X(1)) + 1; + YI = (rows (Z) - 1) * (YI - Y(1)) / (Y(end) - Y(1)) + 1; ## Start the real work K = floor (XI); L = floor (YI); ## Coefficients - AY1 = bc ((YI - L + 1)); - AX1 = bc ((XI - K + 1)); - AY0 = bc ((YI - L + 0)); - AX0 = bc ((XI - K + 0)); - AY_1 = bc ((YI - L - 1)); - AX_1 = bc ((XI - K - 1)); - AY_2 = bc ((YI - L - 2)); - AX_2 = bc ((XI - K - 2)); + AY1 = bc (YI - L + 1); + AX1 = bc (XI - K + 1); + AY0 = bc (YI - L + 0); + AX0 = bc (XI - K + 0); + AY_1 = bc (YI - L - 1); + AX_1 = bc (XI - K - 1); + AY_2 = bc (YI - L - 2); + AX_2 = bc (XI - K - 2); ## Perform interpolation sz = size (Z); - ZI = AY_2 .* AX_2 .* Z (sym_sub2ind (sz, L+2, K+2)) ... - + AY_2 .* AX_1 .* Z (sym_sub2ind (sz, L+2, K+1)) ... - + AY_2 .* AX0 .* Z (sym_sub2ind (sz, L+2, K)) ... - + AY_2 .* AX1 .* Z (sym_sub2ind (sz, L+2, K-1)) ... - + AY_1 .* AX_2 .* Z (sym_sub2ind (sz, L+1, K+2)) ... - + AY_1 .* AX_1 .* Z (sym_sub2ind (sz, L+1, K+1)) ... - + AY_1 .* AX0 .* Z (sym_sub2ind (sz, L+1, K)) ... - + AY_1 .* AX1 .* Z (sym_sub2ind (sz, L+1, K-1)) ... - + AY0 .* AX_2 .* Z (sym_sub2ind (sz, L, K+2)) ... - + AY0 .* AX_1 .* Z (sym_sub2ind (sz, L, K+1)) ... - + AY0 .* AX0 .* Z (sym_sub2ind (sz, L, K)) ... - + AY0 .* AX1 .* Z (sym_sub2ind (sz, L, K-1)) ... - + AY1 .* AX_2 .* Z (sym_sub2ind (sz, L-1, K+2)) ... - + AY1 .* AX_1 .* Z (sym_sub2ind (sz, L-1, K+1)) ... - + AY1 .* AX0 .* Z (sym_sub2ind (sz, L-1, K)) ... - + AY1 .* AX1 .* Z (sym_sub2ind (sz, L-1, K-1)); - ZI (!inside) = extrapval; + ZI = AY_2 .* AX_2 .* Z(sym_sub2ind (sz, L+2, K+2)) ... + + AY_2 .* AX_1 .* Z(sym_sub2ind (sz, L+2, K+1)) ... + + AY_2 .* AX0 .* Z(sym_sub2ind (sz, L+2, K)) ... + + AY_2 .* AX1 .* Z(sym_sub2ind (sz, L+2, K-1)) ... + + AY_1 .* AX_2 .* Z(sym_sub2ind (sz, L+1, K+2)) ... + + AY_1 .* AX_1 .* Z(sym_sub2ind (sz, L+1, K+1)) ... + + AY_1 .* AX0 .* Z(sym_sub2ind (sz, L+1, K)) ... + + AY_1 .* AX1 .* Z(sym_sub2ind (sz, L+1, K-1)) ... + + AY0 .* AX_2 .* Z(sym_sub2ind (sz, L, K+2)) ... + + AY0 .* AX_1 .* Z(sym_sub2ind (sz, L, K+1)) ... + + AY0 .* AX0 .* Z(sym_sub2ind (sz, L, K)) ... + + AY0 .* AX1 .* Z(sym_sub2ind (sz, L, K-1)) ... + + AY1 .* AX_2 .* Z(sym_sub2ind (sz, L-1, K+2)) ... + + AY1 .* AX_1 .* Z(sym_sub2ind (sz, L-1, K+1)) ... + + AY1 .* AX0 .* Z(sym_sub2ind (sz, L-1, K)) ... + + AY1 .* AX1 .* Z(sym_sub2ind (sz, L-1, K-1)); + ZI (!inside) = extrap; else error ("interp2: input data must have 'meshgrid' format"); endif + #} - elseif (strcmp (method, "spline")) + if (strcmp (method, "spline")) if (isgriddata (XI) && isgriddata (YI')) - ZI = __splinen__ ({Y(:,1).', X(1,:)}, Z, {YI(:,1), XI(1,:)}, extrapval, - "spline"); + ZI = __splinen__ ({Y, X}, Z, {YI(:,1), XI(1,:)}, extrap, + "spline"); else - error ("interp2: input data must have 'meshgrid' format"); + error ("interp2: XI, YI must have uniform spacing ('meshgrid' format)"); endif else - error ("interp2: interpolation METHOD not recognized"); + error ("interp2: unrecognized interpolation method '%s'", method); endif endif + endfunction function b = isgriddata (X) d1 = diff (X, 1, 1); - b = all (d1 (:) == 0); + b = all (d1(:) == 0); endfunction ## Compute the bicubic interpolation coefficients @@ -432,16 +446,16 @@ ## This version of sub2ind behaves as if the data was symmetrically padded function ind = sym_sub2ind (sz, Y, X) - Y (Y < 1) = 1 - Y (Y < 1); - while (any (Y (:) > 2 * sz (1))) - Y (Y > 2 * sz (1)) = round (Y (Y > 2 * sz (1)) / 2); + Y(Y < 1) = 1 - Y(Y < 1); + while (any (Y(:) > 2*sz(1))) + Y(Y > 2*sz(1)) = round (Y(Y > 2*sz(1)) / 2); endwhile - Y (Y > sz (1)) = 1 + 2 * sz (1) - Y (Y > sz (1)); - X (X < 1) = 1 - X (X < 1); - while (any (X (:) > 2 * sz (2))) - X (X > 2 * sz (2)) = round (X (X > 2 * sz (2)) / 2); + Y(Y > sz(1)) = 1 + 2*sz(1) - Y(Y > sz(1)); + X(X < 1) = 1 - X(X < 1); + while (any (X(:) > 2*sz(2))) + X(X > 2 * sz(2)) = round (X(X > 2*sz(2)) / 2); endwhile - X (X > sz (2)) = 1 + 2 * sz (2) - X (X > sz (2)); + X(X > sz(2)) = 1 + 2*sz(2) - X(X > sz(2)); ind = sub2ind (sz, Y, X); endfunction @@ -455,7 +469,7 @@ %! yi = linspace (min (y), max (y), 26)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "linear")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; %!demo %! clf; @@ -466,7 +480,7 @@ %! yi = linspace (min (y), max (y), 41)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "linear")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; %!demo %! clf; @@ -477,7 +491,7 @@ %! yi = linspace (min (y), max (y), 26)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "nearest")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; %!demo %! clf; @@ -488,9 +502,10 @@ %! yi = linspace (min (y), max (y), 41)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "nearest")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; -%!demo +## 'pchip' commented out since it is the same as 'cubic' +%!#demo %! clf; %! colormap ("default"); %! A = [13,-1,12;5,4,3;1,6,2]; @@ -499,9 +514,10 @@ %! yi = linspace (min (y), max (y), 26)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "pchip")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; -%!demo +## 'pchip' commented out since it is the same as 'cubic' +%!#demo %! clf; %! colormap ("default"); %! [x,y,A] = peaks (10); @@ -510,7 +526,7 @@ %! yi = linspace (min (y), max (y), 41)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "pchip")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; %!demo %! clf; @@ -521,7 +537,7 @@ %! yi = linspace (min (y), max (y), 26)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "cubic")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; %!demo %! clf; @@ -532,7 +548,7 @@ %! yi = linspace (min (y), max (y), 41)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "cubic")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; %!demo %! clf; @@ -543,7 +559,7 @@ %! yi = linspace (min (y), max (y), 26)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "spline")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; %!demo %! clf; @@ -554,68 +570,75 @@ %! yi = linspace (min (y), max (y), 41)'; %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "spline")); %! [x,y] = meshgrid (x,y); -%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off; +%! hold on; plot3 (x,y,A,"b*"); hold off; -%!test % simple test +%!test # simple test %! x = [1,2,3]; %! y = [4,5,6,7]; %! [X, Y] = meshgrid (x, y); -%! Orig = X.^2 + Y.^3; +%! orig = X.^2 + Y.^3; %! xi = [1.2,2, 1.5]; %! yi = [6.2, 4.0, 5.0]'; %! -%! Expected = ... +%! expected = ... %! [243, 245.4, 243.9; %! 65.6, 68, 66.5; %! 126.6, 129, 127.5]; -%! Result = interp2 (x,y,Orig, xi, yi); +%! result = interp2 (x,y,orig, xi, yi); %! -%! assert (Result, Expected, 1000*eps); +%! assert (result, expected, 1000*eps); -%!test % 2^n form +%!test # 2^n refinement form %! x = [1,2,3]; %! y = [4,5,6,7]; %! [X, Y] = meshgrid (x, y); -%! Orig = X.^2 + Y.^3; +%! orig = X.^2 + Y.^3; %! xi = [1:0.25:3]; yi = [4:0.25:7]'; -%! Expected = interp2 (x,y,Orig, xi, yi); -%! Result = interp2 (Orig, 2); +%! expected = interp2 (x,y,orig, xi, yi); +%! result = interp2 (orig, 2); %! -%! assert (Result, Expected, 10*eps); +%! assert (result, expected, 10*eps); -%!test % matrix slice +%!test # matrix slice %! A = eye (4); %! assert (interp2 (A,[1:4],[1:4]), [1,1,1,1]); -%!test % non-gridded XI,YI +%!test # non-gridded XI,YI %! A = eye (4); %! assert (interp2 (A,[1,2;3,4],[1,3;2,4]), [1,0;0,1]); -%!test % for values outside of boundaries +%!test # for values outside of boundaries %! x = [1,2,3]; %! y = [4,5,6,7]; %! [X, Y] = meshgrid (x,y); -%! Orig = X.^2 + Y.^3; +%! orig = X.^2 + Y.^3; %! xi = [0,4]; %! yi = [3,8]'; -%! assert (interp2 (x,y,Orig, xi, yi), [NA,NA;NA,NA]); -%! assert (interp2 (x,y,Orig, xi, yi,"linear", 0), [0,0;0,0]); +%! assert (interp2 (x,y,orig, xi, yi), [NA,NA;NA,NA]); +%! assert (interp2 (x,y,orig, xi, yi,"linear", 0), [0,0;0,0]); +%! assert (interp2 (x,y,orig, xi, yi,"linear", "extrap"), [1,17;468,484]); +%! assert (interp2 (x,y,orig, xi, yi,"nearest", "extrap"), orig([1,end],[1,end])); -%!test % for values at boundaries -%! A=[1,2;3,4]; -%! x=[0,1]; -%! y=[2,3]'; +%!test # for values at boundaries +%! A = [1,2;3,4]; +%! x = [0,1]; +%! y = [2,3]'; %! assert (interp2 (x,y,A,x,y,"linear"), A); %! assert (interp2 (x,y,A,x,y,"nearest"), A); -%!test % for Matlab-compatible rounding for 'nearest' +%!test # for Matlab-compatible rounding for 'nearest' %! X = meshgrid (1:4); %! assert (interp2 (X, 2.5, 2.5, "nearest"), 3); +## re-order monotonically decreasing (bug #41838). +%!assert (interp2 ([1 2 3], [3 2 1], magic (3), 2.5, 3), 3.5); +%!assert (interp2 ([3 2 1], [1 2 3], magic (3), 1.5, 1), 3.5); + %!shared z, zout, tol %! z = [1 3 5; 3 5 7; 5 7 9]; %! zout = [1 2 3 4 5; 2 3 4 5 6; 3 4 5 6 7; 4 5 6 7 8; 5 6 7 8 9]; %! tol = 2 * eps; +%! %!assert (interp2 (z), zout, tol) %!assert (interp2 (z, "linear"), zout, tol) %!assert (interp2 (z, "pchip"), zout, tol) @@ -630,3 +653,32 @@ %!assert (interp2 (z, [2 3 1], [2 2 2], "cubic"), [5 7 3], 10 * tol) %!assert (interp2 (z, [2 3 1], [2 2 2], "spline"), [5 7 3], tol) +%% Test input validation +%!error interp2 ({1}) +%!error interp2 (ones (2,2,2)) +%!error interp2 (1, ones (2)) +%!error interp2 (1, -1) +%!error interp2 (1, 1.5) +%!error interp2 (1, 1, 1, 1, 1, 2) +%!warning interp2 (rand (3,3), 1, "*linear"); +%!error interp2 (1, 1, 1, 1, 1, 'linear', {1}) +%!error interp2 (1, 1, 1, 1, 1, 'linear', ones (2,2)) +%!error interp2 (1, 1, 1, 1, 1, 'linear', "abc") +%!error interp2 ({1}, 1, 1, 1, 1) +%!error interp2 (1, {1}, 1, 1, 1) +%!error interp2 (1, 1, 1, {1}, 1) +%!error interp2 (1, 1, 1, 1, {1}) +%!error interp2 (ones(2,2), 1, 1, 1, 1) +%!error interp2 (ones(2,2), ones(2,3), 1, 1, 1) +%!error interp2 (1:3, 1:3, ones (3,2), 1, 1) +%!error interp2 (1:2, 1:2, ones (3,2), 1, 1) +%!error interp2 ([1 0 2], 1:3, ones (3,3), 1, 1) +%!error interp2 (1:3, [1 0 2], ones (3,3), 1, 1) +%!error interp2 (1, 1, 1, ones(2,2), 1) +%!error interp2 (1, 1, 1, 1, ones(2,2)) +%!error interp2 (1, 1, 1, 1, 1, "pchip") +%!error interp2 (1, 1, 1, 1, 1, "cubic") +%!error interp2 (1, 1, 1, [1 2 4], [1 2 3], "spline") +%!error interp2 (1, 1, 1, [1 2 3], [1 2 4], "spline") +%!error interp2 (1, 1, 1, 1, 1, "foobar") + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/interp3.m --- a/scripts/general/interp3.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/interp3.m Sun May 25 10:29:05 2014 -0700 @@ -19,52 +19,72 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {@var{vi} =} interp3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi}) ## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{xi}, @var{yi}, @var{zi}) -## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{m}) +## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{n}) ## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}) ## @deftypefnx {Function File} {@var{vi} =} interp3 (@dots{}, @var{method}) ## @deftypefnx {Function File} {@var{vi} =} interp3 (@dots{}, @var{method}, @var{extrapval}) ## -## Perform 3-dimensional interpolation. Each element of the 3-dimensional -## array @var{v} represents a value at a location given by the parameters -## @var{x}, @var{y}, and @var{z}. The parameters @var{x}, @var{x}, and -## @var{z} are either 3-dimensional arrays of the same size as the array -## @var{v} in the @qcode{"meshgrid"} format or vectors. The parameters -## @var{xi}, etc. respect a similar format to @var{x}, etc., and they -## represent the points at which the array @var{vi} is interpolated. +## Three-dimensional interpolation. +## +## Interpolate reference data @var{x}, @var{y}, @var{z}, @var{v} to determine +## @var{vi} at the coordinates @var{xi}, @var{yi}, @var{zi}. The reference +## data @var{x}, @var{y}, @var{z} can be matrices, as returned by +## @code{meshgrid}, in which case the sizes of +## @var{x}, @var{y}, @var{z}, and @var{v} must be equal. If @var{x}, @var{y}, +## @var{z} are vectors describing a cubic grid then +## @code{length (@var{x}) == columns (@var{v})}, +## @code{length (@var{y}) == rows (@var{v})}, +## and @code{length (@var{z}) == size (@var{v}, 3)}. In either case the input +## data must be strictly monotonic. ## -## If @var{x}, @var{y}, @var{z} are omitted, they are assumed to be -## @code{x = 1 : size (@var{v}, 2)}, @code{y = 1 : size (@var{v}, 1)} and -## @code{z = 1 : size (@var{v}, 3)}. If @var{m} is specified, then -## the interpolation adds a point half way between each of the interpolation -## points. This process is performed @var{m} times. If only @var{v} is -## specified, then @var{m} is assumed to be @code{1}. +## If called without @var{x}, @var{y}, @var{z}, and just a single reference +## data matrix @var{v}, the 3-D region +## @code{@var{x} = 1:columns (@var{v}), @var{y} = 1:rows (@var{v}), +## @var{z} = 1:size (@var{v}, 3)} is assumed. +## This saves memory if the grid is regular and the distance between points is +## not important. ## -## Method is one of: +## If called with a single reference data matrix @var{v} and a refinement +## value @var{n}, then perform interpolation over a 3-D grid where each original +## interval has been recursively subdivided @var{n} times. This results in +## @code{2^@var{n}-1} additional points for every interval in the original +## grid. If @var{n} is omitted a value of 1 is used. As an example, the +## interval [0,1] with @code{@var{n}==2} results in a refined interval with +## points at [0, 1/4, 1/2, 3/4, 1]. +## +## The interpolation @var{method} is one of: ## ## @table @asis ## @item @qcode{"nearest"} ## Return the nearest neighbor. ## -## @item @qcode{"linear"} +## @item @qcode{"linear"} (default) ## Linear interpolation from nearest neighbors. ## +## @item @qcode{"pchip"} +## Piecewise cubic Hermite interpolating polynomial---shape-preserving +## interpolation with smooth first derivative (not implemented yet). +## ## @item @qcode{"cubic"} -## Cubic interpolation from four nearest neighbors (not implemented yet). +## Cubic interpolation (same as @qcode{"pchip"} [not implemented yet]). ## ## @item @qcode{"spline"} ## Cubic spline interpolation---smooth first and second derivatives ## throughout the curve. ## @end table ## -## The default method is @qcode{"linear"}. -## -## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values -## beyond the endpoints. If @var{extrap} is a number, replace values beyond -## the endpoints with that number. If @var{extrap} is missing, assume NA. -## @seealso{interp1, interp2, spline, meshgrid} +## If @var{extrapval} is a number, then replace values beyond the endpoints +## with that number. When unspecified, @var{extrapval} defaults to @code{NA}. +## Note that if @var{extrapval} is used, @var{method} must be specified as well. +## @seealso{interp1, interp2, interpn, meshgrid} ## @end deftypefn +## FIXME: Need to validate N argument (maybe change interpn). +## FIXME: Need to add support for 'pchip' method (maybe change interpn). +## FIXME: Need to add support for "extrap" string value (maybe change interpn). + function vi = interp3 (varargin) + method = "linear"; extrapval = NA; nargs = nargin; @@ -75,112 +95,143 @@ if (ischar (varargin{end})) method = varargin{end}; - nargs = nargs - 1; - elseif (nargs > 1 && ischar (varargin{end - 1})) + nargs--; + elseif (nargs > 1 && ischar (varargin{end-1})) + ## FIXME: No support for "extrap" string if (! isnumeric (varargin{end}) || ! isscalar (varargin{end})) - error ("interp3: extrapal is expected to be a numeric scalar"); + error ("interp3: EXTRAPVAL must be a numeric scalar"); endif extrapval = varargin{end}; method = varargin{end-1}; - nargs = nargs - 2; + nargs -= 2; endif - if (nargs < 3 || (nargs == 4 && ! isvector (varargin{1}) - && nargs == (ndims (varargin{1}) + 1))) + if (method(1) == "*") + warning ("interp3: ignoring unsupported '*' flag to METHOD"); + method(1) = []; + endif + + if (nargs < 3) + ## Calling form interp3 (v) OR interp3 (v, n) v = varargin{1}; if (ndims (v) != 3) - error ("interp3: expect 3-dimensional array of values"); + error ("interp3: V must be a 3-D array of values"); endif - x = varargin (2:nargs); - if (any (! cellfun (@isvector, x))) - for i = 2 : 3 - if (! size_equal (x{1}, x{i})) - error ("interp3: dimensional mismatch"); - endif - x{i} = permute (x{i}, [2, 1, 3]); + n = varargin(2:nargs); + v = permute (v, [2, 1, 3]); + vi = ipermute (interpn (v, n{:}, method, extrapval), [2, 1, 3]); + + elseif (nargs == 4 && ! isvector (varargin{1})) + ## Calling form interp3 (v, xi, yi, zi) + v = varargin{1}; + if (ndims (v) != 3) + error ("interp3: V must be a 3-D array of values"); + endif + xi = varargin(2:4); + if (any (! cellfun (@isvector, xi))) + ## Meshgridded values rather than vectors + if (! size_equal (xi{:})) + error ("interp3: XI, YI, and ZI dimensions must be equal"); + endif + for i = 1 : 3 + xi{i} = permute (xi{i}, [2, 1, 3]); endfor - x{1} = permute (x{1}, [2, 1, 3]); endif v = permute (v, [2, 1, 3]); - vi = ipermute (interpn (v, x{:}, method, extrapval), [2, 1, 3]); - elseif (nargs == 7 && nargs == (2 * ndims (varargin{ceil (nargs / 2)})) + 1) + vi = ipermute (interpn (v, xi{:}, method, extrapval), [2, 1, 3]); + + elseif (nargs == 7) + ## Calling form interp3 (x, y, z, v, xi, yi, zi) v = varargin{4}; if (ndims (v) != 3) - error ("interp3: expect 3-dimensional array of values"); + error ("interp3: V must be a 3-D array of values"); endif - x = varargin (1:3); + x = varargin(1:3); if (any (! cellfun (@isvector, x))) - for i = 2 : 3 - if (! size_equal (x{1}, x{i}) || ! size_equal (x{i}, v)) - error ("interp3: dimensional mismatch"); - endif + ## Meshgridded values rather than vectors + if (! size_equal (x{:}, v)) + error ("interp3: X, Y, Z, and V dimensions must be equal"); + endif + for i = 1 : 3 x{i} = permute (x{i}, [2, 1, 3]); endfor - x{1} = permute (x{1}, [2, 1, 3]); endif - y = varargin (5:7); - if (any (! cellfun (@isvector, y))) - for i = 2 : 3 - if (! size_equal (y{1}, y{i})) - error ("interp3: dimensional mismatch"); - endif - y{i} = permute (y{i}, [2, 1, 3]); + xi = varargin(5:7); + if (any (! cellfun (@isvector, xi))) + ## Meshgridded values rather than vectors + if (! size_equal (xi{:})) + error ("interp3: XI, YI, and ZI dimensions must be equal"); + endif + for i = 1 : 3 + xi{i} = permute (xi{i}, [2, 1, 3]); endfor - y{1} = permute (y{1}, [2, 1, 3]); endif v = permute (v, [2, 1, 3]); - vi = ipermute (interpn (x{:}, v, y{:}, method, extrapval), [2, 1, 3]); + vi = ipermute (interpn (x{:}, v, xi{:}, method, extrapval), [2, 1, 3]); + else error ("interp3: wrong number or incorrectly formatted input arguments"); endif + endfunction -%!test -%! x = y = z = -1:1; y = y + 2; +%% FIXME: Need some demo blocks here to show off the function like interp2.m. + +%!test # basic test +%! x = y = z = -1:1; y = y + 2; %! f = @(x,y,z) x.^2 - y - z.^2; %! [xx, yy, zz] = meshgrid (x, y, z); %! v = f (xx,yy,zz); -%! xi = yi = zi = -1:0.5:1; yi = yi + 2.1; +%! xi = yi = zi = -1:0.5:1; yi = yi + 2.1; %! [xxi, yyi, zzi] = meshgrid (xi, yi, zi); %! vi = interp3 (x, y, z, v, xxi, yyi, zzi); %! [xxi, yyi, zzi] = ndgrid (yi, xi, zi); %! vi2 = interpn (y, x, z, v, xxi, yyi, zzi); -%! tol = 10 * eps; -%! assert (vi, vi2, tol); +%! assert (vi, vi2, 10*eps); -%!test -%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]); v(:,2,1)=[7 ;5;4]; v(:,1,2)=[2 ;3;5]; +%!test # meshgridded xi, yi, zi +%! x = z = 1:2; y = 1:3; +%! v = ones ([3,2,2]); v(:,2,1) = [7;5;4]; v(:,1,2) = [2;3;5]; +%! xi = zi = .6:1.6; yi = 1; %! [xxi3, yyi3, zzi3] = meshgrid (xi, yi, zi); %! [xxi, yyi, zzi] = ndgrid (yi, xi, zi); %! vi = interp3 (x, y, z, v, xxi3, yyi3, zzi3, "nearest"); -%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi,"nearest"); +%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi, "nearest"); %! assert (vi, vi2); -%!test -%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]); v(:,2,1)=[7 ;5;4]; v(:,1,2)=[2 ;3;5]; -%! vi = interp3 (x, y, z, v, xi+1, yi, zi, "nearest",3); -%! vi2 = interpn (y, x, z, v, yi, xi+1, zi,"nearest", 3); -%! assert (vi, vi2); - -%!test -%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]); v(:,2,1)=[7 ;5;4]; v(:,1,2)=[2 ;3;5]; +%!test # vector xi, yi, zi +%! x = z = 1:2; y = 1:3; +%! v = ones ([3,2,2]); v(:,2,1) = [7;5;4]; v(:,1,2) = [2;3;5]; +%! xi = zi = .6:1.6; yi = 1; %! vi = interp3 (x, y, z, v, xi, yi, zi, "nearest"); %! vi2 = interpn (y, x, z, v, yi, xi, zi,"nearest"); %! assert (vi, vi2); -%!test -%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]); v(:,2,1)=[7 ;5;4]; v(:,1,2)=[2 ;3;5]; -%! vi = interp3 (v, xi, yi, zi, "nearest",3); -%! vi2 = interpn (v, yi, xi, zi,"nearest", 3); +%!test # vector xi+1 with extrap value +%! x = z = 1:2; y = 1:3; +%! v = ones ([3,2,2]); v(:,2,1) = [7;5;4]; v(:,1,2) = [2;3;5]; +%! xi = zi = .6:1.6; yi = 1; +%! vi = interp3 (x, y, z, v, xi+1, yi, zi, "nearest", 3); +%! vi2 = interpn (y, x, z, v, yi, xi+1, zi, "nearest", 3); %! assert (vi, vi2); -%!test -%! xi=zi=.6:1.6; yi=1; v=ones([3,2,2]); v(:,2,1)=[7 ;5;4]; v(:,1,2)=[2 ;3;5]; +%!test # input value matrix--no x,y,z +%! x = z = 1:2; y = 1:3; +%! v = ones ([3,2,2]); v(:,2,1) = [7;5;4]; v(:,1,2) = [2;3;5]; +%! xi = zi = .6:1.6; yi = 1; %! vi = interp3 (v, xi, yi, zi, "nearest"); %! vi2 = interpn (v, yi, xi, zi,"nearest"); %! assert (vi, vi2); +%!test # input value matrix--no x,y,z, with extrap value +%! x = z = 1:2; y = 1:3; +%! v = ones ([3,2,2]); v(:,2,1) = [7;5;4]; v(:,1,2) = [2;3;5]; +%! xi = zi = .6:1.6; yi = 1; +%! vi = interp3 (v, xi, yi, zi, "nearest", 3); +%! vi2 = interpn (v, yi, xi, zi, "nearest", 3); +%! assert (vi, vi2); + %!shared z, zout, tol %! z = zeros (3, 3, 3); %! zout = zeros (5, 5, 5); @@ -195,7 +246,21 @@ %! 5 6 7 8 9] + (n-1); %! end %! tol = 10 * eps; +%! %!assert (interp3 (z), zout, tol) %!assert (interp3 (z, "linear"), zout, tol) %!assert (interp3 (z, "spline"), zout, tol) +%% Test input validation +%!error interp3 () +%!error interp3 ({1}) +%!error interp3 (1,2,3,4,1,2,3,"linear", {1}) +%!error interp3 (1,2,3,4,1,2,3,"linear", ones (2,2)) +%!warning interp3 (rand (3,3,3), 1, "*linear"); +%!error interp3 (rand (2,2)) +%!error interp3 (rand (2,2), 1,1,1) +%!error interp3 (rand (2,2,2), 1,1, ones (2,2)) +%!error interp3 (1:2, 1:2, 1:2, rand (2,2), 1,1,1) +%!error interp3 (ones(1,2,2), ones(2,2,2), ones(2,2,2), rand (2,2,2), 1,1,1) +%!error interp3 (1:2, 1:2, 1:2, rand (2,2,2), 1,1, ones (2,2)) + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/interpn.m --- a/scripts/general/interpn.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/interpn.m Sun May 25 10:29:05 2014 -0700 @@ -86,6 +86,11 @@ nargs -= 2; endif + if (method(1) == "*") + warning ("interpn: ignoring unsupported '*' flag to METHOD"); + method(1) = []; + endif + if (nargs < 3) v = varargin{1}; m = 1; @@ -318,3 +323,6 @@ %! assert (interpn (z, "linear"), zout, tol); %! assert (interpn (z, "spline"), zout, tol); +%% Test input validation +%!warning interpn (rand (3,3), 1, "*linear"); + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/module.mk --- a/scripts/general/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/module.mk Sun May 25 10:29:05 2014 -0700 @@ -7,7 +7,6 @@ general_FCN_FILES = \ general/accumarray.m \ general/accumdim.m \ - general/bicubic.m \ general/bincoeff.m \ general/bitcmp.m \ general/bitget.m \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/private/__isequal__.m --- a/scripts/general/private/__isequal__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/private/__isequal__.m Sun May 25 10:29:05 2014 -0700 @@ -95,9 +95,9 @@ if (isstruct (x)) ## Test the number of fields. fn_x = fieldnames (x); - l_fn_x = length (fn_x); + l_fn_x = numfields (x); fn_v = cellfun ("fieldnames", varargin, "uniformoutput", false); - t = all (l_fn_x == cellfun ("length", fn_v)); + t = all (l_fn_x == cellfun ("numfields", varargin)); ## Test that all the names are equal. idx = 0; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/general/profshow.m --- a/scripts/general/profshow.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/general/profshow.m Sun May 25 10:29:05 2014 -0700 @@ -1,4 +1,4 @@ -## Copyright (C) 2012-2013 Daniel Kraft +## Copyright (C) 2012-2014 Daniel Kraft ## ## This file is part of Octave. ## @@ -19,17 +19,20 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} profshow (@var{data}) ## @deftypefnx {Function File} {} profshow (@var{data}, @var{n}) -## Show flat profiler results. +## @deftypefnx {Function File} {} profshow () +## @deftypefnx {Function File} {} profshow (@var{n}) +## Display flat per-function profiler results. ## -## This command prints out profiler data as a flat profile. @var{data} is the -## structure returned by @code{profile ("info")}. If @var{n} is given, it -## specifies the number of functions to show in the profile; functions are -## sorted in descending order by total time spent in them. If there are more -## than @var{n} included in the profile, those will not be shown. @var{n} +## Print out profiler data (execution time, number of calls) for the most +## critical @var{n} functions. The results are sorted in descending order by +## the total time spent in each function. If @var{n} is unspecified it ## defaults to 20. ## -## The attribute column shows @samp{R} for recursive functions and nothing -## otherwise. +## The input @var{data} is the structure returned by @code{profile ("info")}. +## If unspecified, @code{profshow} will use the current profile dataset. +## +## The attribute column displays @samp{R} for recursive functions, and is blank +## for all other function types. ## @seealso{profexplore, profile} ## @end deftypefn @@ -38,10 +41,17 @@ function profshow (data, n = 20) - if (nargin < 1 || nargin > 2) + if (nargin > 2) print_usage (); endif + if (nargin == 0) + data = profile ("info"); + elseif (nargin == 1 && ! isstruct (data)) + n = data; + data = profile ("info"); + endif + n = fix (n); if (! isscalar (n) || ! isreal (n) || ! (n > 0)) error ("profile: N must be a positive integer"); @@ -53,30 +63,32 @@ ## We want to sort by times in descending order. For this, extract the ## times to an array, then sort this, and use the resulting index permutation ## to print out our table. - times = -[ data.FunctionTable.TotalTime ]; + times = [ data.FunctionTable.TotalTime ]; + totalTime = sum (times); - [~, p] = sort (times); + [~, p] = sort (times, "descend"); ## For printing the table, find out the maximum length of a function name ## so that we can proportion the table accordingly. Based on this, ## we can build the format used for printing table rows. - nameLen = length ("Function"); - for i = 1 : n - nameLen = max (nameLen, length (data.FunctionTable(p(i)).FunctionName)); - endfor - headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%12s\n", nameLen); - rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%12d\n", nameLen); + nameLen = max (length ("Function"), + columns (char (data.FunctionTable(p(1:n)).FunctionName))); + headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%10s %%12s\n", nameLen); + rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%10.2f %%12d\n", nameLen); - printf (headerFormat, "#", "Function", "Attr", "Time (s)", "Calls"); - printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 2 * 13)); + printf (headerFormat, ... + "#", "Function", "Attr", "Time (s)", "Time (%)", "Calls"); + printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 11 + 2 * 13)); + for i = 1 : n row = data.FunctionTable(p(i)); + timePercent = 100 * row.TotalTime / totalTime; attr = ""; if (row.IsRecursive) attr = "R"; endif - printf (rowFormat, p(i), row.FunctionName, attr, ... - row.TotalTime, row.NumCalls); + printf (rowFormat, p(i), row.FunctionName, attr, + row.TotalTime, timePercent, row.NumCalls); endfor endfunction @@ -96,7 +108,6 @@ %! profile off; %! profshow (profile ("info"), 5); -%!error profshow () %!error profshow (1, 2, 3) %!error profshow (struct (), ones (2)) %!error profshow (struct (), 1+i) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/geometry/voronoi.m --- a/scripts/geometry/voronoi.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/geometry/voronoi.m Sun May 25 10:29:05 2014 -0700 @@ -74,14 +74,13 @@ endif narg = 1; + hax = NaN; if (isscalar (varargin{1}) && ishandle (varargin{1})) hax = varargin{1}; - if (! isaxes (harg)) - error ("imagesc: HAX argument must be an axes object"); + if (! isaxes (hax)) + error ("voronoi: HAX argument must be an axes object"); endif narg++; - elseif (nargout < 2) - hax = gca (); endif if (nargin < 1 + narg || nargin > 3 + narg) @@ -108,6 +107,8 @@ if (length (x) != length (y)) error ("voronoi: X and Y must be vectors of the same length"); + elseif (length (x) < 2) + error ("voronoi: minimum of 2 points needed"); endif ## Add box to approximate rays to infinity. For Voronoi diagrams the @@ -142,19 +143,35 @@ edges = edges(:, [(edges(1, 1 :end - 1) != edges(1, 2 : end) | ... edges(2, 1 :end - 1) != edges(2, 2 : end)), true]); - ## Eliminate the edges of the diagram representing the box - poutside = (1:rows (p)) ... - (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ... - p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta); - edgeoutside = ismember (edges(1, :), poutside) & ... - ismember (edges(2, :), poutside); - edges(:, edgeoutside) = []; + if (numel (x) > 2) + ## Eliminate the edges of the diagram representing the box + poutside = (1:rows (p)) ... + (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ... + p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta); + edgeoutside = ismember (edges(1, :), poutside) & ... + ismember (edges(2, :), poutside); + edges(:, edgeoutside) = []; + else + ## look for the edge between the two given points + for edge = edges(1:2,:) + if (det ([[[1;1],p(edge,1:2)];1,x(1),y(1)]) + * det ([[[1;1],p(edge,1:2)];1,x(2),y(2)]) < 0) + edges = edge; + break; + endif + endfor + ## Use larger plot limits to make it more likely single bisector is shown. + xdelta = ydelta = max (xdelta, ydelta); + endif ## Get points of the diagram Vvx = reshape (p(edges, 1), size (edges)); Vvy = reshape (p(edges, 2), size (edges)); if (nargout < 2) + if (isnan (hax)) + hax = gca (); + endif h = plot (hax, Vvx, Vvy, linespec{:}, x, y, '+'); lim = [xmin, xmax, ymin, ymax]; axis (lim + 0.1 * [[-1, 1] * xdelta, [-1, 1] * ydelta]); @@ -179,5 +196,18 @@ %! assert (vx(2,:), zeros (1, columns (vx)), eps); %! assert (vy(2,:), zeros (1, columns (vy)), eps); -%% FIXME: Need input validation tests +%!testif HAVE_QHULL +%! ## Special case of just 2 points +%! x = [0 1]; y = [1 0]; +%! [vx, vy] = voronoi (x,y); +%! assert (vx, [-0.7; 1.7], eps); +%! assert (vy, [-0.7; 1.7], eps); +%% Input validation tests +%!error voronoi () +%!error voronoi (ones (3,1)) +%!error voronoi (ones (3,1), ones (3,1), "bogus1", "bogus2", "bogus3") +%!error voronoi (0, ones (3,1), ones (3,1)) +%!error voronoi (ones (3,1), ones (4,1)) +%!error voronoi (2.5, 3.5) + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/errordlg.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/helpdlg.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/inputdlg.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/listdlg.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/msgbox.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/private/message_dialog.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/questdlg.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/gui/warndlg.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/help/__unimplemented__.m --- a/scripts/help/__unimplemented__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/help/__unimplemented__.m Sun May 25 10:29:05 2014 -0700 @@ -635,7 +635,6 @@ "graymon", "griddedInterpolant", "gsvd", - "guidata", "guide", "guihandles", "handle", @@ -649,8 +648,6 @@ "hdfinfo", "hdfread", "hgexport", - "hgload", - "hgsave", "hgsetget", "hgtransform", "ichol", @@ -671,10 +668,8 @@ "interpstreamspeed", "iscom", "isinterface", - "isjava", "isocaps", "isstudent", - "javachk", "ldl", "libfunctions", "libfunctionsview", @@ -684,7 +679,6 @@ "light", "lightangle", "lighting", - "linkaxes", "linkdata", "listfonts", "loadlibrary", diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/help/help.m --- a/scripts/help/help.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/help/help.m Sun May 25 10:29:05 2014 -0700 @@ -163,7 +163,7 @@ found = false; - dlist = find_dir_in_path (name, "all"); + dlist = dir_in_loadpath (name, "all"); for i = 1:numel (dlist) fname = make_absolute_filename (fullfile (dlist{i}, "Contents.m")); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/help/which.m --- a/scripts/help/which.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/help/which.m Sun May 25 10:29:05 2014 -0700 @@ -28,9 +28,21 @@ if (nargin > 0 && iscellstr (varargin)) m = __which__ (varargin{:}); + ## Check whether each name is a variable, variables take precedence over + ## functions in name resolution. + for i = 1:nargin + m(i).is_variable = evalin ("caller", + ["exist (\"" m(i).name "\", \"var\")"], false); + if (m(i).is_variable) + m(i).file = "variable"; + endif + endfor + if (nargout == 0) for i = 1:nargin - if (isempty (m(i).file)) + if (m(i).is_variable) + printf ("'%s' is a variable\n", m(i).name); + elseif (isempty (m(i).file)) if (! isempty (m(i).type)) printf ("'%s' is a %s\n", m(i).name, m(i).type); @@ -64,3 +76,17 @@ %!assert (which ("_NO_SUCH_NAME_"), "") +%!test +%! x = 3; +%! str = which ("x"); +%! assert (str, "variable"); + +%!test +%! str = which ("amd"); +%! assert (str(end-6:end), "amd.oct"); +%! amd = 12; +%! str = which ("amd"); +%! assert (str, "variable"); +%! clear amd; +%! str = which ("amd"); +%! assert (str(end-6:end), "amd.oct"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/image.m --- a/scripts/image/image.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/image.m Sun May 25 10:29:05 2014 -0700 @@ -139,13 +139,6 @@ function h = __img__ (hax, do_new, x, y, img, varargin) - ## FIXME: Hack for integer formats which use zero-based indexing - ## Hack favors correctness of display over size of image in memory. - ## True fix must be done in C++ code for renderer. - if (ndims (img) == 2 && (isinteger (img) || islogical (img))) - img = single (img) + 1; - endif - if (! isempty (img)) if (isempty (x)) @@ -198,7 +191,7 @@ endif # ! isempty (img) - set (hax, "view", [0, 90], "ydir", "reverse", "layer", "bottom"); + set (hax, "view", [0, 90], "ydir", "reverse", "layer", "top"); endif # do_new diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/imfinfo.m --- a/scripts/image/imfinfo.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/imfinfo.m Sun May 25 10:29:05 2014 -0700 @@ -18,8 +18,8 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {@var{info} =} imfinfo (@var{filename}) -## @deftypefnx {Function File} {@var{info} =} imfinfo (@var{filename}, @var{ext}) ## @deftypefnx {Function File} {@var{info} =} imfinfo (@var{url}) +## @deftypefnx {Function File} {@var{info} =} imfinfo (@dots{}, @var{ext}) ## Read image information from a file. ## ## @code{imfinfo} returns a structure containing information about the image @@ -148,14 +148,32 @@ ## Author: Soren Hauberg -function info = imfinfo (varargin) +function info = imfinfo (filename, varargin) if (nargin < 1 || nargin > 2) print_usage (); - elseif (! ischar (varargin{1})) + elseif (! ischar (filename)) error ("imfinfo: FILENAME must be a string"); - elseif (nargin > 1 && ! ischar (varargin{2})) + elseif (nargin > 1 && ! ischar (ext)) error ("imfinfo: EXT must be a string"); endif - info = imageIO (@__imfinfo__, "info", varargin, varargin{:}); + info = imageIO ("imfinfo", @__imfinfo__, "info", filename, varargin{:}); endfunction +## This test is the same as the similar one in imread. imfinfo must check +## if file exists before calling __imfinfo_. This test confirm this. +%!testif HAVE_MAGICK +%! fmt = fmt_ori = imformats ("jpg"); +%! fmt.info = @true; +%! error_thrown = false; +%! imformats ("update", "jpg", fmt); +%! unwind_protect +%! try +%! imread ("I sure hope this file does not exist.jpg"); +%! catch +%! error_thrown = true; +%! end_try_catch +%! unwind_protect_cleanup +%! imformats ("update", "jpg", fmt_ori); +%! end_unwind_protect +%! assert (error_thrown, true); + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/imformats.m --- a/scripts/image/imformats.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/imformats.m Sun May 25 10:29:05 2014 -0700 @@ -266,11 +266,10 @@ endfunction function match = find_ext_idx (formats, ext) - ## FIXME: is matlab sensitive to file extensions? ## XXX: what should we do if there's more than one hit? ## Should this function prevent the addition of ## duplicated extensions? - match = cellfun (@(x) any (strcmp (x, ext)), {formats.ext}); + match = cellfun (@(x) any (strcmpi (x, ext)), {formats.ext}); endfunction function bool = isa_magick (coder, filename) @@ -281,34 +280,68 @@ end_try_catch endfunction +## When imread or imfinfo are called, the file must exist or the +## function defined by imformats will never be called. Because +## of this, we must create a file for the tests to work. -## changing the function to read +## changing the function that does the reading %!testif HAVE_MAGICK -%! fmt = imformats ("jpg"); -%! fmt.read = @(x) size (x, 2); -%! imformats ("update", "jpg", fmt); -%! assert (imread ("this is 30 characters long.jpg"), 30); +%! fname = [tmpnam() ".jpg"]; +%! def_fmt = imformats (); +%! fid = fopen (fname, "w"); +%! unwind_protect +%! fmt = imformats ("jpg"); +%! fmt.read = @numel; +%! imformats ("update", "jpg", fmt); +%! assert (imread (fname), numel (fname)); +%! unwind_protect_cleanup +%! fclose (fid); +%! unlink (fname); +%! imformats (def_fmt); +%! end_unwind_protect ## adding a new format %!testif HAVE_MAGICK -%! fmt = imformats ("jpg"); -%! fmt.ext = "junk"; -%! fmt.read = @(x) true(); -%! imformats ("add", fmt); -%! assert (imread ("some file.junk"), true); +%! fname = [tmpnam() ".new_fmt"]; +%! def_fmt = imformats (); +%! fid = fopen (fname, "w"); +%! unwind_protect +%! fmt = imformats ("jpg"); # take jpg as template +%! fmt.ext = "new_fmt"; +%! fmt.read = @() true (); +%! imformats ("add", fmt); +%! assert (imread (fname), true); +%! unwind_protect_cleanup +%! fclose (fid); +%! unlink (fname); +%! imformats (def_fmt); +%! end_unwind_protect -## adding multiple formats in one way +## adding multiple formats at the same time %!testif HAVE_MAGICK -%! fmt = imformats ("jpg"); -%! fmt.ext = "junk1"; -%! fmt.read = @(x) true(); -%! fmt(2) = fmt(1); -%! fmt(2).ext = "junk2"; -%! imformats ("add", fmt); -%! assert (imread ("some file.junk1"), true); -%! assert (imread ("some file.junk2"), true); +%! fname1 = [tmpnam() ".new_fmt1"]; +%! fid1 = fopen (fname1, "w"); +%! fname2 = [tmpnam() ".new_fmt2"]; +%! fid2 = fopen (fname2, "w"); +%! def_fmt = imformats (); +%! unwind_protect +%! fmt = imformats ("jpg"); # take jpg as template +%! fmt.ext = "new_fmt1"; +%! fmt.read = @() true(); +%! fmt(2) = fmt(1); +%! fmt(2).ext = "new_fmt2"; +%! imformats ("add", fmt); +%! assert (imread (fname1), true); +%! assert (imread (fname2), true); +%! unwind_protect_cleanup +%! fclose (fid1); +%! fclose (fid2); +%! unlink (fname1); +%! unlink (fname2); +%! imformats (def_fmt); +%! end_unwind_protect -## changing format +## changing format and resetting back to default %!testif HAVE_MAGICK %! ori_fmt = mod_fmt = imformats ("jpg"); %! mod_fmt.description = "Another description"; @@ -319,10 +352,15 @@ %! new_fmt = imformats ("jpg"); %! assert (new_fmt.description, ori_fmt.description); -## FIXME: how to test for error together with testif? -## update to an invalid format -#%!testif HAVE_MAGICK -#%! fmt = imformats ("jpg"); -#%! fmt = rmfield (fmt, "read"); -#%! error imformats ("update", "jpg", fmt); +## updating to an invalid format should cause an error +%!testif HAVE_MAGICK +%! fmt = imformats ("jpg"); +%! fmt = rmfield (fmt, "read"); +%! error_thrown = false; +%! try +%! imformats ("update", "jpg", fmt); +%! catch +%! error_thrown = true; +%! end_try_catch +%! assert (error_thrown, true); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/imread.m --- a/scripts/image/imread.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/imread.m Sun May 25 10:29:05 2014 -0700 @@ -23,16 +23,16 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{img}, @var{map}, @var{alpha}] =} imread (@var{filename}) -## @deftypefnx {Function File} {[@dots{}] =} imread (@var{filename}, @var{ext}) ## @deftypefnx {Function File} {[@dots{}] =} imread (@var{url}) +## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{ext}) ## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{idx}) ## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{param1}, @var{val1}, @dots{}) ## Read images from various file formats. ## ## Reads an image as a matrix from the file @var{filename}. If there is ## no file @var{filename}, and @var{ext} was specified, it will look for -## a file named @var{filename} and extension @var{ext}, i.e., a file named -## @var{filename}.@var{ext}. +## a file with the extension @var{ext}. Finally, it will attempt to download +## and read an image from @var{url}. ## ## The size and class of the output depends on the ## format of the image. A color image is returned as an @@ -75,7 +75,17 @@ ## Controls the image region that is read. Takes as value a cell array ## with two arrays of 3 elements @code{@{@var{rows} @var{cols}@}}. The ## elements in the array are the start, increment and end pixel to be -## read. If the increment value is omitted, defaults to 1. +## read. If the increment value is omitted, defaults to 1. For example, +## the following are all equivalent: +## +## @example +## @group +## imread (filename, "PixelRegion", @{[200 600] [300 700]@}); +## imread (filename, "PixelRegion", @{[200 1 600] [300 1 700]@}); +## imread (filename)(200:600, 300:700); +## @end group +## @end example +## ## @end table ## ## @seealso{imwrite, imfinfo, imformats} @@ -88,23 +98,14 @@ ## Author: Stefan van der Walt ## Author: Andy Adler -function [img, varargout] = imread (varargin) +function [img, varargout] = imread (filename, varargin) if (nargin < 1) print_usage (); - elseif (! ischar (varargin{1})) + elseif (! ischar (filename)) error ("imread: FILENAME must be a string"); endif - ## In case the file format was specified as a separate argument we - ## do this. imageIO() will ignore the second part if filename on its - ## own is enough. And if the second argument was a parameter name instead - ## of an extension, it is still going to be passed to the next function - ## since we are passing the whole function input as well. - filename = {varargin{1}}; - if (nargin > 1 && ischar (varargin {2})) - filename{2} = varargin{2}; - endif - [img, varargout{1:nargout-1}] = imageIO (@__imread__, "read", filename, varargin{:}); + [img, varargout{1:nargout-1}] = imageIO ("imread", @__imread__, "read", filename, varargin{:}); endfunction @@ -139,3 +140,66 @@ %! assert (A(:,:,2), uint8 ([0, 255, 0; 255, 28, 255; 0, 255, 0])); %! assert (A(:,:,3), uint8 ([0, 255, 0; 255, 36, 255; 0, 255, 0])); +%!function [r, cmap, a] = write_and_read (w, varargin) +%! filename = [tmpnam() ".tif"]; +%! unwind_protect +%! imwrite (w, filename); +%! [r, cmap, a] = imread (filename, varargin{:}); +%! unwind_protect_cleanup +%! unlink (filename); +%! end_unwind_protect +%!endfunction + +## test PixelRegion option +%!testif HAVE_MAGICK +%! w = randi (255, 100, 100, "uint8"); +%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 70] [20 40]}); +%! assert (r, w(50:70, 20:40)) +%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 2 70] [20 3 40]}); +%! assert (r, w(50:2:70, 20:3:40)) + +## If a file does not exist, it's the job of imread to check the file +## exists before sending it over to __imread__ or whatever function +## is defined in imformats to handle that specific format. This is the +## same in imfinfo. So in this test we replace one format in imformats +## with something that will not give an error if the file is missing +## and make sure we do get an error. +%!testif HAVE_MAGICK +%! fmt = fmt_ori = imformats ("jpg"); +%! fmt.read = @true; +%! error_thrown = false; +%! imformats ("update", "jpg", fmt); +%! unwind_protect +%! try +%! imread ("I sure hope this file does not exist.jpg"); +%! catch +%! error_thrown = true; +%! end_try_catch +%! unwind_protect_cleanup +%! imformats ("update", "jpg", fmt_ori); +%! end_unwind_protect +%! assert (error_thrown, true); + +## make one of the formats read, return what it received as input to +## confirm that the input parsing is working correcly +%!testif HAVE_MAGICK +%! fname = [tmpnam() ".jpg"]; +%! def_fmt = imformats (); +%! fid = fopen (fname, "w"); +%! unwind_protect +%! fmt = imformats ("jpg"); +%! fmt.read = @(varargin) varargin; +%! imformats ("update", "jpg", fmt); +%! assert (imread (fname), {fname}); +%! assert (imread (fname, "jpg"), {fname}); +%! assert (imread (fname(1:end-4), "jpg"), {fname}); +%! extra_inputs = {"some", 89, i, {6 7 8}}; +%! assert (imread (fname, extra_inputs{:}), {fname, extra_inputs{:}}); +%! assert (imread (fname, "jpg", extra_inputs{:}), {fname, extra_inputs{:}}); +%! assert (imread (fname(1:end-4), "jpg", extra_inputs{:}), {fname, extra_inputs{:}}); +%! unwind_protect_cleanup +%! fclose (fid); +%! unlink (fname); +%! imformats (def_fmt); +%! end_unwind_protect + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/imshow.m --- a/scripts/image/imshow.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/imshow.m Sun May 25 10:29:05 2014 -0700 @@ -45,6 +45,9 @@ ## @table @asis ## @item @qcode{"displayrange"} ## @var{value1} is the display range as described above. +## +## @item @qcode{"colormap"} +## @var{value1} is the colormap to use when displaying an indexed image. ## ## @item @qcode{"xdata"} ## If @var{value1} is a two element vector, it must contain horizontal axis @@ -75,7 +78,7 @@ endif display_range = NA; - true_color = false; + truecolor = false; indexed = false; xdata = ydata = []; @@ -98,9 +101,9 @@ endif elseif (size (im, 3) == 3) if (ismember (class (im), {"uint8", "uint16", "double", "single"})) - true_color = true; + truecolor = true; else - error ("imshow: color image must be uint8, uint16, double, or single"); + error ("imshow: TrueColor image must be uint8, uint16, double, or single"); endif else error ("imshow: expecting MxN or MxNx3 matrix for image"); @@ -114,34 +117,47 @@ display_range = arg; elseif (columns (arg) == 3) indexed = true; - colormap (arg); + if (iscolormap (arg)) + colormap (arg); + else + error ("imshow: invalid colormap MAP"); + endif elseif (! isempty (arg)) - error ("imshow: argument number %d is invalid", narg+1); + error ("imshow: argument number %d is invalid", narg); endif elseif (ischar (arg)) switch (tolower (arg)) - case "displayrange"; + case "colormap" + map = varargin{narg++}; + if (iscolormap (map)) + colormap (map); + else + error ("imshow: invalid colormap"); + endif + case "displayrange" display_range = varargin{narg++}; - case "xdata"; + case "parent" + warning ("imshow: parent argument is not implemented"); + case {"truesize", "initialmagnification"} + warning ("image: zoom argument ignored -- use GUI features"); + case "xdata" xdata = varargin{narg++}; if (! isvector (xdata)) error ("imshow: xdata must be a vector") endif xdata = [xdata(1) xdata(end)]; - case "ydata"; + case "ydata" ydata = varargin{narg++}; if (! isvector (ydata)) - error ("imshow: expect a vector for ydata") + error ("imshow: ydata must be a vector") endif ydata = [ydata(1) ydata(end)]; - case {"truesize", "initialmagnification"} - warning ("image: zoom argument ignored -- use GUI features"); otherwise warning ("imshow: unrecognized property %s", arg); narg++; endswitch else - error ("imshow: argument number %d is invalid", narg+1); + error ("imshow: argument number %d is invalid", narg); endif endwhile @@ -159,46 +175,44 @@ switch (t) case {"double", "single", "logical"} display_range = [0, 1]; - case {"int8", "int16", "int32", "uint8", "uint16", "uint32"} + case {"uint8", "uint16", "int16"} display_range = [intmin(t), intmax(t)]; otherwise error ("imshow: invalid data type for image"); endswitch endif - nans = isnan (im(:)); - if (any (nans)) - warning ("Octave:imshow-NaN", - "imshow: pixels with NaN or NA values are set to minimum pixel value"); - im(nans) = display_range(1); - endif - - ## This is for compatibility. - if (! (indexed || (true_color && isinteger (im))) || islogical (im)) - im = double (im); + if (isfloat (im)) + nans = isnan (im(:)); + if (any (nans)) + warning ("Octave:imshow-NaN", + "imshow: pixels with NaN or NA values are set to minimum pixel value"); + im(nans) = display_range(1); + endif endif + ## FIXME: Commented out 2014/05/01. imagesc and 'clim' will automatically + ## take care of displaying out-of-range data clamped to the limits. + ## Eventually, this can be deleted if no problems arise. ## Clamp the image to the range boundaries - if (! (true_color || indexed || islogical (im))) - low = display_range(1); - high = display_range(2); - im(im < low) = low; - im(im > high) = high; - endif + ##if (! (truecolor || indexed || islogical (im))) + ## low = display_range(1); + ## high = display_range(2); + ## im(im < low) = low; + ## im(im > high) = high; + ##endif - if (true_color || indexed) - tmp = image (xdata, ydata, im); + if (truecolor || indexed) + htmp = image (xdata, ydata, im); else - tmp = image (xdata, ydata, im); - set (tmp, "cdatamapping", "scaled"); - ## The backend is responsible for scaling to clim if necessary. + htmp = imagesc (xdata, ydata, im, display_range); set (gca (), "clim", display_range); endif - set (gca (), "visible", "off", "ydir", "reverse"); + set (gca (), "visible", "off", "view", [0, 90], "ydir", "reverse", "layer", "top"); axis ("image"); if (nargout > 0) - h = tmp; + h = htmp; endif endfunction @@ -244,5 +258,22 @@ %% Test input validation %!error imshow () %!error imshow ({"cell"}) +%!error imshow (ones (3,3,3, "uint32")) +%!error imshow (ones (3,3,3, "int16")) %!error imshow (ones (4,4,4)) +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! fail ("imshow ([1,1], [2 0 0])", "invalid colormap MAP"); +%! fail ("imshow ([1,1], [1 0 0 0])", "argument number 2 is invalid"); +%! fail ('imshow ([1,1], "colormap", [2 0 0])', "invalid colormap"); +%! fail ('imshow ([1,1], "xdata", ones (2,2))', "xdata must be a vector"); +%! fail ('imshow ([1,1], "ydata", ones (2,2))', "ydata must be a vector"); +%! fail ('imshow ([1,1], "foobar")', "warning", "unrecognized property foobar") +%! fail ("imshow ([1,1], {1})", "argument number 2 is invalid"); +%! fail ("imshow ([1+i,1-i])", "warning", "only showing real part of complex image"); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/imwrite.m --- a/scripts/image/imwrite.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/imwrite.m Sun May 25 10:29:05 2014 -0700 @@ -100,7 +100,7 @@ fmt = imformats (ext); ## When there is no match, fmt will be a 1x1 structure with ## no fields, so we can't just use `isempty (fmt)'. - if (isempty (fieldnames (fmt))) + if (numfields (fmt) == 0) if (isempty (ext)) error ("imwrite: no extension found for %s to identify the image format", filename); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/ind2gray.m --- a/scripts/image/ind2gray.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/ind2gray.m Sun May 25 10:29:05 2014 -0700 @@ -69,18 +69,19 @@ %!shared i2g %! i2g = ind2gray (1:100, gray (100)); -%!assert (i2g, 0:1/99:1, eps); -%!assert (gray2ind (i2g, 100), uint8 (0:99)); +%! +%!assert (i2g, 0:1/99:1, eps) +%!assert (gray2ind (i2g, 100), uint8 (0:99)) %% Test input validation %!error ind2gray () %!error ind2gray (1) %!error ind2gray (1,2,3) -%!error ind2gray ({1}, jet (64)) +%!error ind2gray (ones (3,3,3), jet (64)) %!error ind2gray (1+i, jet (64)) %!error ind2gray (sparse (1), jet (64)) -%!error ind2gray (0, jet (64)) %!error ind2gray (1.1, jet (64)) +%!error ind2gray ({1}, jet (64)) %!error ind2gray (1, {1}) %!error ind2gray (1, 1+i) %!error ind2gray (1, ones (2,2,2)) @@ -88,3 +89,7 @@ %!error ind2gray (1, [-1]) %!error ind2gray (1, [2]) +%!warning ind2gray ([0 1 2], gray (5)); +%!warning ind2gray ([1 2 6], gray (5)); +%!warning ind2gray (uint8 ([1 2 5]), gray (5)); + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/ind2rgb.m --- a/scripts/image/ind2rgb.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/ind2rgb.m Sun May 25 10:29:05 2014 -0700 @@ -82,23 +82,28 @@ %! ## test basic usage with 1 and 3 outputs %! [rgb] = ind2rgb (img, map); %! [r, g, b] = ind2rgb (img, map); -%!assert (ergb, rgb); -%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3])); +%! +%!assert (ergb, rgb) +%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3])) +%!test %! ## test correction for integers -%! img = uint8 (img -1); +%! img = uint8 (img - 1); %! [rgb] = ind2rgb (img, map); -%!assert (ergb, rgb); -%! ## check it fails when image is a float with an index value of 0 -%!fail ("[rgb] = ind2rgb (double(img), map)") +%! assert (ergb, rgb); +%!test +%! ## Check that values below lower bound are mapped to first color value +%! rgb = ind2rgb ([-1 0 2], gray (64)); +%! assert (rgb(:,1:2,:), zeros (1,2,3)); +%! assert (rgb(:,3,:), 1/63 * ones (1,1,3)); %% Test input validation %!error ind2rgb () %!error ind2rgb (1,2,3) -%!error ind2rgb ({1}, jet (64)) +%!error ind2rgb (ones (3,3,3), jet (64)) %!error ind2rgb (1+i, jet (64)) %!error ind2rgb (sparse (1), jet (64)) -%!error ind2rgb (0, jet (64)) %!error ind2rgb (1.1, jet (64)) +%!error ind2rgb ({1}, jet (64)) %!error ind2rgb (1, {1}) %!error ind2rgb (1, 1+i) %!error ind2rgb (1, ones (2,2,2)) @@ -106,3 +111,8 @@ %!error ind2rgb (1, [-1]) %!error ind2rgb (1, [2]) +%!warning ind2rgb ([-1 1], jet (64)); +%!warning ind2rgb ([0 1 2], gray (5)); +%!warning ind2rgb ([1 2 6], gray (5)); +%!warning ind2rgb (uint8 ([1 2 5]), gray (5)); + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/private/__imfinfo__.m --- a/scripts/image/private/__imfinfo__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/private/__imfinfo__.m Sun May 25 10:29:05 2014 -0700 @@ -17,56 +17,22 @@ ## along with Octave; see the file COPYING. If not, see ## . -## This function does al the work of imfinfo. It exists here as private +## This function does all the work of imfinfo. It exists here as private ## function so that imfinfo can use other functions if imformats is ## configured to. It is also needed so that imformats can create a ## function handle for it. ## Author: Soren Hauberg -function info = __imfinfo__ (filename, ext) +function info = __imfinfo__ (filename) - if (nargin < 1 || nargin > 2) + if (nargin != 1) print_usage ("imfinfo"); + elseif (! ischar (filename)) + error ("imfinfo: FILENAME must be a string"); endif - if (! ischar (filename)) - error ("imfinfo: FILENAME must be a string"); - elseif (nargin >= 2 && ! ischar (ext)) - error ("imfinfo: EXT must be a string"); - endif - filename = tilde_expand (filename); - - delete_file = false; - unwind_protect - - fn = file_in_path (IMAGE_PATH, filename); - if (isempty (fn)) - ## We couldn't find the file so... - if (nargin >= 2) - ## try adding a possible file extesion - filename = [filename "." ext]; - fn = file_in_path (IMAGE_PATH, filename); - if (isempty (fn)) - error ("imfinfo: cannot find file %s", filename); - endif - else - ## try filename as an URL - [fn, status, msg] = urlwrite (filename, tmpnam ()); - if (! status) - error ("imfinfo: cannot find or download %s: %s", filename, msg); - endif - delete_file = true; - endif - endif - - info = __magick_finfo__ (fn); - - unwind_protect_cleanup - if (delete_file) - unlink (fn); - endif - end_unwind_protect + info = __magick_finfo__ (filename); endfunction diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/private/__imread__.m --- a/scripts/image/private/__imread__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/private/__imread__.m Sun May 25 10:29:05 2014 -0700 @@ -44,18 +44,6 @@ ## keep track of the varargin offset we're looking at each moment offset = 1; - filename = tilde_expand (filename); - fn = file_in_path (IMAGE_PATH, filename); - if (isempty (fn) && nargin >= offset + 1 && ischar (varargin{offset})) - ## if we can't find the file, check if the next input is the file extension - filename = [filename "." varargin{offset}]; - fn = file_in_path (IMAGE_PATH, filename); - offset++; - endif - if (isempty (fn)) - error ("imread: cannot find %s", filename); - endif - ## It is possible for an file with multiple pages to have very different ## images on each page. Specifically, they may have different sizes. Because ## of this, we need to first find out the index of the images to read so @@ -90,114 +78,62 @@ endif endif - try - ## Use information from the first image to be read to set defaults. - if (ischar (options.index) && strcmpi (options.index, "all")) - info = __magick_ping__ (fn, 1); - else - info = __magick_ping__ (fn, options.index(1)); - endif + ## Use information from the first image to be read to set defaults. + if (ischar (options.index) && strcmpi (options.index, "all")) + info = __magick_ping__ (filename, 1); + else + info = __magick_ping__ (filename, options.index(1)); + endif - ## Set default for options. - options.region = {1:1:info.rows 1:1:info.columns}; + ## Set default for options. + options.region = {1:1:info.rows 1:1:info.columns}; + + for idx = offset:2:(numel (varargin) - offset + 1) + switch (tolower (varargin{idx})) - for idx = offset:2:(numel (varargin) - offset + 1) - switch (tolower (varargin{idx})) + case {"frames", "index"} + ## Do nothing. This options were already processed before the loop. - case {"frames", "index"} - ## Do nothing. This options were already processed before the loop. - - case "pixelregion", - options.region = varargin{idx+1}; - if (! iscell (options.region) || numel (options.region) != 2) - error ("imread: value for %s must be a 2 element cell array", + case "pixelregion", + options.region = varargin{idx+1}; + if (! iscell (options.region) || numel (options.region) != 2) + error ("imread: value for %s must be a 2 element cell array", + varargin{idx}); + endif + for reg_idx = 1:2 + if (numel (options.region{reg_idx}) == 3) + ## do nothing + elseif (numel (options.region{reg_idx}) == 2) + options.region{reg_idx}(3) = options.region{reg_idx}(2); + options.region{reg_idx}(2) = 1; + else + error ("imread: range for %s must be a 2 or 3 element vector", varargin{idx}); endif - for reg_idx = 1:2 - if (numel (options.region{reg_idx}) == 3) - ## do nothing - elseif (numel (options.region{reg_idx}) == 2) - options.region{reg_idx}(3) = options.region{reg_idx}(2); - options.region{reg_idx}(2) = 1; - else - error ("imread: range for %s must be a 2 or 3 element vector", - varargin{idx}); - endif - options.region{reg_idx} = floor (options.region{reg_idx}(1)): ... - floor (options.region{reg_idx}(2)): ... - floor (options.region{reg_idx}(3)); - endfor - if (options.region{1}(end) > info.rows) - error ("imread: end ROWS for PixelRegions option is larger than image height"); - elseif (options.region{2}(end) > info.columns) - error ("imread: end COLS for PixelRegions option is larger than image width"); - endif - - case "info", - ## We ignore this option. This parameter exists in Matlab to - ## speed up the reading of multipage TIFF by passing a structure - ## that contains information about the start on the file of each - ## page. We can't control it through GraphicsMagic but at least - ## we allow to load multiple pages with one command. - - otherwise - error ("imread: invalid PARAMETER `%s'", varargin{idx}); - - endswitch - endfor - - [varargout{1:nargout}] = __magick_read__ (fn, options); + options.region{reg_idx} = floor (options.region{reg_idx}(1)): ... + floor (options.region{reg_idx}(2)): ... + floor (options.region{reg_idx}(3)); + endfor + if (options.region{1}(end) > info.rows) + error ("imread: end ROWS for PixelRegions option is larger than image height"); + elseif (options.region{2}(end) > info.columns) + error ("imread: end COLS for PixelRegions option is larger than image width"); + endif - catch - ## If we can't read it with Magick, maybe the image is in Octave's - ## native image format. This is from back before Octave had 'imread' - ## and 'imwrite'. Then we had the functions 'loadimage' and 'saveimage'. - ## - ## This "image format" seems to be any file that can be read with - ## load() and contains 2 variables. The variable named "map" is a - ## colormap and must exist whether the image is indexed or not. The - ## other variable must be named "img" or "X" for a "normal" or - ## indexed image. - ## - ## FIXME: this has been deprecated for the next major release (3.8 or 4.0). - ## If someone wants to revive this as yet another image format, a - ## separate Octave package can be written for it, that register the - ## format through imformats. - - magick_error = lasterr (); - - img_field = false; - x_field = false; - map_field = false; + case "info", + ## We ignore this option. This parameter exists in Matlab to + ## speed up the reading of multipage TIFF by passing a structure + ## that contains information about the start on the file of each + ## page. We can't control it through GraphicsMagic but at least + ## we allow to load multiple pages with one command. - try - vars = load (fn); - if (isstruct (vars)) - img_field = isfield (vars, "img"); - x_field = isfield (vars, "X"); - map_field = isfield (vars, "map"); - endif - catch - error ("imread: invalid image file: %s", magick_error); - end_try_catch + otherwise + error ("imread: invalid PARAMETER `%s'", varargin{idx}); - if (map_field && (img_field || x_field)) - varargout{2} = vars.map; - if (img_field) - varargout{1} = vars.img; - else - varargout{1} = vars.X; - endif - persistent warned = false; - if (! warned) - warning ("Octave's native image format has been deprecated."); - warned = true; - endif - else - error ("imread: invalid Octave image file format"); - endif + endswitch + endfor - end_try_catch + [varargout{1:nargout}] = __magick_read__ (filename, options); endfunction @@ -205,10 +141,6 @@ ## can be defined in two places, but only in one place can it also be the ## string "all" function bool = is_valid_index_option (arg) - ## is the index option - bool = false; - if (isvector (arg) && isnumeric (arg) && isreal (arg)) - bool = true; - endif + bool = isvector (arg) && isnumeric (arg) && isreal (arg); endfunction diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/private/imageIO.m --- a/scripts/image/private/imageIO.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/private/imageIO.m Sun May 25 10:29:05 2014 -0700 @@ -16,54 +16,111 @@ ## along with Octave; see the file COPYING. If not, see ## . -## This function simply connects imread and imfinfo() to the function -## to be used based on their format. It does it by checking the file extension -## of the file and redirecting to the appropriate function after checking -## with imformats. +## This function the image input functions imread() and imfinfo() to the +## functions that will actually be used, based on their format. See below +## on the details on how it identifies the format, and to what it defaults. +## +## It will change the input arguments that were passed to imread() and +## imfinfo(). It will change the filename to provide the absolute filepath +## for the file, it will extract the possible format name from the rest of +## the input arguments (in case there was one), and will give an error if +## the file can't be found. ## -## First argument is a function handle for the default imageIO function (what -## to use if the file extension for the image file is not listed by imformats). -## Second argument is the fieldname in the struct returned by imformats with a -## function handle for the function to use. Third argument is a cell array, its -## first element the filename, and the second, an optional file extension to -## add to filename, if filename alone does not exist. All the others are the -## original input arguments passed to the original imageIO function which will -## be passed on to the destination function. +## Usage: ## -## No input checking whatsoever is performed. That should be performed by the -## function calling it. - -function varargout = imageIO (core_func, fieldname, filename, varargin) +## func - Function name to use on error message. +## core_func - Function handle for the default function to use if we can't +## find the format in imformats. +## fieldname - Name of the field in the struct returned by imformats that +## has the function to use. +## filename - Most likely the first input argument from the function that +## called this. May be missing the file extension which can be +## on varargin. +## varargin - Followed by all the OTHER arguments passed to imread and +## imfinfo. - ## It should not be this function job to check if the file exists or not. - ## However, we need to know the file extension to use with imformats and - ## that means we need to know the actual filename that will be used which - ## is dependent on whether a file exists. - ## - ## If a file named filename{1} exists, then that's it, we will use that - ## wether it has an extension or not. If it does not exist and we have - ## something in filename{2}, then we will consider it the file extension. - ## Note the detail that if we find a file using filename{1} only, then we - ## should completely ignore filename{2}. It won't even be used by - ## imformats() at all, even if filename{1} has no extension to use with - ## imformats(). - if (isscalar (filename) || ! isempty (file_in_path (IMAGE_PATH, filename{1}))) - [~, ~, ext] = fileparts (filename{1}); - if (! isempty (ext)) - ## remove dot from extension - ext = ext(2:end); - endif - else - ext = filename{2}; +function varargout = imageIO (func, core_func, fieldname, filename, varargin) + + ## First thing: figure out the filename and possibly download it. + ## The first attempt is to try the filename and see if it exists. If it + ## does not, we try to add the next argument since the file extension can + ## be given as a separate argument. If we still can't find the file, it + ## can be a URL. Lastly, if we still didn't found a file, try adding the + ## extension to the URL + + file_2_delete = false; # will we have to remove the file in the end? + persistent abs_path = @(x) file_in_path (IMAGE_PATH, tilde_expand (x)); + + ## Filename was given with file extension + fn = abs_path (filename); + if (isempty (fn) && ! isempty (varargin)) + ## Maybe if we add a file extension + fn = abs_path ([filename "." varargin{1}]); endif - fmt = imformats (ext); - ## When there is no match, fmt will be a 1x1 structure with no fields, - ## so we can't just use `isempty (fmt)'. - if (isempty (fieldnames (fmt))) - [varargout{1:nargout}] = core_func (varargin{:}); - else - [varargout{1:nargout}] = fmt.(fieldname) (varargin{:}); + ## Maybe we have an URL + if (isempty (fn)) + file_2_delete = true; # mark file for deletion + [fn, ~] = urlwrite (filename, tmpnam ()); + ## Maybe the URL is missing the file extension + if (isempty (fn) && ! isempty (varargin)) + [fn, ~] = urlwrite ([filename "." varargin{1}], tmpnam ()); + endif + + if (isempty (fn)) + error ("%s: unable to find file %s", func, filename); + endif endif + + ## unwind_protect block because we may have a file to remove in the end + unwind_protect + + ## When guessing the format to use, we first check if the second + ## argument is a format defined in imformats. If so, we remove it + ## from the rest of arguments before passing them on. If not, we + ## try to guess the format from the file extension. Finally, if + ## we still don't know the format, we use the Octave core functions + ## which is the same for all formats. + foo = []; # the function we will use + + ## We check if the call to imformats (ext) worked using + ## "numfields (fmt) > 0 because when it fails, the returned + ## struct is not considered empty. + + ## try the second input argument + if (! isempty (varargin) && ischar (varargin{1})) + fmt = imformats (varargin{1}); + if (numfields (fmt) > 0) + foo = fmt.(fieldname); + varargin(1) = []; # remove format name from arguments + endif + endif + + ## try extension from file name + if (isempty (foo)) + [~, ~, ext] = fileparts (fn); + if (! isempty (ext)) + ## remove dot from extension + ext = ext(2:end); + endif + fmt = imformats (ext); + if (numfields (fmt) > 0) + foo = fmt.(fieldname); + endif + endif + + ## use the core function + if (isempty (foo)) + foo = core_func; + endif + + [varargout{1:nargout}] = foo (fn, varargin{:}); + + unwind_protect_cleanup + if (file_2_delete) + unlink (fn); + endif + end_unwind_protect + endfunction diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/image/private/ind2x.m --- a/scripts/image/private/ind2x.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/image/private/ind2x.m Sun May 25 10:29:05 2014 -0700 @@ -22,12 +22,13 @@ function [x, map] = ind2x (caller, x, map) ## Check if X is an indexed image. - ## an indexed image is defined has having only 2D, and that's how Matlab + ## An indexed image is defined has having only 2D, and that's how Matlab ## behaves. But we want to support ND images, so we will allow up to 4D - ## and check that the 3rd is a singleton - if (all (ndims (x) != [2 4]) || size (x, 3) != 1 || issparse (x) || - (isfloat (x) && ! isindex (x)) || - ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"}))) + ## and check that the 3rd dimension is a singleton. + if (all (ndims (x) != [2 4]) || size (x, 3) != 1 + || iscomplex (x) || issparse (x) + || (isfloat (x) && x != fix (x)) + || ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"}))) error ("%s: X must be an indexed image", caller); endif @@ -36,10 +37,20 @@ error ("%s: MAP must be a valid colormap", caller); endif - ## Do we have enough colors in the color map? - ## there's an offset of 1 when the indexed image is an integer class so we fix - ## it now and convert it to float only if really necessary and even then only - ## to single precision since that is enough for both uint8 and uint16. + ## Any color indices below the lower bound of the color map are modified + ## to point to the first color in the map (see bug #41851). + if (isfloat (x)) + invalid_idx = x < 1; + if (any (invalid_idx(:))) + warning (["Octave:" caller ":invalid-idx-img"], + [caller ": indexed image contains colors outside of colormap"]); + x(invalid_idx) = 1; + endif + endif + + ## Switch to using 1-based indexing. + ## It is possible that an integer storage class may not have enough room + ## to make the switch, in which case we convert the data to single. maxidx = max (x(:)); if (isinteger (x)) if (maxidx == intmax (class (x))) @@ -49,9 +60,12 @@ maxidx += 1; endif + ## When there are more colors in the image, than there are in the map, + ## pad the colormap with the last color in the map for Matlab compatibility. num_colors = rows (map); if (num_colors < maxidx) - ## Pad with the last color in the map for Matlab compatibility + warning (["Octave:" caller ":invalid-idx-img"], + [caller ": indexed image contains colors outside of colormap"]); pad = repmat (map(end,:), maxidx - num_colors, 1); map(end+1:maxidx, :) = pad; endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/io/importdata.m --- a/scripts/io/importdata.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/io/importdata.m Sun May 25 10:29:05 2014 -0700 @@ -146,8 +146,7 @@ ## i.e., output = output.onlyFieldLeft ## Update the list of fields - fields = fieldnames (output); - if (numel (fields) == 1) + if (numfields (output) == 1) output = output.(fields{1}); endif endif @@ -210,11 +209,33 @@ endwhile - fclose (fid); + if (row == -1) + ## No numeric data found => return file as cellstr array + ## 1. Read as char string + fseek (fid, 0, "bof"); + output = fread (fid, Inf, "*char")'; + fclose (fid); + ## 2. Find EOL type + idx = find (output(1:min (4096, length (output))) == "\n", 1) - 1; + if (isindex (idx) && output(idx) == "\r") + dlm = "\r\n"; + else + dlm = "\n"; + endif + ## 3. Split each line into a cell (column vector) + output = strsplit (output, dlm)'; + ## 4. Remove last cell (for files with -proper- EOL before EOF) + if (isempty (output{end})) + output(end) = []; + endif + ## 5. Return after setting some output data + delimiter = ""; + header_rows = numel (output); + return; + else + fclose (fid); + endif - if (row == -1) - error ("importdata: Unable to determine delimiter"); - endif if (num_header_rows >= 0) header_rows = num_header_rows; endif @@ -498,6 +519,30 @@ %! assert (d, "\t"); %! assert (h, 0); +%!test +%! ## Only text / no numeric data; \n as EOL +%! fn = tmpnam (); +%! fid = fopen (fn, "w"); +%! fputs (fid, "aaaa 11\nbbbbb 22\nccccc 3\n"); +%! fclose (fid); +%! [a, d, h] = importdata (fn); +%! unlink (fn); +%! assert (a, {"aaaa 11"; "bbbbb 22"; "ccccc 3"}); +%! assert (d, ""); +%! assert (h, 3); + +%!test +%! ## Only text / no numeric data; \r\n as EOL; missing last EOL before EOF +%! fn = tmpnam (); +%! fid = fopen (fn, "w"); +%! fputs (fid, "aaaa 11\r\nbbbbb 22\r\nccccc 3"); +%! fclose (fid); +%! [a, d, h] = importdata (fn); +%! unlink (fn); +%! assert (a, {"aaaa 11"; "bbbbb 22"; "ccccc 3"}); +%! assert (d, ""); +%! assert (h, 3); + %!error importdata () %!error importdata (1,2,3,4) %!error importdata (1) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/java/javachk.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/java/javachk.m Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,151 @@ +## Copyright (C) 2014 Philip Nienhuis +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} javachk (@var{feature}) +## @deftypefnx {Function File} {} javachk (@var{feature}, @var{component}) +## @deftypefnx {Function File} {@var{msg} =} javachk (@dots{}) +## Check for the presence of the Java @var{feature} in the current session +## and print or return an error message if it is not. +## +## Possible features are: +## +## @table @asis +## @item @qcode{"awt"} +## Abstract Window Toolkit for GUIs. +## +## @item @qcode{"desktop"} +## Interactive desktop is running. +## +## @item @qcode{"jvm"} +## Java Virtual Machine. +## +## @item @qcode{"swing"} +## Swing components for lightweight GUIs. +## @end table +## +## If @var{feature} is supported and: +## +## @itemize @bullet +## @item +## No output argument is requested: +## +## Return an empty string +## +## @item +## An output argument is requested: +## +## Return a struct with fields @qcode{"feature"} and @qcode{"identifier"} +## both empty +## +## @end itemize +## +## If @var{feature} is not supported and: +## +## @itemize @bullet +## @item +## No output argument is requested: +## +## Emit an error message. +## +## @item +## An output argument is requested: +## +## Return a struct with field @qcode{"feature"} set to @var{feature} and +## field @qcode{"identifier"} set to @var{component} +## +## @end itemize +## +## The optional input @var{component} will be used in place of @var{feature} +## in any error messages for greater specificity. +## +## @code{javachk} determines if specific Java features are available in an +## Octave session. This function is provided for scripts which may alter +## their behavior based on the availability of Java. The feature +## @qcode{"desktop"} is never available as Octave has no Java-based desktop. +## Other features may be available if Octave was compiled with the Java +## Interface and Java is installed. +## +## @seealso{error, usejava} +## @end deftypefn + +## Author: Philip Nienhuis +## Created: 2014-04-19 + +function msg = javachk (feature, component="") + + msg = ""; + chk = false; + switch (feature) + ## For each feature, try methods() on a Java class of a feature + case "awt" + try + dum = methods ("java.awt.Frame"); + chk = true; + end_try_catch + case "desktop" + ## Octave has no Java based GUI/desktop, leave chk = false + case "jvm" + try + dum = methods ("java.lang.Runtime"); + chk = true; + end_try_catch + case "swing" + try + dum = methods ("javax.swing.Popup"); + chk = true; + end_try_catch + otherwise + error ("javachk: unrecognized feature '%s', can be one of 'awt'|'desktop'|'jvm'|'swing'\n", feature); + endswitch + + if (! chk) + ## Desired feature not present + if (nargout >= 1) + msg.message = sprintf ("javachk: %s is not supported", feature); + msg.identifier = component; + else + if (! isempty (component)) + err = sprintf ("javachk: %s is not supported\n", component); + else + err = sprintf ("javachk: %s is not supported\n", feature); + endif + error (err); + endif + endif + +endfunction + + +%!error javachk ("desktop") +%!error javachk ("desktop", "Java DESKTOP") +%!test +%! msg = javachk ("desktop"); +%! assert (msg.message, "javachk: desktop is not supported"); +%! assert (msg.identifier, ""); +%!test +%! msg = javachk ("desktop", "Java DESKTOP"); +%! assert (msg.message, "javachk: desktop is not supported"); +%! assert (msg.identifier, "Java DESKTOP"); + +%!testif HAVE_JAVA +%! assert (javachk ("jvm"), ""); + +%% Test input validation +%!error javachk ("foobar") + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/java/javamem.m --- a/scripts/java/javamem.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/java/javamem.m Sun May 25 10:29:05 2014 -0700 @@ -36,7 +36,7 @@ ## determined by the environment variable @w{@env{OCTAVE_JAVA_DIR}}. ## If unset, the directory where @file{javaaddpath.m} resides is used instead ## (typically -## @file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/} +## @file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}). ## ## @file{java.opts} is a plain text file with one option per line. The ## default initial memory size and default maximum memory size (which diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/java/module.mk --- a/scripts/java/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/scripts/java/module.mk Sun May 25 10:29:05 2014 -0700 @@ -3,6 +3,7 @@ java_FCN_FILES = \ java/javaArray.m \ java/javaaddpath.m \ + java/javachk.m \ java/javaclasspath.m \ java/javamem.m \ java/javarmpath.m \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/java/usejava.m --- a/scripts/java/usejava.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/java/usejava.m Sun May 25 10:29:05 2014 -0700 @@ -43,6 +43,7 @@ ## @qcode{"desktop"} always returns @code{false} as Octave has no Java-based ## desktop. Other features may be available if Octave was compiled with the ## Java Interface and Java is installed. +## @seealso{javachk} ## @end deftypefn ## Author: Rik Wehbring diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/linear-algebra/issymmetric.m --- a/scripts/linear-algebra/issymmetric.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/linear-algebra/issymmetric.m Sun May 25 10:29:05 2014 -0700 @@ -40,7 +40,8 @@ retval = isnumeric (x) && issquare (x); if (retval) if (tol == 0) - retval = all ((x == x.')(:)); + ## Handle large sparse matrices as well as full ones + retval = nnz (x != x.') == 0; else norm_x = norm (x, inf); retval = norm_x == 0 || norm (x - x.', inf) / norm_x <= tol; @@ -59,6 +60,7 @@ %!assert (issymmetric ([1, 2i; 2i, 1])) %!assert (! (issymmetric ("t"))) %!assert (! (issymmetric (["te"; "et"]))) +%!assert (issymmetric (speye (100000))) %!test %! s.a = 1; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/cast.m --- a/scripts/miscellaneous/cast.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/cast.m Sun May 25 10:29:05 2014 -0700 @@ -19,27 +19,41 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} cast (@var{val}, @var{type}) ## Convert @var{val} to data type @var{type}. -## @seealso{int8, uint8, int16, uint16, int32, uint32, int64, uint64, double} +## +## The value @var{val} may be modified to fit within the range of the new type. +## +## Examples: +## +## @example +## @group +## cast (-5, "uint8") +## @result{} 0 +## cast (300, "int8") +## @result{} 127 +## @end group +## @end example +## +## @seealso{typecast, int8, uint8, int16, uint16, int32, uint32, int64, uint64, double, single, logical, char} ## @end deftypefn ## Author: jwe function retval = cast (val, typ) - if (nargin == 2) - if (ischar (typ)) - if (any (strcmp (typ, {"int8"; "uint8"; "int16"; "uint16"; - "int32"; "uint32"; "int64"; "uint64"; - "double"; "single"; "logical"; "char"}))) - retval = feval (typ, val); - else - error ("cast: type name '%s' is not a built-in type", typ); - endif + if (nargin != 2) + print_usage (); + endif + + if (ischar (typ)) + if (any (strcmp (typ, {"int8"; "uint8"; "int16"; "uint16"; + "int32"; "uint32"; "int64"; "uint64"; + "double"; "single"; "logical"; "char"}))) + retval = feval (typ, val); else - error ("cast: expecting TYPE name as second argument"); + error ("cast: type name '%s' is not a built-in type", typ); endif else - print_usage (); + error ("cast: expecting TYPE name as second argument"); endif endfunction diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/colon.m diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/edit.m --- a/scripts/miscellaneous/edit.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/edit.m Sun May 25 10:29:05 2014 -0700 @@ -330,7 +330,7 @@ ## If editing a new file, prompt for creation if gui is running if (isguirunning ()) - if (! __octave_link_edit_file__ (file,"prompt")); + if (! __octave_link_edit_file__ (file, "prompt")); return; endif endif @@ -344,8 +344,12 @@ ext = file(idx+1:end); if (! any (strcmp (ext, {"cc", "m"}))) ## Some unknown file. Create and open it or just open it. + ## Add .m file extension per default + fileandpath = [fileandpath ".m"]; if (isguirunning ()) ## Write the initial file (if there is anything to write) + ## Give user the opportunity to change the file extension + fileandpath = uiputfile (fileandpath); fid = fopen (fileandpath, "wt"); if (fid < 0) error ("edit: could not create %s", fileandpath); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/fact.m --- a/scripts/miscellaneous/fact.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/fact.m Sun May 25 10:29:05 2014 -0700 @@ -115,7 +115,7 @@ "When Richard Stallman executes ps -e, you show up."; "When Richard Stallman gets angry he doesn't swear; he recurses."; "On Richard Stallman's computer the bootloader is contained in his .emacs."; - "Richard Satallman can make any operating system free, free from drivers."; + "Richard Stallman can make any operating system free, free from drivers."; "Richard Stallman programmed Chuck Norris."; "Behind Richard Stallman's beard there is another fist, to code faster."; "Richard Stallman won a Sudoku that started with only one number in each line."; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/genvarname.m --- a/scripts/miscellaneous/genvarname.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/genvarname.m Sun May 25 10:29:05 2014 -0700 @@ -80,7 +80,7 @@ ## Since variable names may only contain letters, digits and underscores, ## genvarname replaces any sequence of disallowed characters with ## an underscore. Also, variables may not begin with a digit; in this -## case an underscore is added before the variable name. +## case an x is added before the variable name. ## ## Variable names beginning and ending with two underscores @qcode{"__"} are ## valid but they are used internally by octave and should generally be @@ -131,22 +131,20 @@ str{i}(! ismember (str{i}, validchars)) = "_"; ## do not use keywords if (iskeyword (str{i})) - str{i} = ["_" str{i}]; - endif - ## double underscores at the beginning and end are reserved variables - underscores = (str{i} == "_"); - if (any (underscores)) - firstnon = find (!underscores, 1); - lastnon = find (!underscores, 1, "last"); - str{i}([1:firstnon-2, lastnon+2:end]) = []; + firstcharacter = toupper (str{i}(1)); + str{i} = ["x", firstcharacter, str{i}(2:end)]; endif ## The variable cannot be empty if (isempty (str{i})) str{i} = "x"; endif + ## Leading underscores are not Matlab compatible + if (str{i}(1) == "_") + str{i} = ["x", str{i}]; + endif ## it cannot start with a number if (ismember (str{i}(1), "0":"9")) - str{i} = ["_" str{i}]; + str{i} = ["x", str{i}]; endif ## make sure that the variable is unique relative to other variables @@ -199,12 +197,12 @@ ## more than one repetition not in order %!assert (genvarname ({"a" "b" "a" "b" "a"}), {"a" "b" "a1" "b1" "a2"}) ## Variable name munging -%!assert (genvarname ("__x__"), "_x_") -%!assert (genvarname ("123456789"), "_123456789") -%!assert (genvarname ("_$1__"), "_1_") -%!assert (genvarname ("__foo__", "_foo_"), "_foo_1") -%!assert (genvarname ("1million_and1", "_1million_and1"), "_1million_and1_1") +%!assert (genvarname ("__x__"), "x__x__") +%!assert (genvarname ("123456789"), "x123456789") +%!assert (genvarname ("_$1__"), "x__1__") +%!assert (genvarname ("__foo__", "x__foo__"), "x__foo__1") +%!assert (genvarname ("1million_and1", "x1million_and1"), "x1million_and1_1") %!assert (genvarname ({"", "", ""}), {"x", "x1", "x2"}) -%!assert (genvarname ("if"), "_if") -%!assert (genvarname ({"if", "if", "if"}), {"_if", "_if1", "_if2"}) +%!assert (genvarname ("if"), "xIf") +%!assert (genvarname ({"if", "if", "if"}), {"xIf", "xIf1", "xIf2"}) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/gzip.m --- a/scripts/miscellaneous/gzip.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/gzip.m Sun May 25 10:29:05 2014 -0700 @@ -58,10 +58,17 @@ %! error ("gzipped file cannot be found!"); %! endif %! gunzip (entry); -%! if (system (sprintf ("diff %s %s%c%s%s", filename, dirname, filesep, -%! basename, extension))) +%! fid = fopen (filename, "rb"); +%! assert (fid >= 0); +%! orig_data = fread (fid); +%! fclose (fid); +%! fid = fopen ([dirname filesep basename extension], "rb"); +%! assert (fid >= 0); +%! new_data = fread (fid); +%! fclose (fid); +%! if (orig_data != new_data) %! error ("unzipped file not equal to original file!"); -%! end +%! endif %! unwind_protect_cleanup %! delete (filename); %! delete ([dirname, filesep, basename, extension]); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/inputname.m --- a/scripts/miscellaneous/inputname.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/inputname.m Sun May 25 10:29:05 2014 -0700 @@ -57,3 +57,8 @@ %!assert (inputname (1), "hello") %!assert (inputname (2), "worldly") +%!function r = foo (x, y) +%! r = inputname (2); +%!endfunction +%!assert (foo (pi, e), "e"); +%!assert (feval (@foo, pi, e), "e"); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/ls.m --- a/scripts/miscellaneous/ls.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/ls.m Sun May 25 10:29:05 2014 -0700 @@ -61,14 +61,14 @@ if (nargin > 0) args = tilde_expand (varargin); if (ispc () && ! isunix ()) + idx = ! strncmp (args, '/', 1); + ## Enclose paths, potentially having spaces, in double quotes: + args(idx) = strcat ('"', args(idx), '"'); ## shell (cmd.exe) on MinGW uses '^' as escape character - args = regexprep (args, '([^\w.*? -])', '^$1'); - ## Strip UNIX directory character which looks like an option to dir cmd. - if (args{end}(end) == '/') - args{end}(end) = ""; - endif + args = regexprep (args, '([^\w.*?])', '^$1'); else - args = regexprep (args, '([^\w.*? -])', '\\$1'); + ## Escape any special characters in filename + args = regexprep (args, '([^\w.*?-[]])', '\\$1'); endif args = sprintf ("%s ", args{:}); else diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/mex.m --- a/scripts/miscellaneous/mex.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/mex.m Sun May 25 10:29:05 2014 -0700 @@ -23,8 +23,16 @@ ## @seealso{mkoctfile} ## @end deftypefn -function mex (varargin) - args = {"--mex", varargin{:}}; - mkoctfile (args{:}); +function retval = mex (varargin) + + [output, status] = mkoctfile ("--mex", varargin{:}); + + if (! isempty (output)) + disp (output); + endif + if (nargout > 0) + retval = status; + endif + endfunction diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/run.m --- a/scripts/miscellaneous/run.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/run.m Sun May 25 10:29:05 2014 -0700 @@ -31,9 +31,10 @@ ## falling back to the script name without an extension. ## ## Implementation Note: If @var{script} includes a path component, then -## @code{run} first changes the directory to the directory where @var{script} -## is found. @code{run} then executes the script, and returns to the original -## directory. +## @code{run} first changes the working directory to the directory where +## @var{script} is found. Next, the script is executed. Finally, @code{run} +## returns to the original working directory unless @code{script} has +## specifically changed directories. ## @seealso{path, addpath, source} ## @end deftypefn @@ -65,7 +66,9 @@ evalin ("caller", sprintf ('source ("%s%s");', f, ext), "rethrow (lasterror ())"); unwind_protect_cleanup - cd (wd); + if (strcmp (d, pwd ())) + cd (wd); + endif end_unwind_protect else error ("run: the path %s doesn't exist", d); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/miscellaneous/what.m --- a/scripts/miscellaneous/what.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/miscellaneous/what.m Sun May 25 10:29:05 2014 -0700 @@ -37,7 +37,7 @@ if (d(end) == '/' || d(end) == '\') d(end) = []; endif - dtmp = find_dir_in_path (d); + dtmp = dir_in_loadpath (d); if (isempty (dtmp)) error ("what: could not find the directory %s", d); endif @@ -45,7 +45,7 @@ d = dtmp; endif - files = dir (d); + files = readdir (d); w.path = d; w.m = cell (0, 1); w.mex = cell (0, 1); @@ -56,7 +56,7 @@ w.classes = cell (0, 1); for i = 1 : length (files) - n = files(i).name; + n = files{i}; ## Ignore . and .. if (strcmp (n, ".") || strcmp (n, "..")) continue; @@ -71,7 +71,7 @@ w.mex{end+1} = n; elseif (strcmp (e, ".mat")) w.mat{end+1} = n; - elseif (strcmp (n(1), "@")) + elseif (strcmp (n(1), "@") && isdir (n)) w.classes{end+1} = n; endif endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/optimization/fminbnd.m --- a/scripts/optimization/fminbnd.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/optimization/fminbnd.m Sun May 25 10:29:05 2014 -0700 @@ -170,7 +170,7 @@ ## update a, b, v, w, and x - if (fu <= fval) + if (fu < fval) if (u < x) b = x; else @@ -283,4 +283,5 @@ %!assert (fminbnd (@(x) (x - 1e-3)^4, -1, 1, opt0), 1e-3, 10e-3*sqrt (eps)) %!assert (fminbnd (@(x) abs (x-1e7), 0, 1e10, opt0), 1e7, 10e7*sqrt (eps)) %!assert (fminbnd (@(x) x^2 + sin (2*pi*x), 0.4, 1, opt0), fzero (@(x) 2*x + 2*pi*cos (2*pi*x), [0.4, 1], opt0), sqrt (eps)) +%!assert (fminbnd (@(x) x > 0.3, 0, 1) < 0.3) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/optimization/fzero.m --- a/scripts/optimization/fzero.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/optimization/fzero.m Sun May 25 10:29:05 2014 -0700 @@ -100,7 +100,7 @@ ## Get default options if requested. if (nargin == 1 && ischar (fun) && strcmp (fun, 'defaults')) - x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", 1e-8, + x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", eps, "OutputFcn", [], "FunValCheck", "off"); return; endif @@ -117,7 +117,7 @@ ## displev = optimget (options, "Display", "notify"); funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on"); outfcn = optimget (options, "OutputFcn"); - tolx = optimget (options, "TolX", 1e-8); + tolx = optimget (options, "TolX", eps); maxiter = optimget (options, "MaxIter", Inf); maxfev = optimget (options, "MaxFunEvals", Inf); @@ -302,7 +302,7 @@ endif ## If there's an output function, use it now. - if (outfcn) + if (! isempty (outfcn)) optv.funccount = nfev; optv.fval = fval; optv.iteration = niter; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/optimization/glpk.m --- a/scripts/optimization/glpk.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/optimization/glpk.m Sun May 25 10:29:05 2014 -0700 @@ -123,7 +123,7 @@ ## ## @item @qcode{"D"} ## An inequality constraint with both upper and lower bounds -## (@code{A(i,:)*x >= -b(i)} @emph{and} (@code{A(i,:)*x <= b(i)}). +## (@code{A(i,:)*x >= -b(i)}) @emph{and} (@code{A(i,:)*x <= b(i)}). ## @end table ## ## @item vartype diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/optimization/optimget.m --- a/scripts/optimization/optimget.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/optimization/optimget.m Sun May 25 10:29:05 2014 -0700 @@ -20,10 +20,12 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} optimget (@var{options}, @var{parname}) ## @deftypefnx {Function File} {} optimget (@var{options}, @var{parname}, @var{default}) -## Return a specific option from a structure created by -## @code{optimset}. If @var{parname} is not a field of the @var{options} -## structure, return @var{default} if supplied, otherwise return an -## empty matrix. +## Return the specific option @var{parname} from the optimization options +## structure @var{options} created by @code{optimset}. +## +## If @var{parname} is not defined then return @var{default} if supplied, +## otherwise return an empty matrix. +## @seealso{optimset} ## @end deftypefn function retval = optimget (options, parname, default) @@ -32,21 +34,22 @@ print_usage (); endif + ## Expand partial-length names into full names opts = __all_opts__ (); idx = strncmpi (opts, parname, length (parname)); - nmatch = sum (idx); if (nmatch == 1) parname = opts{idx}; elseif (nmatch == 0) - warning ("unrecognized option: %s", parname); + warning ("optimget: unrecognized option: %s", parname); else - fmt = sprintf ("ambiguous option: %%s (%s%%s)", + fmt = sprintf ("optimget: ambiguous option: %%s (%s%%s)", repmat ("%s, ", 1, nmatch-1)); warning (fmt, parname, opts{idx}); endif - if (isfield (options, parname)) + + if (isfield (options, parname) && ! isempty (options.(parname))) retval = options.(parname); elseif (nargin > 2) retval = default; @@ -57,13 +60,20 @@ endfunction -%!error optimget () - %!shared opts %! opts = optimset ("tolx", 0.1, "maxit", 100); -%!assert (optimget (opts, "TolX"), 0.1); -%!assert (optimget (opts, "maxit"), 100); -%!assert (optimget (opts, "MaxITer"), 100); -%!warning (optimget (opts, "Max")); -%!warning (optimget (opts, "foobar")); +%!assert (optimget (opts, "TolX"), 0.1) +%!assert (optimget (opts, "maxit"), 100) +%!assert (optimget (opts, "MaxITer"), 100) +%!assert (optimget (opts, "TolFun"), []) +%!assert (optimget (opts, "TolFun", 1e-3), 1e-3) +%% Test input validation +%!error optimget () +%!error optimget (1) +%!error optimget (1,2,3,4,5) +%!error optimget (1, "name") +%!error optimget (struct (), 2) +%!warning (optimget (opts, "foobar")); +%!warning (optimget (opts, "Max")); + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/optimization/optimset.m --- a/scripts/optimization/optimset.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/optimization/optimset.m Sun May 25 10:29:05 2014 -0700 @@ -19,10 +19,24 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} optimset () -## @deftypefnx {Function File} {} optimset (@var{par}, @var{val}, @dots{}) -## @deftypefnx {Function File} {} optimset (@var{old}, @var{par}, @var{val}, @dots{}) -## @deftypefnx {Function File} {} optimset (@var{old}, @var{new}) -## Create options struct for optimization functions. +## @deftypefnx {Function File} {@var{options} =} optimset () +## @deftypefnx {Function File} {@var{options} =} optimset (@var{par}, @var{val}, @dots{}) +## @deftypefnx {Function File} {@var{options} =} optimset (@var{old}, @var{par}, @var{val}, @dots{}) +## @deftypefnx {Function File} {@var{options} =} optimset (@var{old}, @var{new}) +## Create options structure for optimization functions. +## +## When called without any input or output arguments, @code{optimset} prints +## a list of all valid optimization parameters. +## +## When called with one output and no inputs, return an options structure with +## all valid option parameters initialized to @code{[]}. +## +## When called with a list of parameter/value pairs, return an options +## structure with only the named parameters initialized. +## +## When the first input is an existing options structure @var{old}, the values +## are updated from either the @var{par}/@var{val} list or from the options +## structure @var{new}. ## ## Valid parameters are: ## @@ -96,13 +110,13 @@ ## ## @item Updating ## @end table +## @seealso{optimget} ## @end deftypefn function retval = optimset (varargin) nargs = nargin (); - ## Add more as needed. opts = __all_opts__ (); if (nargs == 0) @@ -124,8 +138,8 @@ error ("optimset: no defaults for function '%s'", fcn); end_try_catch elseif (nargs == 2 && isstruct (varargin{1}) && isstruct (varargin{2})) - ## Set slots in old from nonempties in new. Should we be checking - ## to ensure that the field names are expected? + ## Set slots in old from non-empties in new. + ## Should we be checking to ensure that the field names are expected? old = varargin{1}; new = varargin{2}; fnames = fieldnames (old); @@ -140,9 +154,9 @@ if (nmatch == 1) key = opts{find (i)}; elseif (nmatch == 0) - warning ("unrecognized option: %s", key); + warning ("optimset: unrecognized option: %s", key); else - fmt = sprintf ("ambiguous option: %%s (%s%%s)", + fmt = sprintf ("optimset: ambiguous option: %%s (%s%%s)", repmat ("%s, ", 1, nmatch-1)); warning (fmt, key, opts{i}); endif @@ -155,8 +169,8 @@ pairs = reshape (varargin(2:end), 2, []); retval = optimset (varargin{1}, cell2struct (pairs(2, :), pairs(1, :), 2)); elseif (rem (nargs, 2) == 0) - ## Create struct. Default values are replaced by those specified by - ## name/value pairs. + ## Create struct. + ## Default values are replaced by those specified by name/value pairs. pairs = reshape (varargin, 2, []); retval = optimset (struct (), cell2struct (pairs(2, :), pairs(1, :), 2)); else @@ -166,10 +180,13 @@ endfunction -%!assert (optimget (optimset ("tolx", 1e-2), "tOLx"), 1e-2) +%!assert (isfield (optimset (), "TolFun")) %!assert (isfield (optimset ("tolFun", 1e-3), "TolFun")) -%!warning (optimset ("Max", 10)); -%!warning (optimset ("foobar", 13)); +%!assert (optimget (optimset ("tolx", 1e-2), "tOLx"), 1e-2) -%!error (optimset ("%NOT_A_REAL_FUNCTION_NAME%")) +%% Test input validation +%!error optimset ("1_Parameter") +%!error optimset ("%NOT_A_REAL_FUNCTION_NAME%") +%!warning optimset ("foobar", 13); +%!warning optimset ("Max", 10); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/optimization/sqp.m --- a/scripts/optimization/sqp.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/optimization/sqp.m Sun May 25 10:29:05 2014 -0700 @@ -1,4 +1,5 @@ ## Copyright (C) 2005-2013 John W. Eaton +## Copyright (C) 2013 Arun Giridhar ## ## This file is part of Octave. ## @@ -128,8 +129,17 @@ ## ## @table @asis ## @item 101 -## The algorithm terminated normally. -## Either all constraints meet the requested tolerance, or the stepsize, +## The algorithm terminated normally. +## All constraints meet the specified tolerance. +## +## @item 102 +## The BFGS update failed. +## +## @item 103 +## The maximum number of iterations was reached. +## +## @item 104 +## The stepsize has become too small, i.e., ## @tex ## $\Delta x,$ ## @end tex @@ -137,12 +147,6 @@ ## delta @var{x}, ## @end ifnottex ## is less than @code{@var{tol} * norm (x)}. -## -## @item 102 -## The BFGS update failed. -## -## @item 103 -## The maximum number of iterations was reached. ## @end table ## ## An example of calling @code{sqp}: @@ -394,6 +398,8 @@ t3 = all (lambda_i >= 0); t4 = norm (lambda .* con); + ## Normal convergence. All constraints are satisfied + ## and objective has converged. if (t2 && t3 && max ([t0; t1; t4]) < tol) info = 101; break; @@ -408,8 +414,8 @@ info = INFO.info; - ## FIXME -- check QP solution and attempt to recover if it has - ## failed. For now, just warn about possible problems. + ## FIXME: check QP solution and attempt to recover if it has failed. + ## For now, just warn about possible problems. id = "Octave:SQP-QP-subproblem"; switch (info) @@ -453,8 +459,9 @@ delx = x_new - x; + ## Check if step size has become too small (indicates lack of progress). if (norm (delx) < tol * norm (x)) - info = 101; + info = 104; break; endif @@ -483,6 +490,8 @@ d2 = delxt*r; + ## Check if the next BFGS update will work properly. + ## If d1 or d2 vanish, the BFGS update will fail. if (d1 == 0 || d2 == 0) info = 102; break; @@ -510,6 +519,7 @@ endwhile + ## Check if we've spent too many iterations without converging. if (iter >= iter_max) info = 103; endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/pkg/module.mk --- a/scripts/pkg/module.mk Sun May 25 10:26:18 2014 -0700 +++ b/scripts/pkg/module.mk Sun May 25 10:29:05 2014 -0700 @@ -5,6 +5,7 @@ pkg/private/configure_make.m \ pkg/private/copy_files.m \ pkg/private/create_pkgadddel.m \ + pkg/private/default_prefix.m \ pkg/private/describe.m \ pkg/private/dirempty.m \ pkg/private/extract_pkg.m \ diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/pkg/pkg.m --- a/scripts/pkg/pkg.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/pkg/pkg.m Sun May 25 10:29:05 2014 -0700 @@ -280,14 +280,7 @@ global_install = ((ispc () && ! isunix ()) || (geteuid () == 0)); if (isbool (prefix)) - if (global_install) - prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages"); - archprefix = fullfile (octave_config_info ("libdir"), - "octave", "packages"); - else - prefix = fullfile ("~", "octave"); - archprefix = prefix; - endif + [prefix, archprefix] = default_prefix (global_install); prefix = tilde_expand (prefix); archprefix = tilde_expand (archprefix); endif @@ -326,15 +319,12 @@ case "-local" global_install = false; if (! user_prefix) - prefix = tilde_expand (fullfile ("~", "octave")); - archprefix = prefix; + [prefix, archprefix] = default_prefix (global_install); endif case "-global" global_install = true; if (! user_prefix) - prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages"); - archprefix = fullfile (octave_config_info ("libdir"), - "octave", "packages"); + [prefix, archprefix] = default_prefix (global_install); endif case available_actions if (strcmp (action, "none")) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/pkg/private/configure_make.m --- a/scripts/pkg/private/configure_make.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/pkg/private/configure_make.m Sun May 25 10:29:05 2014 -0700 @@ -32,11 +32,6 @@ mkoctfile_program = fullfile (octave_bindir, sprintf ("mkoctfile-%s%s", ver, ext)); octave_config_program = fullfile (octave_bindir, sprintf ("octave-config-%s%s", ver, ext)); octave_binary = fullfile (octave_bindir, sprintf ("octave-%s%s", ver, ext)); - cenv = {"MKOCTFILE"; mkoctfile_program; - "OCTAVE_CONFIG"; octave_config_program; - "OCTAVE"; octave_binary; - "INSTALLDIR"; desc.dir}; - scenv = sprintf ("%s=\"%s\" ", cenv{:}); if (! exist (mkoctfile_program, "file")) __gripe_missing_component__ ("pkg", "mkoctfile"); @@ -48,6 +43,16 @@ __gripe_missing_component__ ("pkg", "octave"); endif + if (verbose) + mkoctfile_program = [mkoctfile_program " --verbose"]; + endif + + cenv = {"MKOCTFILE"; mkoctfile_program; + "OCTAVE_CONFIG"; octave_config_program; + "OCTAVE"; octave_binary; + "INSTALLDIR"; desc.dir}; + scenv = sprintf ("%s=\"%s\" ", cenv{:}); + ## Configure. if (exist (fullfile (src, "configure"), "file")) flags = ""; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/pkg/private/default_prefix.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/default_prefix.m Sun May 25 10:29:05 2014 -0700 @@ -0,0 +1,40 @@ +## Copyright (C) 2014 Carlo de Falco +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{prefix}, @var{archprefix} =} @ +## default_prefix (@var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function [prefix, archprefix] = default_prefix (global_install, desc) + if (global_install) + prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages"); + if (nargin == 2) + archprefix = fullfile (octave_config_info ("libdir"), "octave", + "packages", [desc.name "-" desc.version]); + else + archprefix = fullfile (octave_config_info ("libdir"), "octave", + "packages"); + endif + else + prefix = tilde_expand (fullfile ("~", "octave")); + archprefix = prefix; + endif +endfunction + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/pkg/private/getarchprefix.m --- a/scripts/pkg/private/getarchprefix.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/pkg/private/getarchprefix.m Sun May 25 10:29:05 2014 -0700 @@ -24,8 +24,7 @@ function archprefix = getarchprefix (desc, global_install) if (global_install) - archprefix = fullfile (octave_config_info ("libdir"), "octave", - "packages", [desc.name "-" desc.version]); + [~, archprefix] = default_prefix (global_install, desc); else archprefix = desc.dir; endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/appearance/__getlegenddata__.m --- a/scripts/plot/appearance/__getlegenddata__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/appearance/__getlegenddata__.m Sun May 25 10:29:05 2014 -0700 @@ -29,7 +29,7 @@ if (numel (ca) == 1) kids = get (ca, "children"); else - kids = [get(kids, "children"){:}]; + kids = [get(ca, "children"){:}]; endif for i = numel (kids):-1:1 diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/appearance/axis.m --- a/scripts/plot/appearance/axis.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/appearance/axis.m Sun May 25 10:29:05 2014 -0700 @@ -30,7 +30,9 @@ ## The argument @var{limits} should be a 2-, 4-, or 6-element vector. The ## first and second elements specify the lower and upper limits for the ## x-axis. The third and fourth specify the limits for the y-axis, and the -## fifth and sixth specify the limits for the z-axis. +## fifth and sixth specify the limits for the z-axis. The special values +## -Inf and Inf may be used to indicate that the limit should automatically be +## computed based on the data in the axis. ## ## Without any arguments, @code{axis} turns autoscaling on. ## @@ -297,15 +299,15 @@ endfor if (len > 1) - set (ca, "xlim", [ax(1), ax(2)]); + xlim (ca, ax(1:2)); endif if (len > 3) - set (ca, "ylim", [ax(3), ax(4)]); + ylim (ca, ax(3:4)); endif if (len > 5) - set (ca, "zlim", [ax(5), ax(6)]); + zlim (ca, ax(5:6)); endif else diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/appearance/datetick.m --- a/scripts/plot/appearance/datetick.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/appearance/datetick.m Sun May 25 10:29:05 2014 -0700 @@ -45,8 +45,8 @@ unwind_protect ## FIXME: This will bring the axes to the top of the stack. - ## This may not always be desirable if there are multiple axes - ## objects. + ## This may not be desirable if there are multiple axes objects, + ## such as can occur with plotyy. axes (hax); __datetick__ (varargin{:}); unwind_protect_cleanup diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/appearance/diffuse.m --- a/scripts/plot/appearance/diffuse.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/appearance/diffuse.m Sun May 25 10:29:05 2014 -0700 @@ -18,11 +18,11 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} diffuse (@var{sx}, @var{sy}, @var{sz}, @var{lv}) -## Calculate diffuse reflection strength of a surface defined by the normal +## Calculate the diffuse reflection strength of a surface defined by the normal ## vector elements @var{sx}, @var{sy}, @var{sz}. ## -## The light source location vector @var{lv} can be given as 2-element vector -## [azimuth, elevation] in degrees or as 3-element vector [lx, ly, lz]. +## The light source location vector @var{lv} can be given as a 2-element vector +## [azimuth, elevation] in degrees or as a 3-element vector [x, y, z]. ## @seealso{specular, surfl} ## @end deftypefn @@ -34,13 +34,13 @@ print_usage (); endif - ## check for normal vector - if (!size_equal (sx, sy, sz)) - error ("diffuse: SX, SY, and SZ must have same size"); + ## Check normal vectors + if (! size_equal (sx, sy, sz)) + error ("diffuse: SX, SY, and SZ must be the same size"); endif - ## check for light vector (lv) argument - if (length (lv) < 2 || length (lv) > 3) + ## Check light vector (lv) argument + if (! isvector (lv) || length (lv) < 2 || length (lv) > 3) error ("diffuse: light vector LV must be a 2- or 3-element vector"); elseif (length (lv) == 2) [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0); @@ -48,7 +48,7 @@ ## Normalize view and light vector. if (sum (abs (lv)) > 0) - lv /= norm (lv); + lv /= norm (lv); endif ns = sqrt (sx.^2 + sy.^2 + sz.^2); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/appearance/legend.m --- a/scripts/plot/appearance/legend.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/appearance/legend.m Sun May 25 10:29:05 2014 -0700 @@ -166,11 +166,27 @@ nargs = numel (varargin); nkids = numel (kids); + ## Find any existing legend object on figure + hlegend = []; + fkids = get (fig, "children"); + for i = 1 : numel (fkids) + if ( strcmp (get (fkids(i), "type"), "axes") + && strcmp (get (fkids(i), "tag"), "legend")) + udata = get (fkids(i), "userdata"); + if (any (ismember (udata.handle, ca))) + hlegend = fkids(i); + break; + endif + endif + endfor + orientation = "default"; location = "default"; show = "create"; textpos = "default"; box = "default"; + delete_leg = false; + find_leg_hdl = (nargs == 0); ## Process old way of specifying location with a number rather than a string. if (nargs > 0) @@ -229,20 +245,6 @@ error ("legend: unrecognized legend location"); endswitch - ## Find any existing legend object on figure - hlegend = []; - fkids = get (fig, "children"); - for i = 1 : numel (fkids) - if ( strcmp (get (fkids(i), "type"), "axes") - && strcmp (get (fkids(i), "tag"), "legend")) - udata = get (fkids(i), "userdata"); - if (any (udata.handle == ca)) - hlegend = fkids(i); - break; - endif - endif - endfor - if (nargs == 1) arg = varargin{1}; if (ischar (arg)) @@ -250,8 +252,7 @@ str = tolower (strtrim (arg)); switch (str) case "off" - delete (hlegend); - return; + delete_leg = true; case "hide" show = "off"; nargs--; @@ -305,24 +306,26 @@ endif have_labels = (nargs > 0); + hobjects = []; + hplots = []; + text_strings = {}; - if (strcmp (show, "off")) + if (delete_leg) + delete (hlegend); + hlegend = []; + elseif (find_leg_hdl) + ## Don't change anything about legend. + ## hleg output will be assigned hlegend value at end of function. + elseif (strcmp (show, "off")) if (! isempty (hlegend)) set (findobj (hlegend), "visible", "off"); hlegend = []; endif - hobjects = []; - hplots = []; - text_strings = {}; elseif (strcmp (show, "on")) if (! isempty (hlegend)) set (findobj (hlegend), "visible", "on"); - ## NOTE - Matlab sets both "visible", and "box" to "on" + ## NOTE: Matlab sets both "visible" and "box" to "on" set (hlegend, "visible", get (hlegend, "box")); - else - hobjects = []; - hplots = []; - text_strings = {}; endif elseif (strcmp (box, "on")) if (! isempty (hlegend)) @@ -332,26 +335,24 @@ if (! isempty (hlegend)) set (hlegend, "box", "off", "visible", "off"); endif - elseif (! have_labels && ! (strcmp (location, "default") && - strcmp (orientation, "default"))) + elseif (! have_labels && ! isempty (hlegend) + && ! (strcmp (location, "default") && strcmp (orientation, "default"))) ## Changing location or orientation of existing legend - if (! isempty (hlegend)) - if (strcmp (location, "default")) - set (hlegend, "orientation", orientation); - elseif (strcmp (orientation, "default")) - if (outside) - set (hlegend, "location", [location "outside"]); - else - set (hlegend, "location", location); - endif + if (strcmp (location, "default")) + set (hlegend, "orientation", orientation); + elseif (strcmp (orientation, "default")) + if (outside) + set (hlegend, "location", [location "outside"]); else - if (outside) - set (hlegend, "location", [location "outside"], - "orientation", orientation); - else - set (hlegend, "location", location, - "orientation", orientation); - endif + set (hlegend, "location", location); + endif + else + if (outside) + set (hlegend, "location", [location "outside"], + "orientation", orientation); + else + set (hlegend, "location", location, + "orientation", orientation); endif endif else @@ -565,6 +566,12 @@ linelength = 15; ## Create the axis first + oldfig = get (0, "currentfigure"); + if (oldfig != fig) + set (0, "currentfigure", fig); + else + oldfig = []; + endif curaxes = get (fig, "currentaxes"); unwind_protect ud = ancestor (hplots, "axes"); @@ -829,10 +836,11 @@ case "line" color = get (hplots(k), "color"); style = get (hplots(k), "linestyle"); + lwidth = min (get (hplots(k), "linewidth"), 5); if (! strcmp (style, "none")) l1 = line ("xdata", ([xoffset, xoffset + linelength] + xk * xstep) / lpos(3), "ydata", [1, 1] .* (lpos(4) - yoffset - yk * ystep) / lpos(4), - "color", color, "linestyle", style, + "color", color, "linestyle", style, "linewidth", lwidth, "marker", "none", "userdata", hplots(k)); hobjects(end+1) = l1; @@ -841,11 +849,11 @@ if (! strcmp (marker, "none")) l1 = line ("xdata", (xoffset + 0.5 * linelength + xk * xstep) / lpos(3), "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4), - "color", color, "linestyle", "none", + "color", color, "linestyle", "none", "linewidth", lwidth, "marker", marker, "markeredgecolor",get (hplots(k), "markeredgecolor"), "markerfacecolor",get (hplots(k), "markerfacecolor"), - "markersize", get (hplots(k), "markersize"), + "markersize", min (get (hplots(k), "markersize"),10), "userdata", hplots(k)); hobjects(end+1) = l1; endif @@ -855,6 +863,8 @@ {@updateline, hlegend, linelength, false}); addlistener (hplots(k), "linestyle", {@updateline, hlegend, linelength, false}); + addlistener (hplots(k), "linewidth", + {@updateline, hlegend, linelength, false}); addlistener (hplots(k), "marker", {@updateline, hlegend, linelength, false}); addlistener (hplots(k), "markeredgecolor", @@ -876,13 +886,24 @@ xoffset + xk * xstep) / lpos(3), "ydata", (lpos(4) - yoffset - [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4), - "facecolor", facecolor, "edgecolor", edgecolor, - "cdata", cdata, "userdata", hplots(k)); - hobjects(end+1) = p1; - ## Copy clim from axes so that colors work out. - set (hlegend, "clim", get (ca(1), "clim")); + "facecolor", facecolor, "edgecolor", edgecolor, + "cdata", cdata, "userdata", hplots(k)); + else + ## non-standard patch only making use of marker styles + ## such as scatter plot. + p1 = patch ("xdata", (xoffset + 0.5 * linelength + xk * xstep) / lpos(3), + "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4), + "marker", get (hplots(k), "marker"), + "markeredgecolor",get (hplots(k),"markeredgecolor"), + "markerfacecolor",get (hplots(k),"markerfacecolor"), + "markersize", min (get (hplots(k),"markersize"),10), + "cdata", cdata, "userdata", hplots(k)); endif - ## FIXME: Probably need listeners, as for line objects + hobjects(end+1) = p1; + ## Copy clim from axes so that colors work out. + set (hlegend, "clim", get (ca(1), "clim")); + + ## FIXME: Need listeners, as for line objects. ## Changing clim, for example, won't update colors case "surface" @@ -894,11 +915,11 @@ xoffset + xk * xstep) / lpos(3), "ydata", (lpos(4) - yoffset - [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4), - "facecolor", facecolor, "edgecolor", edgecolor, - "cdata", cdata, "userdata", hplots(k)); + "facecolor", facecolor, "edgecolor", edgecolor, + "cdata", cdata, "userdata", hplots(k)); hobjects(end+1) = p1; endif - ## FIXME: Probably need listeners, as for line objects + ## FIXME: Need listeners, as for line objects. endswitch @@ -1032,6 +1053,9 @@ endif unwind_protect_cleanup set (fig, "currentaxes", curaxes); + if (! isempty (oldfig)) + set (0, "currentfigure", oldfig); + endif end_unwind_protect endif endif @@ -1065,8 +1089,10 @@ set (hax, "position", position); set (hax, "outerposition", outerposition); endswitch - set (hax, "units", units); - h = legend (hax, hplots, get (h, "string")); + ## Crazy syntax because set() only seems to support row vectors + set (hax, repmat ({"units"}, [1 numel(hax)]), units(:)'); + + h = legend (hax(1), hplots, get (h, "string")); unwind_protect_cleanup recursive = false; end_unwind_protect @@ -1149,6 +1175,7 @@ if (ishandle (hplots(i)) && strcmp (get (hplots(i), "type"), "line")) dellistener (hplots(i), "color"); dellistener (hplots(i), "linestyle"); + dellistener (hplots(i), "linewidth"); dellistener (hplots(i), "marker"); dellistener (hplots(i), "markeredgecolor"); dellistener (hplots(i), "markerfacecolor"); @@ -1163,7 +1190,7 @@ if (update_name) ## When string changes, have to rebuild legend completely [hplots, text_strings] = __getlegenddata__ (hlegend); - legend (hplots, text_strings); + legend (get (hplots(1), "parent"), hplots, text_strings); else kids = get (hlegend, "children"); ll = lm = []; @@ -1198,14 +1225,18 @@ if (! strcmp (linestyle, "none")) line ("xdata", xpos1, "ydata", ypos1, "color", get (h, "color"), - "linestyle", get (h, "linestyle"), "marker", "none", + "linestyle", get (h, "linestyle"), + "linewidth", min (get (h, "linewidth"), 5), + "marker", "none", "userdata", h, "parent", hlegend); endif if (! strcmp (marker, "none")) line ("xdata", xpos2, "ydata", ypos2, "color", get (h, "color"), "marker", marker, "markeredgecolor", get (h, "markeredgecolor"), "markerfacecolor", get (h, "markerfacecolor"), - "markersize", get (h, "markersize"), "linestyle", "none", + "markersize", min (get (h, "markersize"), 10), + "linestyle", "none", + "linewidth", min (get (h, "linewidth"), 5), "userdata", h, "parent", hlegend); endif endif @@ -1223,8 +1254,8 @@ %!demo %! clf; %! plot (rand (3)); -%! title ('legend() without inputs creates default labels'); -%! h = legend (); +%! title ('legend("show") without inputs creates default labels'); +%! h = legend ('show'); %!demo %! clf; @@ -1605,3 +1636,20 @@ %! graphics_toolkit (toolkit); %! end_unwind_protect +%!test +%! ## bug #42035 +%! h = figure ("visible", "off"); +%! unwind_protect +%! hax1 = subplot (1,2,1); +%! plot (1:10); +%! hax2 = subplot (1,2,2); +%! plot (1:10); +%! hleg1 = legend (hax1, "foo"); +%! assert (get (hleg1, "userdata").handle, hax1) +%! assert (gca (), hax2); +%! hleg2 = legend ("bar"); +%! assert (get (hleg2, "userdata").handle, gca ()) +%! unwind_protect_cleanup +%! close (h); +%! end_unwind_protect + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/appearance/private/__axis_limits__.m --- a/scripts/plot/appearance/private/__axis_limits__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/appearance/private/__axis_limits__.m Sun May 25 10:29:05 2014 -0700 @@ -48,6 +48,11 @@ if (arg(1) >= arg(2)) error ("%s: axis limits must be increasing", fcn); else + autoscale = isinf (arg); + if (any (autoscale)) + set (hax, fcnmode, "auto"); + arg(autoscale) = get (hax, fcn)(autoscale); + endif set (hax, fcn, arg(:)); endif endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/appearance/specular.m --- a/scripts/plot/appearance/specular.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/appearance/specular.m Sun May 25 10:29:05 2014 -0700 @@ -19,15 +19,17 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv}) ## @deftypefnx {Function File} {} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv}, @var{se}) -## Calculate specular reflection strength of a surface defined by the normal -## vector elements @var{sx}, @var{sy}, @var{sz} using Phong's approximation. +## Calculate the specular reflection strength of a surface defined by the +## normal vector elements @var{sx}, @var{sy}, @var{sz} using Phong's +## approximation. ## -## The light source location and viewer location vectors can be specified using -## parameter @var{lv} and @var{vv} respectively. The location vectors can +## The light source location and viewer location vectors are specified using +## parameters @var{lv} and @var{vv} respectively. The location vectors can ## given as 2-element vectors [azimuth, elevation] in degrees or as 3-element ## vectors [x, y, z]. ## -## An optional sixth argument describes the specular exponent (spread) @var{se}. +## An optional sixth argument specifies the specular exponent (spread) @var{se}. +## If not given, @var{se} defaults to 10. ## @seealso{diffuse, surfl} ## @end deftypefn @@ -39,54 +41,52 @@ print_usage (); endif - ## Checks for specular exponent (se). - if (nargin < 6) - se = 10; - else - if (!isnumeric (se) || numel (se) != 1 || se <= 0) - error ("specular: exponent must be positive scalar"); - endif + ## Check normal vectors + if (! size_equal (sx, sy, sz)) + error ("specular: SX, SY, and SZ must be the same size"); endif - ## Checks for normal vector. - if (!size_equal (sx, sy, sz)) - error ("specular: SX, SY, and SZ must have same size"); - endif - - ## Check for light vector (lv) argument. - if (length (lv) < 2 || length (lv) > 3) + ## Check light vector (lv) argument + if (! isvector (lv) || length (lv) < 2 || length (lv) > 3) error ("specular: light vector LV must be a 2- or 3-element vector"); elseif (length (lv) == 2) [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0); endif - ## Check for view vector (vv) argument. - if (length (vv) < 2 || length (lv) > 3) + ## Check view vector (vv) argument + if (! isvector (vv) || length (vv) < 2 || length (lv) > 3) error ("specular: view vector VV must be a 2- or 3-element vector"); elseif (length (vv) == 2) [vv(1), vv(2), vv(3)] = sph2cart (vv(1) * pi / 180, vv(2) * pi / 180, 1.0); endif - ## Normalize view and light vector. + ## Check specular exponent (se) argument + if (nargin < 6) + se = 10; + elseif (! (isnumeric (se) && numel (se) == 1 && se > 0)) + error ("specular: exponent SE must be a positive scalar"); + endif + + ## Normalize view and light vectors if (sum (abs (lv)) > 0) - lv /= norm (lv); + lv /= norm (lv); endif if (sum (abs (vv)) > 0) - vv /= norm (vv); + vv /= norm (vv); endif - ## Calculate normal vector lengths and dot-products. + ## Calculate normal vector lengths and dot-products ns = sqrt (sx.^2 + sy.^2 + sz.^2); l_dot_n = (sx * lv(1) + sy * lv(2) + sz * lv(3)) ./ ns; v_dot_n = (sx * vv(1) + sy * vv(2) + sz * vv(3)) ./ ns; - ## Calculate specular reflection using Phong's approximation. + ## Calculate specular reflection using Phong's approximation retval = 2 * l_dot_n .* v_dot_n - dot (lv, vv); - ## Set zero if light is on the other side. + ## Set reflectance to zero if light is on the other side retval(l_dot_n < 0) = 0; - ## Allow postive values only. + ## Allow postive values only retval(retval < 0) = 0; retval = retval .^ se; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/area.m --- a/scripts/plot/draw/area.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/area.m Sun May 25 10:29:05 2014 -0700 @@ -49,7 +49,7 @@ ## @example ## @group ## t = linspace (0, 2*pi, 100)'; -## y = [sin(t).^2, cos(t).^2)]; +## y = [sin(t).^2, cos(t).^2]; ## area (t, y); ## legend ("sin^2", "cos^2", "location", "NorthEastOutside"); ## @end group diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/colorbar.m --- a/scripts/plot/draw/colorbar.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/colorbar.m Sun May 25 10:29:05 2014 -0700 @@ -310,24 +310,6 @@ set (hi, "xdata", [cmin, cmax]); set (hiax, "xlim", cext); endif - - ## FIXME: Setting xlim or ylim from within a listener callback - ## causes the axis to change size rather than change limits. - ## Workaround it by jiggling the position property which forces - ## a redraw of the axis object. - ## - ## Debug Example: - ## Uncomment the line below. - ## keyboard; - ## Now run the the following code. - ## clf; colorbar (); contour (peaks ()) - ## Once the keyboard command has been hit in the debugger try - ## set (hiax, "ylim", [0 0.5]) - pos = get (hiax, "position"); - pos(1) += eps; - set (hiax, "position", pos); - pos(1) -= eps; - set (hiax, "position", pos); endif endfunction diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/fill.m --- a/scripts/plot/draw/fill.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/fill.m Sun May 25 10:29:05 2014 -0700 @@ -92,17 +92,28 @@ set (hax, "nextplot", "add"); for i = 1 : length (iargs) + x = varargin{iargs(i)}; + y = varargin{iargs(i) + 1}; cdata = varargin{iargs(i) + 2}; + + if (! size_equal (x,y)) + if (iscolumn (y) && rows (y) == rows (x)) + y = repmat (y, [1, columns(x)]); + elseif (iscolumn (x) && rows (x) == rows (y)) + x = repmat (x, [1, columns(y)]); + else + error ("fill: X annd Y must have same number of rows"); + endif + endif ## For Matlab compatibility, replicate cdata to match size of data - if (iscolumn (cdata)) - sz = size (varargin{iargs(i)}); + if (iscolumn (cdata) && ! ischar (cdata)) + sz = size (x); if (all (sz > 1)) cdata = repmat (cdata, [1, sz(2)]); endif endif - [htmp, fail] = __patch__ (hax, varargin{iargs(i)+(0:1)}, cdata, - opts{:}); + [htmp, fail] = __patch__ (hax, x, y, cdata, opts{:}); if (fail) print_usage (); endif @@ -160,4 +171,30 @@ %! x2 = sin (t2) + 0.8; %! y2 = cos (t2); %! h = fill (x1,y1,'r', x2,y2,'g'); +%! title ({'fill() function'; 'cdata specified with string'}); +%!demo +%! clf; +%! t1 = (1/16:1/8:1) * 2*pi; +%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi; +%! x1 = sin (t1) - 0.8; +%! y1 = cos (t1); +%! x2 = sin (t2) + 0.8; +%! y2 = cos (t2); +%! h = fill (x1,y1,1, x2,y2,2); +%! title ({'fill() function'; 'cdata = row vector produces FaceColor = "flat"'}); + +%!demo +%! clf; +%! x = [0 0 +%! 1 0.5 +%! 1 0.5 +%! 0 0]; +%! y = [0 0 +%! 0 0 +%! 1 0.5 +%! 1 0.5]; +%! c = [1 2 3 4]'; +%! fill (x, y, c); +%! title ({'fill() function'; 'cdata = column vector produces FaceColor = "interp"'}); + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/patch.m --- a/scripts/plot/draw/patch.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/patch.m Sun May 25 10:29:05 2014 -0700 @@ -88,6 +88,15 @@ print_usage (); endif + ## FIXME: This is a hack to get 'layer' command to work for 2D patches + ## Alternative is much more complicated surgery in graphics.cc. + ## of get_children_limits() for 'z' axis and 'patch' object type. + if (! ishold ()) + if (isempty (get (htmp, "zdata"))) + set (hax, "zlim", [-1 1]); + endif + endif + if (nargout > 0) h = htmp; endif diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/peaks.m --- a/scripts/plot/draw/peaks.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/peaks.m Sun May 25 10:29:05 2014 -0700 @@ -27,7 +27,7 @@ ## The function has the form ## ## @tex -## $$f(x,y) = 3 (1 - x) ^ 2 e ^ {\left(-x^2 - (y+1)^2\right)} - 10 \left({x \over 5} - x^3 - y^5)\right) - {1 \over 3} e^{\left(-(x+1)^2 - y^2\right)}$$ +## $$f(x,y) = 3 (1 - x) ^ 2 e ^ {\left(-x^2 - (y+1)^2\right)} - 10 \left({x \over 5} - x^3 - y^5\right) - {1 \over 3} e^{\left(-(x+1)^2 - y^2\right)}$$ ## @end tex ## @ifnottex ## @verbatim diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/plotyy.m --- a/scripts/plot/draw/plotyy.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/plotyy.m Sun May 25 10:29:05 2014 -0700 @@ -22,7 +22,7 @@ ## @deftypefnx {Function File} {} plotyy (@dots{}, @var{fun1}, @var{fun2}) ## @deftypefnx {Function File} {} plotyy (@var{hax}, @dots{}) ## @deftypefnx {Function File} {[@var{ax}, @var{h1}, @var{h2}] =} plotyy (@dots{}) -## Plot two sets of data with independent y-axes. +## Plot two sets of data with independent y-axes and a common x-axis. ## ## The arguments @var{x1} and @var{y1} define the arguments for the first plot ## and @var{x1} and @var{y2} for the second. @@ -40,7 +40,7 @@ ## the principal axis in which to plot the @var{x1} and @var{y1} data. ## ## The return value @var{ax} is a vector with the axis handles of the two -## y axes. @var{h1} and @var{h2} are handles to the objects generated by the +## y-axes. @var{h1} and @var{h2} are handles to the objects generated by the ## plot commands. ## ## @example @@ -57,113 +57,66 @@ ## @seealso{plot} ## @end deftypefn -function [Ax, H1, H2] = plotyy (varargin) +function [ax, h1, h2] = plotyy (varargin) - ## Don't use __plt_get_axis_arg__ here as ax is a two vector for plotyy - if (nargin > 1 && length (varargin{1}) == 2 && ishandle (varargin{1}(1)) - && ishandle (varargin{1}(2)) - && all (floor (varargin{1}) != varargin{1})) - obj1 = get (varargin{1}(1)); - obj2 = get (varargin{1}(2)); - if (strcmp (obj1.type, "axes") || strcmp (obj2.type, "axes")) - ax = [obj1, obj2]; - varargin(1) = []; - if (isempty (varargin)) - varargin = {}; - endif - else - error ("plotyy: expecting first argument to be axes handle"); - endif - oldh = gca (); - else - f = get (0, "currentfigure"); - if (isempty (f)) - f = figure (); - endif - ca = get (f, "currentaxes"); - if (isempty (ca)) - ax = []; - elseif (ishandle (ca) && isprop (ca, "__plotyy_axes__")) - ax = get (ca, "__plotyy_axes__"); - else - ax = ca; - endif - if (length (ax) > 2) - for i = 3 : length (ax) - delete (ax (i)); - endfor - ax = ax(1:2); - elseif (length (ax) == 1) - ax(2) = axes (); - set (ax(2), "nextplot", get (ax(1), "nextplot")); - elseif (isempty (ax)) - ax(1) = axes (); - ax(2) = axes (); - ca = ax(2); - endif - if (nargin < 2) - varargin = {}; - endif - oldh = ca; - endif + [hax, varargin] = __plt_get_axis_arg__ ("plotyy", varargin{:}); - if (nargin < 4) + nargin = numel (varargin); + if (nargin < 4 || nargin > 6) print_usage (); endif + oldfig = []; + if (! isempty (hax)) + oldfig = get (0, "currentfigure"); + endif unwind_protect - [ax, h1, h2] = __plotyy__ (ax, varargin{:}); + hax = newplot (hax); + + ## FIXME: Second conditional test shouldn't be required. + ## 'cla reset' needs to delete user properties like __plotyy_axes__. + if (isprop (hax, "__plotyy_axes__") + && isaxes (get (hax, "__plotyy_axes__")) == [true true]) + hax = get (hax, "__plotyy_axes__"); + else + hax(2) = axes ("nextplot", get (hax(1), "nextplot")); + endif + + [axtmp, h1tmp, h2tmp] = __plotyy__ (hax, varargin{:}); + + set (gcf, "currentaxes", hax(1)); + unwind_protect_cleanup - ## Only change back to the old axis if we didn't delete it - if (isaxes (oldh)) - axes (oldh); + if (! isempty (oldfig)) + set (0, "currentfigure", oldfig); endif end_unwind_protect if (nargout > 0) - Ax = ax; - H1 = h1; - H2 = h2; + ax = axtmp; + h1 = h1tmp; + h2 = h2tmp; endif endfunction -function [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, varargin) - if (nargin > 5) - fun1 = varargin{1}; - else - fun1 = @plot; - endif - if (nargin > 6) - fun2 = varargin{2}; - else +function [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, fun1 = @plot, fun2) + + if (nargin < 7) fun2 = fun1; endif xlim = [min([x1(:); x2(:)]), max([x1(:); x2(:)])]; - if (isaxes (ax(1))) - axes (ax(1)); - else - ax(1) = axes (); - endif - newplot (); + axes (ax(1)); + h1 = feval (fun1, x1, y1); - set (ax(1), "ycolor", getcolor (h1(1))); - set (ax(1), "xlim", xlim); - set (ax(1), "color", "none"); - - cf = gcf (); - set (cf, "nextplot", "add"); + set (ax(1), "color", "none", "ycolor", getcolor (h1(1)), "xlim", xlim); - if (isaxes (ax(2))) - axes (ax(2)); - else - ax(2) = axes (); - set (ax(2), "nextplot", get (ax(1), "nextplot")); - endif - newplot (); + set (gcf (), "nextplot", "add"); + + axes (ax(2)); colors = get (ax(1), "colororder"); set (ax(2), "colororder", [colors(2:end,:); colors(1,:)]); @@ -174,35 +127,38 @@ set (ax, "activepositionproperty", "position"); endif - ## Kluge, until __plt_get_axis_arg__ and newplot are reworked. - set (ax(2), "nextplot", "replacechildren"); + ## Don't replace axis which has colororder property already modified + if (strcmp (get (ax(1), "nextplot"), "replace")) + set (ax(2), "nextplot", "replacechildren"); + endif h2 = feval (fun2, ax(2), x2, y2); - set (ax(2), "yaxislocation", "right"); - set (ax(2), "ycolor", getcolor (h2(1))); + + set (ax(2), "yaxislocation", "right", "color", "none", + "ycolor", getcolor (h2(1)), "box", "off", "xlim", xlim); if (strcmp (get(ax(1), "activepositionproperty"), "position")) set (ax(2), "position", get (ax(1), "position")); else - set (ax(2), "outerposition", get (ax(1), "outerposition")); - set (ax(2), "looseinset", get (ax(1), "looseinset")); + set (ax(2), {"outerposition", "looseinset"}, + get (ax(1), {"outerposition", "looseinset"})); endif - set (ax(2), "xlim", xlim); - set (ax(2), "color", "none"); - set (ax(2), "box", "off"); + ## Restore nextplot value by copying value from axis #1 + set (ax(2), "nextplot", get (ax(1), "nextplot")); ## Add invisible text objects that when destroyed, ## also remove the other axis t1 = text (0, 0, "", "parent", ax(1), "tag", "plotyy", - "handlevisibility", "off", "visible", "off", + "visible", "off", "handlevisibility", "off", "xliminclude", "off", "yliminclude", "off"); t2 = text (0, 0, "", "parent", ax(2), "tag", "plotyy", - "handlevisibility", "off", "visible", "off", + "visible", "off", "handlevisibility", "off", "xliminclude", "off", "yliminclude", "off"); set (t1, "deletefcn", {@deleteplotyy, ax(2), t2}); set (t2, "deletefcn", {@deleteplotyy, ax(1), t1}); + ## Add cross-listeners so a change in one axes' attributes updates the other. addlistener (ax(1), "position", {@update_position, ax(2)}); addlistener (ax(2), "position", {@update_position, ax(1)}); addlistener (ax(1), "outerposition", {@update_position, ax(2)}); @@ -235,6 +191,80 @@ endif endfunction +function deleteplotyy (h, ~, ax2, t2) + if (isaxes (ax2) + && (isempty (gcbf ()) || strcmp (get (gcbf (), "beingdeleted"), "off")) + && strcmp (get (ax2, "beingdeleted"), "off")) + set (t2, "deletefcn", []); + delete (ax2); + endif +endfunction + +function update_nextplot (h, ~, ax2) + persistent recursion = false; + if (! recursion) + unwind_protect + recursion = true; + set (ax2, "nextplot", get (h, "nextplot")); + unwind_protect_cleanup + recursion = false; + end_unwind_protect + endif +endfunction + +function update_position (h, ~, ax2) + persistent recursion = false; + + ## Don't allow recursion + if (! recursion) + unwind_protect + recursion = true; + view = get (h, "view"); + oldview = get (ax2, "view"); + plotboxaspectratio = get (h, "plotboxaspectratio"); + oldplotboxaspectratio = get (ax2, "plotboxaspectratio"); + plotboxaspectratiomode = get (h, "plotboxaspectratiomode"); + oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode"); + + if (strcmp (get (h, "activepositionproperty"), "position")) + position = get (h, "position"); + oldposition = get (ax2, "position"); + if (! (isequal (position, oldposition) && isequal (view, oldview))) + set (ax2, "position", position, "view", view); + endif + else + outerposition = get (h, "outerposition"); + oldouterposition = get (ax2, "outerposition"); + if (! (isequal (outerposition, oldouterposition) + && isequal (view, oldview))) + set (ax2, "outerposition", outerposition, "view", view); + endif + endif + + if (! (isequal (plotboxaspectratio, oldplotboxaspectratio) + && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode))) + set (ax2, "plotboxaspectratio", plotboxaspectratio, + "plotboxaspectratiomode", plotboxaspectratiomode); + endif + unwind_protect_cleanup + recursion = false; + end_unwind_protect + endif +endfunction + +function color = getcolor (ax) + obj = get (ax); + if (isfield (obj, "color")) + color = obj.color; + elseif (isfield (obj, "facecolor") && ! ischar (obj.facecolor)) + color = obj.facecolor; + elseif (isfield (obj, "edgecolor") && ! ischar (obj.edgecolor)) + color = obj.edgecolor; + else + color = [0, 0, 0]; + endif +endfunction + %!demo %! clf; @@ -245,12 +275,11 @@ %! xlabel ('X'); %! ylabel (ax(1), 'Axis 1'); %! ylabel (ax(2), 'Axis 2'); -%! axes (ax(1)); %! text (0.5, 0.5, 'Left Axis', ... -%! 'color', [0 0 1], 'horizontalalignment', 'center'); -%! axes (ax(2)); +%! 'color', [0 0 1], 'horizontalalignment', 'center', 'parent', ax(1)); %! text (4.5, 80, 'Right Axis', ... -%! 'color', [0 0.5 0], 'horizontalalignment', 'center'); +%! 'color', [0 0.5 0], 'horizontalalignment', 'center', 'parent', ax(2)); +%! title ({"plotyy() example"; "Left axis uses @plot, Right axis uses @semilogy"}); %!demo %! clf; @@ -267,14 +296,6 @@ %! axis square; %!demo -%! clf; -%! x = linspace (-1, 1, 201); -%! hax = plotyy (x, sin (pi*x), x, cos (pi*x)); -%! ylabel (hax(1), 'Blue on the Left'); -%! ylabel (hax(2), 'Green on the Right'); -%! xlabel ('xlabel'); - -%!demo %! clf %! hold on %! t = (0:0.1:9); @@ -284,81 +305,7 @@ %! [~, h3, h4] = plotyy (t+1, x, t+1, y); %! set ([h3, h4], 'linestyle', '--'); %! xlabel (hax(1), 'xlabel'); -%! title (hax(2), 'title'); +%! title (hax(2), 'Two plotyy graphs on same figure using "hold on"'); %! ylabel (hax(1), 'Left axis is Blue'); %! ylabel (hax(2), 'Right axis is Green'); -function deleteplotyy (h, d, ax2, t2) - if (isaxes (ax2) - && (isempty (gcbf ()) || strcmp (get (gcbf (), "beingdeleted"),"off")) - && strcmp (get (ax2, "beingdeleted"), "off")) - set (t2, "deletefcn", []); - delete (ax2); - endif -endfunction - -function update_nextplot (h, d, ax2) - persistent recursion = false; - prop = "nextplot"; - if (! recursion) - unwind_protect - recursion = true; - set (ax2, prop, get (h, prop)); - unwind_protect_cleanup - recursion = false; - end_unwind_protect - endif -endfunction - -function update_position (h, d, ax2) - persistent recursion = false; - - ## Don't allow recursion - if (! recursion) - unwind_protect - recursion = true; - view = get (h, "view"); - oldview = get (ax2, "view"); - plotboxaspectratio = get (h, "plotboxaspectratio"); - oldplotboxaspectratio = get (ax2, "plotboxaspectratio"); - plotboxaspectratiomode = get (h, "plotboxaspectratiomode"); - oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode"); - - if (strcmp (get(h, "activepositionproperty"), "position")) - position = get (h, "position"); - oldposition = get (ax2, "position"); - if (! (isequal (position, oldposition) && isequal (view, oldview))) - set (ax2, "position", position, "view", view); - endif - else - outerposition = get (h, "outerposition"); - oldouterposition = get (ax2, "outerposition"); - if (! (isequal (outerposition, oldouterposition) && isequal (view, oldview))) - set (ax2, "outerposition", outerposition, "view", view); - endif - endif - - if (! (isequal (plotboxaspectratio, oldplotboxaspectratio) - && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode))) - set (ax2, "plotboxaspectratio", plotboxaspectratio); - set (ax2, "plotboxaspectratiomode", plotboxaspectratiomode); - endif - unwind_protect_cleanup - recursion = false; - end_unwind_protect - endif -endfunction - -function color = getcolor (ax) - obj = get (ax); - if (isfield (obj, "color")) - color = obj.color; - elseif (isfield (obj, "facecolor") && ! ischar (obj.facecolor)) - color = obj.facecolor; - elseif (isfield (obj, "edgecolor") && ! ischar (obj.edgecolor)) - color = obj.edgecolor; - else - color = [0, 0, 0]; - endif -endfunction - diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/polar.m --- a/scripts/plot/draw/polar.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/polar.m Sun May 25 10:29:05 2014 -0700 @@ -36,6 +36,14 @@ ## ## The optional return value @var{h} is a graphics handle to the created plot. ## +## Implementation Note: The polar axis is drawn using line and text objects +## encapsulated in an hggroup. The hggroup properties are linked to the +## original axes object such that altering an appearance property, for example +## @code{fontname}, will update the polar axis. Two new properties are +## added to the original axes--@code{rtick}, @code{ttick}--which replace +## @code{xtick}, @code{ytick}. The first is a list of tick locations in the +## radial (rho) direction; The second is a list of tick locations in the +## angular (theta) direction specified in degrees, i.e., in the range 0--359. ## @seealso{rose, compass, plot} ## @end deftypefn @@ -87,9 +95,46 @@ print_usage (); endif - set (hax, "xlim", [-maxr, maxr], "ylim", [-maxr, maxr], - "xaxislocation", "zero", "yaxislocation", "zero", - "plotboxaspectratio", [1, 1, 1]); + ## FIXME: Should more gracefully handle "hold on" and not override props. + set (hax, "visible", "off", "plotboxaspectratio", [1, 1, 1], + "zlim", [-1 1]); + + if (! isprop (hax, "rtick")) + addproperty ("rtick", hax, "data"); + endif + + ## calculate r(ho)tick from xtick + xtick = get (hax, "xtick"); + rtick = xtick(find (xtick > 0, 1):find (xtick >= maxr, 1)); + if (isempty (rtick)) + rtick = [0.5 1]; + endif + set (hax, "rtick", rtick); + + ## add t(heta)tick + if (! isprop (hax, "ttick")) + addproperty ("ttick", hax, "data"); + endif + + ## theta(angular) ticks in degrees + set (hax, "ttick", 0:30:330); + + ## Create hggroup to hold text/line objects and attach listeners + hg = hggroup (hax, "tag", "polar_grid", "handlevisibility", "off"); + __update_polar_grid__(hax, [], hg); + + addlistener (hax, "rtick", {@__update_polar_grid__, hg}); + addlistener (hax, "ttick", {@__update_polar_grid__, hg}); + addlistener (hax, "color", {@__update_patch__, hg}); + addlistener (hax, "fontangle", {@__update_text__, hg, "fontangle"}); + addlistener (hax, "fontname", {@__update_text__, hg, "fontname"}); + addlistener (hax, "fontsize", {@__update_text__, hg, "fontsize"}); + addlistener (hax, "fontunits", {@__update_text__, hg, "fontunits"}); + addlistener (hax, "fontweight", {@__update_text__, hg, "fontweight"}); + addlistener (hax, "interpreter", {@__update_text__, hg, "interpreter"}); + addlistener (hax, "layer", {@__update_layer__, hg}); + addlistener (hax, "gridlinestyle", {@__update_lines__, hg,"gridlinestyle"}); + addlistener (hax, "linewidth", {@__update_lines__, hg, "linewidth"}); unwind_protect_cleanup if (! isempty (oldfig)) @@ -193,6 +238,116 @@ endfunction +## Callback functions for listeners + +function __update_text__ (hax, ~, hg, prop) + + kids = get (hg, "children"); + idx = strcmp (get (kids, "type"), "text"); + set (kids(idx).', prop, get (hax, prop)); + +endfunction + +function __update_lines__ (hax, ~, hg, prop) + + kids = get (hg, "children"); + idx = strcmp (get (kids, "type"), "line"); + lprop = prop; + if (strcmp (prop, "gridlinestyle")) + lprop = "linestyle"; + endif + set (kids(idx).', lprop, get (hax, prop)); + +endfunction + +function __update_patch__ (hax, ~, hg) + + kids = get (hg, "children"); + idx = strcmp (get (kids, "type"), "patch"); + set (kids(idx).', "facecolor", get (hax, "color")); + +endfunction + +function __update_layer__ (hax, ~, hg) + + set (hg, "handlevisibility", "on"); + kids = get (hax, "children"); + if (strcmp (get (hax, "layer"), "bottom")) + set (hax, "children", [kids(kids != hg); hg]); + else + set (hax, "children", [hg; kids(kids != hg)]); + endif + set (hg, "handlevisibility", "off"); + +endfunction + +function __update_polar_grid__ (hax, ~, hg) + + ## Delete existing polar grid + delete (get (hg, "children")); + + rtick = unique (get (hax, "rtick")(:)'); + rtick = rtick(rtick > 0); + if (isempty (rtick)) + rtick = [0.5 1]; + endif + + ttick = unique (get (hax, "ttick")(:)'); + ttick = ttick(ttick >= 0); + if (isempty (ttick)) + ttick = 0:30:330; + endif + + lprops = {"linestyle", get(hax, "gridlinestyle"), ... + "linewidth", get(hax, "linewidth")}; + ## "fontunits" should be first because it affects "fontsize" property. + tprops(1:2:12) = {"fontunits", "fontangle", "fontname", "fontsize", ... + "fontweight", "interpreter"}; + tprops(2:2:12) = get (hax, tprops(1:2:12)); + + ## The number of points used for a circle + circle_points = 50; + t = linspace (0, 2*pi, circle_points)'; + x = kron (cos (t), rtick); + y = kron (sin (t), rtick); + + ## Draw colored disk under axes at Z-depth = -1 + patch (x(:,end), y(:,end), -ones (circle_points, 1), + get (hax, "color"), "parent", hg); + + ## Plot dotted circles + line (x(:,1:end-1), y(:,1:end-1), lprops{:}, "parent", hg); + + ## Outer circle is drawn solid + line (x(:,end), y(:,end), lprops{:}, "linestyle", "-", "parent", hg); + + ## Add radial labels + [x, y] = pol2cart (0.42 * pi, rtick); + text (x, y, num2cell (rtick), "verticalalignment", "bottom", tprops{:}, + "parent", hg); + + ## add radial lines + s = rtick(end) * sin (ttick * pi / 180); + c = rtick(end) * cos (ttick * pi / 180); + x = [zeros(1, numel (ttick)); c]; + y = [zeros(1, numel (ttick)); s]; + line (x, y, "linestyle", ":", lprops{:}, "parent", hg); + + ## add angular labels + tticklabel = num2cell (ttick); + ## FIXME: This tm factor does not work as fontsize increases + tm = 1.08; + text (tm * c, tm * s, tticklabel, "horizontalalignment", "center", + tprops{:}, "parent", hg); + + lim = 1.1 * rtick(end); + set (hax, "xlim", [-lim, lim], "ylim", [-lim, lim]); + + ## Put polar grid behind or ahead of plot + __update_layer__ (hax, [], hg); + +endfunction + %!demo %! clf; @@ -210,8 +365,25 @@ %!demo %! clf; +%! theta = linspace (0,2*pi,1000); +%! rho = sin (2*theta).*cos (2*theta); +%! polar (theta, rho, '--r'); +%! set (gca, "rtick", 0.1:0.1:0.6, "ttick", 0:20:340); +%! title ('polar() plot with finer grid'); + +%!demo +%! clf; +%! theta = linspace (0,2*pi,1000); +%! rho = sin (2*theta).*cos (2*theta); +%! polar (theta, rho, '--b'); +%! set (gca, "fontsize", 12, "linewidth", 2, "color", [0.8 0.8 0.8]); +%! title ('polar() plot with modified axis appearance'); + +%!demo +%! clf; %! theta = linspace (0,8*pi,1000); %! rho = sin (5/4*theta); %! polar (theta, rho); +%! set (gca, "rtick", 0.2:0.2:1); %! title ('polar() plot'); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/private/__ezplot__.m --- a/scripts/plot/draw/private/__ezplot__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/private/__ezplot__.m Sun May 25 10:29:05 2014 -0700 @@ -448,8 +448,12 @@ axis (hax, domain); elseif (isplot || ispolar) h = feval (pltfunc, hax, X, Z); - if (isplot && ! parametric) - axis (hax, domain); + if (isplot) + if (! parametric) + axis (hax, domain); + else + axis ("equal"); + endif endif elseif (isplot3) if (animate) diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/private/__patch__.m --- a/scripts/plot/draw/private/__patch__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/private/__patch__.m Sun May 25 10:29:05 2014 -0700 @@ -70,7 +70,7 @@ y = varargin{2}; iarg = 4; if (rem (nargin - iarg, 2) == 1) - c = varargin {iarg}; + c = varargin{iarg}; z = varargin{3}; iarg = 5; else @@ -83,7 +83,7 @@ z = []; iarg = 3; if (rem (nargin - iarg, 2) == 1) - c = varargin {iarg}; + c = varargin{iarg}; iarg++; else c = []; @@ -127,7 +127,7 @@ args{9} = "cdata"; args{10} = c; else - error ("patch: color value not valid"); + error ("patch: color data C must be numeric"); endif elseif (isvector (c) && numel (c) == 3) args{7} = "facecolor"; @@ -150,7 +150,7 @@ args{9} = "cdata"; args{10} = c; else - error ("patch: color value not valid"); + error ("patch: Invalid TrueColor data C"); endif else ## Color Vectors @@ -159,18 +159,17 @@ args{8} = "interp"; args{9} = "cdata"; args{10} = []; - elseif (isequal (size (c), size (x)) && isequal (size (c), size (y))) + elseif (size_equal (c, x) && size_equal (c, y)) args{7} = "facecolor"; args{8} = "interp"; args{9} = "cdata"; args{10} = c; else - error ("patch: size of x, y, and c must be equal"); + error ("patch: size of X, Y, and C must be equal"); endif endif elseif (ischar (c) && rem (nargin - iarg, 2) == 0) - ## Assume that any additional argument over an even number is - ## color string. + ## Assume any additional argument over an even number is a color string. args{7} = "facecolor"; args{8} = tolower (c); args{9} = "cdata"; @@ -195,7 +194,7 @@ endif if (!failed) - h = __go_patch__ (p, args {:}); + h = __go_patch__ (p, args{:}); ## Setup listener functions addlistener (h, "xdata", @update_data); @@ -229,19 +228,19 @@ if (idx > nargs) faces = []; else - faces = args {idx}; + faces = args{idx}; endif idx = find (strcmpi (args, "vertices"), 1, "last") + 1; if (idx > nargs) vert = []; else - vert = args {idx}; + vert = args{idx}; endif idx = find (strcmpi (args, "facevertexcdata"), 1, "last") + 1; if (isempty (idx) || idx > nargs) fvc = []; else - fvc = args {idx}; + fvc = args{idx}; endif idx = find (strcmpi (args, "facecolor"), 1, "last") + 1; if (isempty (idx) || idx > nargs) @@ -254,7 +253,7 @@ endif nc = rows (faces); - idx = faces .'; + idx = faces.'; t1 = isnan (idx); for i = find (any (t1)) first_idx_in_column = find (t1(:,i), 1); @@ -273,11 +272,11 @@ else if (columns (fvc) == 3) c = cat (3, reshape (fvc(idx, 1), size (idx)), - reshape (fvc(idx, 2), size (idx)), - reshape (fvc(idx, 3), size (idx))); + reshape (fvc(idx, 2), size (idx)), + reshape (fvc(idx, 3), size (idx))); elseif (isempty (fvc)) c = []; - else ## if (columnns (fvc) == 1) + else ## if (columnns (fvc) == 1) c = permute (fvc(faces), [2, 1]); endif endif @@ -293,25 +292,25 @@ if (idx > nargs) x = []; else - x = args {idx}; + x = args{idx}; endif idx = find (strcmpi (args, "ydata"), 1, "last") + 1; if (idx > nargs) y = []; else - y = args {idx}; + y = args{idx}; endif idx = find (strcmpi (args, "zdata"), 1, "last") + 1; if (isempty (idx) || idx > nargs) z = []; else - z = args {idx}; + z = args{idx}; endif idx = find (strcmpi (args, "cdata"), 1, "last") + 1; if (isempty (idx) || idx > nargs) c = []; else - c = args {idx}; + c = args{idx}; endif idx = find (strcmpi (args, "facecolor"), 1, "last") + 1; if (isempty (idx) || idx > nargs) @@ -328,13 +327,13 @@ nr = nc; nc = 1; endif - if (!isempty (z)) + if (isempty (z)) + vert = [x(:), y(:)]; + else vert = [x(:), y(:), z(:)]; - else - vert = [x(:), y(:)]; endif faces = reshape (1:numel (x), nr, nc); - faces = faces'; + faces = faces.'; if (ndims (c) == 3) fvc = reshape (c, rows (c) * columns (c), size (c, 3)); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/private/__scatter__.m --- a/scripts/plot/draw/private/__scatter__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/private/__scatter__.m Sun May 25 10:29:05 2014 -0700 @@ -84,6 +84,21 @@ c = []; endif + ## Validate inputs + if (nd == 2 && ! size_equal (x, y)) + error ([fcn ": X and Y must have the same size"]); + elseif (nd == 3 && ! size_equal (x, y, z)) + error ([fcn ": X, Y, and Z must have the same size"]); + endif + + if (! isscalar (s) && ! size_equal (x, s)) + error ([fcn ": size of S must match X, Y, and Z"]); + endif + + if (rows (c) > 1 && rows (c) != rows (x)) + error ([fcn ": number of colors in C must match number of points in X"]); + endif + newargs = {}; filled = false; have_marker = false; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/private/__stem__.m --- a/scripts/plot/draw/private/__stem__.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/private/__stem__.m Sun May 25 10:29:05 2014 -0700 @@ -48,6 +48,8 @@ h = []; nx = rows (x); + h_baseline = []; + for i = 1 : columns (x) if (have_z) xt = x(:)'; @@ -90,19 +92,19 @@ __line__ (hax, xt, yt, zt, "color", lc, "linestyle", ls, "parent", hg); __line__ (hax, x, y, z, "color", mc, "linestyle", "none", "marker", ms, "markerfacecolor", fc, "parent", hg); - h_baseline = []; else __line__ (hax, xt, yt, "color", lc, "linestyle", ls, "parent", hg); __line__ (hax, x(:,i), y(:, i), "color", mc, "linestyle", "none", "marker", ms, "markerfacecolor", fc, "parent", hg); + x_axis_range = get (hax, "xlim"); - h_baseline = line (hax, x_axis_range, [0, 0], "color", [0, 0, 0]); - set (h_baseline, "handlevisibility", "off", "xliminclude", "off"); - addlistener (hax, "xlim", @update_xlim); - addproperty ("basevalue", h_baseline, "data", 0); - addlistener (h_baseline, "basevalue", {@update_baseline, 0}); - addlistener (h_baseline, "ydata", {@update_baseline, 1}); - addlistener (h_baseline, "visible", {@update_baseline, 2}); + if (isempty (h_baseline)) + h_baseline = line (hax, x_axis_range, [0, 0], "color", [0, 0, 0]); + set (h_baseline, "handlevisibility", "off", "xliminclude", "off"); + addproperty ("basevalue", h_baseline, "data", 0); + else + set (h_baseline, "xdata", x_axis_range); + endif endif ## Setup the hggroup and listeners. @@ -110,11 +112,6 @@ addproperty ("baseline", hg, "data", h_baseline); addproperty ("basevalue", hg, "data", 0); - if (! have_z) - addlistener (hg, "showbaseline", @show_baseline); - addlistener (hg, "basevalue", @move_baseline); - endif - addproperty ("color", hg, "linecolor", lc); addproperty ("linestyle", hg, "linelinestyle", ls); addproperty ("linewidth", hg, "linelinewidth", 0.5); @@ -146,14 +143,28 @@ ## Matlab property, although Octave does not implement it. addproperty ("hittestarea", hg, "radio", "on|{off}", "off"); - if (! isempty (args)) - set (hg, args{:}); - endif - if (i == 1 && ! isempty (h_baseline)) - set (h_baseline, "parent", get (hg, "parent")); - endif endfor + ## baseline listeners + if (! isempty (h_baseline)) + addlistener (hax, "xlim", @update_xlim); + for hg = h' + addlistener (hg, "showbaseline", @show_baseline); + addlistener (hg, "visible", {@show_baseline, h}); + addlistener (hg, "basevalue", @move_baseline); + endfor + + addlistener (h_baseline, "basevalue", {@update_baseline, 0}); + addlistener (h_baseline, "ydata", {@update_baseline, 1}); + addlistener (h_baseline, "visible", {@update_baseline, 2}); + set (h_baseline, "parent", get (hg(1), "parent")); + endif + + ## property/value pairs + if (! isempty (args)) + set (h, args{:}); + endif + if (! strcmp (hold_state, "add") && have_z) set (hax, "view", [-37.5 30], "xgrid", "on", "ygrid", "on", "zgrid", "on"); @@ -365,8 +376,16 @@ endfor endfunction -function show_baseline (h, ~) - set (get (h, "baseline"), "visible", get (h, "showbaseline")); +function show_baseline (h, ~, hg = []) + if (isempty (hg)) + set (get (h, "baseline"), "visible", get (h, "showbaseline")); + else + if (all (strcmp (get (hg, "visible"), "off"))) + set (get (h, "baseline"), "visible", "off"); + else + set (get (h, "baseline"), "visible", "on"); + endif + endif endfunction function move_baseline (h, ~) @@ -374,6 +393,7 @@ bl = get (h, "baseline"); set (bl, "ydata", [b0, b0]); + set (bl, "basevalue", b0); kids = get (h, "children"); yt = get (h, "ydata")(:)'; diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/shrinkfaces.m --- a/scripts/plot/draw/shrinkfaces.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/shrinkfaces.m Sun May 25 10:29:05 2014 -0700 @@ -23,24 +23,29 @@ ## @deftypefnx {Function File} {@var{nfv} =} shrinkfaces (@var{f}, @var{v}, @var{sf}) ## @deftypefnx {Function File} {[@var{nf}, @var{nv}] =} shrinkfaces (@dots{}) ## -## Reduce the faces area for a given patch, structure or explicit faces -## and points matrices by a scale factor @var{sf}. The structure -## @var{fv} must contain the fields @qcode{"faces"} and @qcode{"vertices"}. -## If the factor @var{sf} is omitted then a default of 0.3 is used. +## Reduce the size of faces in a patch by the shrink factor @var{sf}. +## +## The patch object can be specified by a graphics handle (@var{p}), a patch +## structure (@var{fv}) with the fields @qcode{"faces"} and @qcode{"vertices"}, +## or as two separate matrices (@var{f}, @var{v}) of faces and vertices. ## -## Given a patch handle as the first input argument and no output -## parameters, perform the shrinking of the patch faces in place and -## redraw the patch. +## The shrink factor @var{sf} is a positive number specifying the percentage +## of the original area the new face will occupy. If no factor is given the +## default is 0.3 (a reduction to 30% of the original size). A factor greater +## than 1.0 will result in the expansion of faces. +## +## Given a patch handle as the first input argument and no output parameters, +## perform the shrinking of the patch faces in place and redraw the patch. ## ## If called with one output argument, return a structure with fields ## @qcode{"faces"}, @qcode{"vertices"}, and @qcode{"facevertexcdata"} -## containing the data after shrinking which can then directly be used as an -## input argument for the @code{patch} function. +## containing the data after shrinking. This structure can be used directly +## as an input argument to the @code{patch} function. ## -## Performing the shrinking on faces which are not convex can lead to -## undesired results. +## @strong{Caution:}: Performing the shrink operation on faces which are not +## convex can lead to undesirable results. ## -## For example, +## Example: a triangulated 3/4 circle and the corresponding shrunken version. ## ## @example ## @group @@ -56,9 +61,6 @@ ## @end group ## @end example ## -## @noindent -## draws a triangulated 3/4 circle and the corresponding shrunken -## version. ## @seealso{patch} ## @end deftypefn @@ -71,8 +73,8 @@ endif sf = 0.3; + colors = []; p = varargin{1}; - colors = []; if (ishandle (p) && nargin < 3) faces = get (p, "Faces"); @@ -104,8 +106,8 @@ error ("shrinkfaces: scale factor must be a positive scalar"); endif - n = columns (vertices); - if (n < 2 || n > 3) + nc = columns (vertices); + if (nc < 2 || nc > 3) error ("shrinkfaces: only 2-D and 3-D patches are supported"); endif @@ -120,14 +122,12 @@ elseif (rows (colors) == rows (vertices)) c = colors(faces'(:), :); else - ## Discard inconsistent color data. - c = []; + c = []; # Discard inconsistent color data. endif sv = rows (v); - ## we have to deal with a probably very large number of vertices, so - ## use sparse we use as midpoint (1/m, ..., 1/m) in generalized - ## barycentric coordinates. - midpoints = full (kron ( speye (sv / m), ones (m, m) / m) * sparse (v)); + ## We have to deal with a possibly very large number of vertices, so use + ## sparse as midpoint (1/m, ..., 1/m) in generalized barycentric coordinates. + midpoints = full (kron (speye (sv / m), ones (m, m) / m) * sparse (v)); v = sqrt (sf) * (v - midpoints) + midpoints; f = reshape (1:sv, m, sv / m)'; @@ -216,3 +216,13 @@ %!assert (size (nfv.vertices), [3 3]) %!assert (norm (nfv2.vertices - vertices), 0, 2*eps) +%% Test input validation +%!error shrinkfaces () +%!error shrinkfaces (1,2,3,4) +%!error [a,b,c] = shrinkfaces (1) +%!error shrinkfaces (nfv, ones (2)) +%!error shrinkfaces (nfv, 0) +%!error shrinkfaces (faces, ones (3,1)) +%!error shrinkfaces (faces, ones (3,4)) +%!error shrinkfaces (faces(1:2), vertices) + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/stem.m --- a/scripts/plot/draw/stem.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/stem.m Sun May 25 10:29:05 2014 -0700 @@ -187,7 +187,7 @@ %! y = [sin(x), cos(x)]; %! h = stem (x, y); %! set (h(2), 'color', 'g'); -%! set (h(1), 'basevalue', -1); +%! set (h(1), 'basevalue', -0.75); %! title ('stem plots modified through hggroup handle'); %!demo @@ -213,3 +213,18 @@ %!error stem (ones (2,2), ones (3,3)) %!error stem (1, "FOO") +%!test +%! ## stemseries share the same baseline and basevalue +%! hf = figure ("visible", "off"); +%! unwind_protect +%! h = stem ([1 2; 1.5 2.5], [1 1;2 2]); +%! assert (get (h(1), "baseline"), get (h(2), "baseline")) +%! bv = 0.3; +%! set (h(1), "basevalue", bv) +%! assert (get (get (h(1), "baseline"), "basevalue"), bv) +%! assert (get (h(1), "basevalue"), bv) +%! assert (get (h(2), "basevalue"), bv) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/stemleaf.m --- a/scripts/plot/draw/stemleaf.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/stemleaf.m Sun May 25 10:29:05 2014 -0700 @@ -185,7 +185,7 @@ hl = xs(hlidx); # lower hinge hu = xs(huidx); # upper hinge h_spread = hu - hl; # h_spread: difference between hinges - step = 1.5*h_spread; # step: 1.5 * h_spread + step = fix(1.5*h_spread); # step: 1.5 * h_spread i_fence_l = hl - step; # inner fences: outside hinges + step o_fence_l = hl - 2*step; # outer fences: outside hinges + 2*step i_fence_h = hu + step; @@ -349,13 +349,13 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " #138|___________________" , -%! " M 69| 52 |" , +%! " #138|___________________" , +%! " M 69| 52 |" , %! " H 35| 30 116| 86" , %! " 1 | -28 146|" , %! " _______" , %! " ______| 129|_______" , -%! " f| -99 245|" , +%! " f| -99 245|" , %! " | 0 0| out" , %! " F| -228 374|" , %! " | 0 0| far" , @@ -389,13 +389,13 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " # 14|___________________" , -%! " M 7| 22 |" , +%! " # 14|___________________" , +%! " M 7| 22 |" , %! " H 4| 12 42| 30" , %! " 1 | 5 52|" , %! " _______" , %! " ______| 45|_______" , -%! " f| -33 87|" , +%! " f| -33 87|" , %! " | 0 0| out" , %! " F| -78 132|" , %! " | 0 0| far" , @@ -418,13 +418,13 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " # 14|___________________" , -%! " M 7| -28 |" , +%! " # 14|___________________" , +%! " M 7| -28 |" , %! " H 4| -42 -12| 30" , %! " 1 | -52 -5|" , %! " _______" , %! " ______| 45|_______" , -%! " f| -87 33|" , +%! " f| -87 33|" , %! " | 0 0| out" , %! " F| -132 78|" , %! " | 0 0| far" , @@ -446,15 +446,15 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " # 15|___________________" , -%! " M 8| 22 |" , +%! " # 15|___________________" , +%! " M 8| 22 |" , %! " H 4| 11 42| 31" , %! " 1 | 0 52|" , %! " _______" , %! " ______| 46|_______" , -%! " f| -35 88|" , +%! " f| -35 88|" , %! " | 0 0| out" , -%! " F| -82 135|" , +%! " F| -81 134|" , %! " | 0 0| far" , %! " " , %! " 0 | 20" , @@ -475,15 +475,15 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " # 15|___________________" , -%! " M 8| -22 |" , +%! " # 15|___________________" , +%! " M 8| -22 |" , %! " H 4| -42 -11| 31" , %! " 1 | -52 0|" , %! " _______" , %! " ______| 46|_______" , -%! " f| -88 35|" , +%! " f| -88 35|" , %! " | 0 0| out" , -%! " F| -135 82|" , +%! " F| -134 81|" , %! " | 0 0| far" , %! " " , %! " -5 | 2" , @@ -503,15 +503,15 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " # 5|___________________" , -%! " M 3| 0 |" , +%! " # 5|___________________" , +%! " M 3| 0 |" , %! " H 2| -7 0| 7" , %! " 1 | -9 0|" , %! " _______" , %! " ______| 10|_______" , -%! " f| -17 10|" , +%! " f| -17 10|" , %! " | 0 0| out" , -%! " F| -28 21|" , +%! " F| -27 20|" , %! " | 0 0| far" , %! " " , %! " -0 | 9700" , @@ -527,15 +527,15 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " # 4|___________________" , -%! " M 2| -7 |" , +%! " # 4|___________________" , +%! " M 2| -7 |" , %! " H 1| -9 0| 9" , %! " 1 | -9 0|" , %! " _______" , %! " ______| 13|_______" , -%! " f| -22 13|" , +%! " f| -22 13|" , %! " | 0 0| out" , -%! " F| -36 27|" , +%! " F| -35 26|" , %! " | 0 0| far" , %! " " , %! " -0 | 970" , @@ -552,7 +552,7 @@ %! " " , %! " Fenced Letter Display" , %! " " , -%! " # 17|___________________" , +%! " # 17|___________________" , %! " M 9| 895 |" , %! " H 5| 795 1499| 704" , %! " 1 | 150 1995|" , diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/surface.m --- a/scripts/plot/draw/surface.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/surface.m Sun May 25 10:29:05 2014 -0700 @@ -73,109 +73,110 @@ h = 0; bad_usage = false; - firststring = nargin; - for i = 1 : (nargin - 1) - if (ischar (varargin{i})) - firststring = i; - break; - endif - endfor + firststring = find (cellfun ("isclass", varargin, "char"), 1); + if (isempty (firststring)) + firststring = nargin; + endif - if (firststring > 5) - bad_usage = true; - return; - elseif (firststring == 5) - x = varargin{1}; - y = varargin{2}; - z = varargin{3}; - c = varargin{4}; + switch (firststring) + case 5 + x = varargin{1}; + y = varargin{2}; + z = varargin{3}; + c = varargin{4}; - if (iscomplex (x) || iscomplex (y) || iscomplex (z) || iscomplex (c)) - error ("mesh: X, Y, Z, C arguments must be real"); - endif + if (iscomplex (x) || iscomplex (y) || iscomplex (z) || iscomplex (c)) + error ("mesh: X, Y, Z, C arguments must be real"); + endif + + [z_nr, z_nc] = size (z); + [c_nr, c_nc, c_np] = size (c); + if (! (z_nr == c_nr && z_nc == c_nc && (c_np == 1 || c_np == 3))) + error ("surface: Z and C must have the same size"); + endif - [z_nr, z_nc] = size (z); - [c_nr, c_nc, c_np] = size (c); - if (! (z_nr == c_nr && z_nc == c_nc && (c_np == 1 || c_np == 3))) - error ("surface: Z and C must have the same size"); - endif - - if (isvector (x) && isvector (y) && ismatrix (z)) - if (rows (z) == length (y) && columns (z) == length (x)) - x = x(:)'; - y = y(:); + if (isvector (x) && isvector (y) && ismatrix (z)) + if (rows (z) == length (y) && columns (z) == length (x)) + x = x(:)'; + y = y(:); + else + error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)"); + endif + elseif (ismatrix (x) && ismatrix (y) && ismatrix (z)) + if (! size_equal (x, y, z)) + error ("surface: X, Y, and Z must have the same dimensions"); + endif else - error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)"); + error ("surface: X and Y must be vectors and Z must be a matrix"); endif - elseif (ismatrix (x) && ismatrix (y) && ismatrix (z)) - if (! size_equal (x, y, z)) - error ("surface: X, Y, and Z must have the same dimensions"); + + case 4 + x = varargin{1}; + y = varargin{2}; + z = varargin{3}; + c = z; + + if (iscomplex (x) || iscomplex (y) || iscomplex (z)) + error ("mesh: X, Y, Z arguments must be real"); endif - else - error ("surface: X and Y must be vectors and Z must be a matrix"); - endif - elseif (firststring == 4) - x = varargin{1}; - y = varargin{2}; - z = varargin{3}; - c = z; - - if (iscomplex (x) || iscomplex (y) || iscomplex (z)) - error ("mesh: X, Y, Z arguments must be real"); - endif - if (isvector (x) && isvector (y) && ismatrix (z)) - if (rows (z) == length (y) && columns (z) == length (x)) - x = x(:)'; - y = y(:); + if (isvector (x) && isvector (y) && ismatrix (z)) + if (rows (z) == length (y) && columns (z) == length (x)) + x = x(:)'; + y = y(:); + else + error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)"); + endif + elseif (ismatrix (x) && ismatrix (y) && ismatrix (z)) + if (! size_equal (x, y, z)) + error ("surface: X, Y, and Z must have the same dimensions"); + endif else - error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)"); - endif - elseif (ismatrix (x) && ismatrix (y) && ismatrix (z)) - if (! size_equal (x, y, z)) - error ("surface: X, Y, and Z must have the same dimensions"); + error ("surface: X and Y must be vectors and Z must be a matrix"); endif - else - error ("surface: X and Y must be vectors and Z must be a matrix"); - endif - elseif (firststring == 3) - z = varargin{1}; - c = varargin{2}; - if (iscomplex (z) || iscomplex (c)) - error ("mesh: X, C arguments must be real"); - endif + case 3 + z = varargin{1}; + c = varargin{2}; + + if (iscomplex (z) || iscomplex (c)) + error ("mesh: X, C arguments must be real"); + endif - if (ismatrix (z) && !isvector (z) && !isscalar (z)) - [nr, nc] = size (z); - x = 1:nc; - y = (1:nr)'; - else - error ("surface: Z argument must be a matrix"); - endif - elseif (firststring == 2) - z = varargin{1}; - c = z; + if (ismatrix (z) && !isvector (z) && !isscalar (z)) + [nr, nc] = size (z); + x = 1:nc; + y = (1:nr)'; + else + error ("surface: Z argument must be a matrix"); + endif - if (iscomplex (z)) - error ("mesh: Z argument must be real"); - endif + case 2 + z = varargin{1}; + c = z; + + if (iscomplex (z)) + error ("mesh: Z argument must be real"); + endif - if (ismatrix (z) && !isvector (z) && !isscalar (z)) - [nr, nc] = size (z); - x = 1:nc; - y = (1:nr)'; - else - error ("surface: Z argument must be a matrix"); - endif - elseif (firststring == 1) - x = 1:3; - y = x'; - c = z = eye (3); - else - bad_usage = true; - return; - endif + if (ismatrix (z) && !isvector (z) && !isscalar (z)) + [nr, nc] = size (z); + x = 1:nc; + y = (1:nr)'; + else + error ("surface: Z argument must be a matrix"); + endif + + case 1 + x = 1:3; + y = x'; + c = z = eye (3); + + otherwise + bad_usage = true; + return; + + endswitch if (firststring < nargin) other_args = varargin(firststring:end); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/draw/surfl.m --- a/scripts/plot/draw/surfl.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/draw/surfl.m Sun May 25 10:29:05 2014 -0700 @@ -164,7 +164,7 @@ endif vn = get (htmp, "vertexnormals"); - dar = get (hax, "plotboxaspectratio"); + dar = get (hax, "dataaspectratio"); vn(:,:,1) *= dar(1); vn(:,:,2) *= dar(2); vn(:,:,3) *= dar(3); @@ -206,8 +206,7 @@ %! clf; %! [X,Y,Z] = sombrero (); %! colormap (copper (64)); -%! [az, el] = view (); -%! surfl (X,Y,Z, [az+225,el], [0.2 0.6 0.4 25]); +%! surfl (X,Y,Z, [62.50,30], [0.2 0.6 0.4 25]); %! shading interp; %! title ('surfl() with lighting vector and material properties'); diff -r bd1fd4ed3d67 -r 888f8ce79bbe scripts/plot/util/colstyle.m --- a/scripts/plot/util/colstyle.m Sun May 25 10:26:18 2014 -0700 +++ b/scripts/plot/util/colstyle.m Sun May 25 10:29:05 2014 -0700 @@ -36,10 +36,7 @@ try opt = __pltopt__ ("colstyle", style); l = opt.linestyle; - c = opt.color; - m = opt.marker; - msg = []; - switch (c) + switch (opt.color) case [0 0 0] c = "k"; case [1 0 0] @@ -56,7 +53,11 @@ c = "c"; case [0 1 1] c = "w"; + otherwise + c = opt.color; endswitch + m = opt.marker; + msg = []; catch l = c = m = []; msg = lasterr (); @@ -86,5 +87,5 @@ %% Test input validation %!error colstyle () %!error colstyle (1, 2) -%!error colstyle (1.5) +%!error