# HG changeset patch # User John W. Eaton # Date 1406909405 14400 # Node ID dcb260e7a6487e6001bba12d5c0e10b82598861f # Parent 19cb2530c16bce44cda6b3ccdb63517a0c3ce9d1# Parent c59745865c7f6656ebd4898e07d6e46746640ef9 maint: Periodic merge of gui-release to default. diff -r c59745865c7f -r dcb260e7a648 Makefile.am --- a/Makefile.am Fri Aug 01 09:06:21 2014 -0400 +++ b/Makefile.am Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 NEWS --- a/NEWS Fri Aug 01 09:06:21 2014 -0400 +++ b/NEWS Fri Aug 01 12:10:05 2014 -0400 @@ -1,3 +1,102 @@ +Summary of important user-visible changes for version 4.2: +--------------------------------------------------------- + + ** A new syntax for object oriented programming termed classdef has been + introduced. See the manual for more extensive documentation of the + classdef interface. + + New keywords: + + classdef endclassdef + enumeration endenumeration + events endevents + methods endmethods + properties endproperties + + ** 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'. + + ** Z-order stacking issues with patches, grid lines, and line object + plot markers for on screen display and printing have all been resolved. + For 2-D plots the axis grid lines can be placed on top of the plot + with set (gca, "layer", "top"). + + ** The patch graphic object has been overhauled. It now produces visual + results equivalent to Matlab even for esoteric combinations of + faces/vertices/cdata. + + ** The polar() plot function now draws a circular theta axis and + radial rho axis rather than using a rectangular x/y axis. + + ** 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: + + bandwidth isbanded javachk + dir_in_loadpath isdiag linkaxes + hgload istril numfields + hgsave istriu + + ** 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_unsigned_conversion + interp1q javafields + isequalwithequalnans javamethods + java_convert_matrix re_read_readline_init_file + java_debug 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 +126,7 @@ ** Other new functions added in 4.0.0: - validateattributes + validateattributes ** Deprecated functions. diff -r c59745865c7f -r dcb260e7a648 bootstrap.conf --- a/bootstrap.conf Fri Aug 01 09:06:21 2014 -0400 +++ b/bootstrap.conf Fri Aug 01 12:10:05 2014 -0400 @@ -50,10 +50,12 @@ isatty largefile link + log log2 log2-ieee log2f log2f-ieee + logf lstat malloc-gnu mbrtowc @@ -66,8 +68,8 @@ open opendir pathmax + progname putenv - progname readdir readlink realloc-gnu diff -r c59745865c7f -r dcb260e7a648 build-aux/common.mk --- a/build-aux/common.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/build-aux/common.mk Fri Aug 01 12:10:05 2014 -0400 @@ -108,8 +108,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@ @@ -132,8 +130,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@ @@ -519,7 +515,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 c59745865c7f -r dcb260e7a648 configure.ac --- a/configure.ac Fri Aug 01 09:06:21 2014 -0400 +++ b/configure.ac Fri Aug 01 12:10:05 2014 -0400 @@ -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. @@ -865,9 +857,13 @@ warn_llvm="Missing LLVM file TargetData.h. JIT compiler is disabled." fi + AC_CHECK_HEADERS([llvm/IR/Verifier.h]) + OCTAVE_LLVM_FUNCTION_ADDATTRIBUTE_API OCTAVE_LLVM_FUNCTION_ADDFNATTR_API OCTAVE_LLVM_CALLINST_ADDATTRIBUTE_API + OCTAVE_LLVM_RAW_FD_OSTREAM_API + OCTAVE_LLVM_LEGACY_PASSMANAGER_API AC_LANG_POP(C++) CPPFLAGS="$save_CPPFLAGS" CXXFLAGS="$save_CXXFLAGS" @@ -895,6 +891,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 +2183,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]) @@ -2847,7 +2844,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 c59745865c7f -r dcb260e7a648 doc/interpreter/container.txi --- a/doc/interpreter/container.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/container.txi Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 doc/interpreter/contrib.txi --- a/doc/interpreter/contrib.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/contrib.txi Fri Aug 01 12:10:05 2014 -0400 @@ -284,8 +284,10 @@ An exception are matrix or cell constructors: @example +@group [sin(x), cos(x)] @{sin(x), cos(x)@} +@end group @end example @noindent diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/contributors.in --- a/doc/interpreter/contributors.in Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/contributors.in Fri Aug 01 12:10:05 2014 -0400 @@ -3,6 +3,7 @@ Adam H. Aitkenhead Giles Anderson Joel Andersson +Pedro Angelo Muthiah Annamalai Markus Appel Branden Archer @@ -15,6 +16,7 @@ Heinz Bauschke Julien Bect Roman Belov +Markus Bergholz Karl Berry David Billinghurst Don Bindner @@ -69,6 +71,7 @@ Peter Ekberg Rolf Fabian Gunnar Farnebäck +Massimiliano Fasi Stephen Fegan Ramon Garcia Fernandez Torsten Finke @@ -80,6 +83,7 @@ Walter Gautschi Klaus Gebhardt Driss Ghaddab +Eugenio Gianniti Nicolo Giorgetti Arun Giridhar Michael D. Godfrey @@ -88,6 +92,7 @@ Tomislav Goles Keith Goodman Brian Gough +Michael C. Grant Steffen Groot Etienne Grossmann David Grundberg @@ -119,6 +124,7 @@ John Hunt Teemu Ikonen Alan W. Irwin +Allan Jacobs Geoff Jacobsen Mats Jansson Cai Jianming @@ -188,6 +194,7 @@ Júlio Hoffimann Mendes Ed Meyer Thorsten Meyer +Stefan Miereis Petr Mikulik Mike Miller Stefan Monnier @@ -210,12 +217,14 @@ Michael O'Brien Peter O'Gorman Thorsten Ohl +Kai T. Ohlhus Arno Onken Valentin Ortega-Clavero Luis F. Ortiz Carl Osterwisch Janne Olavi Paanajärvi Scott Pakin +Jason Alan Palmer Gabriele Pannocchia Sylvain Pelissier Per Persson @@ -234,6 +243,7 @@ Francesco Potortì Konstantinos Poulios Jarno Rajahalme +Eduardo Ramos James B. Rawlings Eric S. Raymond Balint Reczey @@ -266,6 +276,7 @@ Julian Schnidder Nicol N. Schraudolph Sebastian Schubert +Lasse Schuirmann Ludwig Schwardt Thomas L. Scofield Daniel J. Sebald @@ -282,6 +293,7 @@ Joerg Specht Quentin H. Spencer Christoph Spiel +David Spies Richard Stallman Russell Standish Brett Stewart @@ -325,6 +337,7 @@ Martin Weiser Michael Weitzel David Wells +Joachim Wiesemann Fook Fah Yap Sean Young Michael Zeising diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/diagperm.txi --- a/doc/interpreter/diagperm.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/diagperm.txi Fri Aug 01 12:10:05 2014 -0400 @@ -489,21 +489,18 @@ right and the consequent usage of smarter algorithms for certain operations implies, as a side effect, small differences in treating zeros. The contents of this section apply also to sparse matrices, discussed in -the following chapter. (@pxref{Sparse Matrices}) +the following chapter. (@pxref{Sparse Matrices}) -The IEEE floating point standard defines the result of the expressions @code{0*Inf} and -@code{0*NaN} as @code{NaN}. This is widely agreed to be a good -compromise. -Numerical software dealing with structured and sparse matrices (including -Octave) however, almost always makes a distinction between a "numerical zero" -and an "assumed zero". -A "numerical zero" is a zero value occurring in a place where any floating-point -value could occur. It is normally stored somewhere in memory as an explicit -value. -An "assumed zero", on the contrary, is a zero matrix element implied by the -matrix structure (diagonal, triangular) or a sparsity pattern; its value is -usually not stored explicitly anywhere, but is implied by the underlying -data structure. +The IEEE floating point standard defines the result of the expressions +@code{0*Inf} and @code{0*NaN} as @code{NaN}. This is widely agreed to be a +good compromise. Numerical software dealing with structured and sparse matrices +(including Octave) however, almost always makes a distinction between a +"numerical zero" and an "assumed zero". A "numerical zero" is a zero value +occurring in a place where any floating-point value could occur. It is +normally stored somewhere in memory as an explicit value. An "assumed zero", on +the contrary, is a zero matrix element implied by the matrix structure +(diagonal, triangular) or a sparsity pattern; its value is usually not stored +explicitly anywhere, but is implied by the underlying data structure. The primary distinction is that an assumed zero, when multiplied by any number, or divided by any nonzero number, diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/doccheck/aspell-octave.en.pws --- a/doc/interpreter/doccheck/aspell-octave.en.pws Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/doccheck/aspell-octave.en.pws Fri Aug 01 12:10:05 2014 -0400 @@ -52,6 +52,7 @@ backend Backends backends +backtrace bartlett BaseValue basevalue @@ -235,6 +236,7 @@ dMatrix dmperm Dobkin +docstring docstrings dOmega doNotSpecify @@ -387,6 +389,7 @@ goto Goto gotos +gperf GPL GPLK gplot @@ -499,6 +502,7 @@ javaaddpath javamem jbig +JDK JIT jpeg JPEG @@ -678,8 +682,10 @@ nbininv nbinpdf nbinrnd +ncols nd ndgrid +ndims ne Nelder neq @@ -700,7 +706,11 @@ nolabel noncommercially nonconformant +nondecreasing +nonincreasing +nonnan nonsmooth +nonsparse nonzeros NOP noperm @@ -713,9 +723,11 @@ noscal noshare notin +nrows nthargout NTSC ntsc +numel Numpy nzmax oct @@ -726,6 +738,7 @@ onCleanup online OpenGL +OpenJDK oplus Oppenheim Ord @@ -1166,6 +1179,7 @@ wp wspace xb +xboxes xc xcorr xdata @@ -1188,9 +1202,11 @@ xu xwd xy +xyboxes xyerrorbar xyerrorbars xyz +yboxes yc ydata yerrorbar diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/errors.txi --- a/doc/interpreter/errors.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/errors.txi Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 doc/interpreter/external.txi --- a/doc/interpreter/external.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/external.txi Fri Aug 01 12:10:05 2014 -0400 @@ -589,7 +589,7 @@ @subsubsection Array and Sparse Class Differences The number of elements in a sparse matrix is considered to be the number -of non-zero elements rather than the product of the dimensions. Therefore +of nonzero elements rather than the product of the dimensions. Therefore @example @group @@ -600,13 +600,13 @@ @end example @noindent -returns the number of non-zero elements. If the user really requires the -number of elements in the matrix, including the non-zero elements, they +returns the number of nonzero elements. If the user really requires the +number of elements in the matrix, including the nonzero elements, they should use @code{numel} rather than @code{nelem}. Note that for very large matrices, where the product of the two dimensions is larger than the representation of an unsigned int, then @code{numel} can overflow. An example is @code{speye (1e6)} which will create a matrix with a million -rows and columns, but only a million non-zero elements. Therefore the +rows and columns, but only a million nonzero elements. Therefore the number of rows by the number of columns in this case is more than two hundred times the maximum value that can be represented by an unsigned int. The use of @code{numel} should therefore be avoided useless it is known @@ -707,7 +707,7 @@ technique for creating a sparse matrix. The alternative is to first create a sparse matrix with the desired -number of non-zero elements and then later fill those elements in. +number of nonzero elements and then later fill those elements in. Sample code: @example @@ -748,7 +748,7 @@ @var{nz} greater than 4 is also valid. The disadvantage is that the matrix occupies more memory than strictly needed. -It is not always possible to know the number of non-zero elements prior +It is not always possible to know the number of nonzero elements prior to filling a matrix. For this reason the additional unused storage of a sparse matrix can be removed after its creation with the @code{maybe_compress} function. In addition, @code{maybe_compress} can @@ -850,7 +850,7 @@ sm.maybe_mutate (); // If don't know a priori the final # of nz. @end example -Note that both increasing and decreasing the number of non-zero elements in +Note that both increasing and decreasing the number of nonzero elements in a sparse matrix is expensive as it involves memory reallocation. Also as parts of the matrix, though not its entirety, exist as old and new copies at the same time, additional memory is needed. Therefore, if possible this @@ -1607,6 +1607,7 @@ An example of the behavior of this function within Octave is then @example +@group a(1).f1 = "f11"; a(1).f2 = "f12"; a(2).f1 = "f21"; a(2).f2 = "f22"; b = mystruct (a); @@ -1625,6 +1626,7 @@ this = this3 that = that3 +@end group @end example @node Sparse Matrices with Mex-Files @@ -1653,11 +1655,11 @@ @noindent @code{mxGetNzmax} gets the maximum number of elements that can be stored -in the sparse matrix. This is not necessarily the number of non-zero +in the sparse matrix. This is not necessarily the number of nonzero elements in the sparse matrix. @code{mxGetJc} returns an array with one additional value than the number of columns in the sparse matrix. The difference between consecutive values of the array returned by -@code{mxGetJc} define the number of non-zero elements in each column of +@code{mxGetJc} define the number of nonzero elements in each column of the sparse matrix. Therefore, @example @@ -1673,10 +1675,10 @@ @end example @noindent -returns the actual number of non-zero elements stored in the matrix in +returns the actual number of nonzero elements stored in the matrix in @code{nz}. As the arrays returned by @code{mxGetPr} and @code{mxGetPi} -only contain the non-zero values of the matrix, we also need a pointer -to the rows of the non-zero elements, and this is given by +only contain the nonzero values of the matrix, we also need a pointer +to the rows of the nonzero elements, and this is given by @code{mxGetIr}. A complete example of the use of sparse matrices in mex-files is given by the file @file{mysparse.c} shown below. @@ -1692,7 +1694,7 @@ mysparse (sm) @result{} Matrix is 2-by-2 real sparse matrix with 2 elements -last non-zero element (2, 2) = 3.14159 +last nonzero element (2, 2) = 3.14159 @end group @end example @@ -1790,8 +1792,8 @@ This feature should be used with care as the list of built-in functions can change. No guarantees can be made that a function that is currently built in won't be implemented as a .m file or as a dynamically linked function in the -future. An example of how to call built-in functions from C++ can be seen in the -code +future. An example of how to call built-in functions from C++ can be seen in +the code @example @EXAMPLEFILE(standalonebuiltin.cc) diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/func.txi --- a/doc/interpreter/func.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/func.txi Fri Aug 01 12:10:05 2014 -0400 @@ -802,7 +802,7 @@ @DOCSTRING(command_line_path) -@DOCSTRING(find_dir_in_path) +@DOCSTRING(dir_in_loadpath) @node Subfunctions @subsection Subfunctions diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/grammar.txi --- a/doc/interpreter/grammar.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/grammar.txi Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 doc/interpreter/install.txi --- a/doc/interpreter/install.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/install.txi Fri Aug 01 12:10:05 2014 -0400 @@ -734,6 +734,7 @@ Suggestions on how to compile ATLAS would be most welcome. @item @sc{glpk} + @item Qhull (@url{http://www.qhull.org}) Both @sc{glpk} and Qhull use @code{int} internally so maximum problem @@ -846,7 +847,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 @@ -1026,3 +1027,4 @@ @env{FFLAGS} is set to @qcode{"-O"}. @end itemize + diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/java.txi --- a/doc/interpreter/java.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/java.txi Fri Aug 01 12:10:05 2014 -0400 @@ -163,9 +163,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 c59745865c7f -r dcb260e7a648 doc/interpreter/linalg.txi --- a/doc/interpreter/linalg.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/linalg.txi Fri Aug 01 12:10:05 2014 -0400 @@ -27,12 +27,12 @@ @cite{@sc{lapack} Users' Guide} is available at: @cite{http://www.netlib.org/lapack/lug/} -A common text for engineering courses is G. Strang, @cite{Linear Algebra -and Its Applications, 4th Edition}. It has become a widespread reference -for linear algebra. An alternative is P. Lax @cite{Linear Algebra and -Its Applications}, and also is a good choice. It claims to be suitable -for high school students with substantial mathematical interests as well -as first-year undergraduates. +A common text for engineering courses is @nospell{G. Strang}, +@cite{Linear Algebra and Its Applications, 4th Edition}. It has become a +widespread reference for linear algebra. An alternative is P. Lax +@cite{Linear Algebra and Its Applications}, and also is a good choice. It +claims to be suitable for high school students with substantial mathematical +interests as well as first-year undergraduates. @menu * Techniques Used for Linear Algebra:: @@ -49,7 +49,7 @@ Octave includes a polymorphic solver that selects an appropriate matrix factorization depending on the properties of the matrix itself. Generally, the cost of determining the matrix type is small relative to -the cost of factorizing the matrix itself. In any case the matrix type +the cost of factorizing the matrix itself. In any case the matrix type is cached once it is calculated so that it is not re-determined each time it is used in a linear equation. @@ -96,6 +96,8 @@ @DOCSTRING(balance) +@DOCSTRING(bandwidth) + @DOCSTRING(cond) @DOCSTRING(det) @@ -212,3 +214,4 @@ @DOCSTRING(cgs) @DOCSTRING(gmres) + diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/macros.texi --- a/doc/interpreter/macros.texi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/macros.texi Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 doc/interpreter/numbers.txi --- a/doc/interpreter/numbers.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/numbers.txi Fri Aug 01 12:10:05 2014 -0400 @@ -811,6 +811,8 @@ @DOCSTRING(isnumeric) +@DOCSTRING(islogical) + @DOCSTRING(isfloat) @DOCSTRING(isreal) @@ -835,7 +837,13 @@ @DOCSTRING(isdefinite) -@DOCSTRING(islogical) +@DOCSTRING(isbanded) + +@DOCSTRING(isdiag) + +@DOCSTRING(istril) + +@DOCSTRING(istriu) @DOCSTRING(isprime) diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/plot.txi --- a/doc/interpreter/plot.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/plot.txi Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 doc/interpreter/sparse.txi --- a/doc/interpreter/sparse.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/sparse.txi Fri Aug 01 12:10:05 2014 -0400 @@ -44,13 +44,13 @@ There are many classes of mathematical problems which give rise to matrices, where a large number of the elements are zero. In this case it makes sense to have a special matrix type to handle this class of -problems where only the non-zero elements of the matrix are +problems where only the nonzero elements of the matrix are stored. Not only does this reduce the amount of memory to store the matrix, but it also means that operations on this type of matrix can take advantage of the a priori knowledge of the positions of the -non-zero elements to accelerate their calculations. +nonzero elements to accelerate their calculations. -A matrix type that stores only the non-zero elements is generally called +A matrix type that stores only the nonzero elements is generally called sparse. It is the purpose of this document to discuss the basics of the storage and creation of sparse matrices and the fundamental operations on them. @@ -81,7 +81,7 @@ With full matrices, knowledge of the point of an element of the matrix within the matrix is implied by its position in the computers memory. However, this is not the case for sparse matrices, and so the positions -of the non-zero elements of the matrix must equally be stored. +of the nonzero elements of the matrix must equally be stored. An obvious way to do this is by storing the elements of the matrix as triplets, with two elements being their position in the array @@ -94,9 +94,9 @@ In this format the position of each element in a row and the data are stored as previously. However, if we assume that all elements in the same column are stored adjacent in the computers memory, then we only -need to store information on the number of non-zero elements in each +need to store information on the number of nonzero elements in each column, rather than their positions. Thus assuming that the matrix has -more non-zero elements than there are columns in the matrix, we win in +more nonzero elements than there are columns in the matrix, we win in terms of the amount of memory used. In fact, the column index contains one more element than the number of @@ -109,7 +109,7 @@ @group for (j = 0; j < nc; j++) for (i = cidx(j); i < cidx(j+1); i++) - printf ("non-zero element (%i,%i) is %d\n", + printf ("nonzero element (%i,%i) is %d\n", ridx(i), j, data(i)); @end group @end example @@ -125,7 +125,7 @@ @end group @end example -The non-zero elements of this matrix are +The nonzero elements of this matrix are @example @group @@ -319,7 +319,7 @@ in fact a sparse matrix. Another very basic function is @dfn{nnz} that returns the number of -non-zero entries there are in a sparse matrix, while the function +nonzero entries there are in a sparse matrix, while the function @dfn{nzmax} returns the amount of storage allocated to the sparse matrix. Note that Octave tends to crop unused memory at the first opportunity for sparse objects. There are some cases of user created @@ -376,7 +376,7 @@ There are several graphical means of finding out information about sparse matrices. The first is the @dfn{spy} command, which displays -the structure of the non-zero elements of the +the structure of the nonzero elements of the matrix. @xref{fig:spmatrix}, for an example of the use of @dfn{spy}. More advanced graphical information can be obtained with the @dfn{treeplot}, @dfn{etreeplot} and @dfn{gplot} commands. @@ -390,7 +390,7 @@ interconnections between nodes are represented as an adjacency matrix. That is, if the i-th node in a graph is connected to the j-th node. Then the ij-th node (and in the case of undirected graphs the -@nospell{ji-th} node) of the sparse adjacency matrix is non-zero. If each node +@nospell{ji-th} node) of the sparse adjacency matrix is nonzero. If each node is then associated with a set of coordinates, then the @dfn{gplot} command can be used to graphically display the interconnections between nodes. @@ -509,9 +509,9 @@ The two basic reasons to use sparse matrices are to reduce the memory usage and to not have to do calculations on zero elements. The two are closely related in that the computation time on a sparse matrix operator -or function is roughly linear with the number of non-zero elements. +or function is roughly linear with the number of nonzero elements. -Therefore, there is a certain density of non-zero elements of a matrix +Therefore, there is a certain density of nonzero elements of a matrix where it no longer makes sense to store it as a sparse matrix, but rather as a full matrix. For this reason operators and functions that have a high probability of returning a full matrix will always return one. For @@ -630,7 +630,7 @@ of zero is important must not be done using sparse matrices. In general any function or operator used on a sparse matrix will -result in a sparse matrix with the same or a larger number of non-zero +result in a sparse matrix with the same or a larger number of nonzero elements than the original matrix. This is particularly true for the important case of sparse matrix factorizations. The usual way to address this is to reorder the matrix, such that its factorization is @@ -667,7 +667,7 @@ @ifset htmltex 598 @end ifset -non-zero terms, while this Cholesky@tie{}factorization has +nonzero terms, while this Cholesky@tie{}factorization has @ifinfo @ifnothtml 71, @@ -693,7 +693,7 @@ @ifset htmltex 399 @end ifset -non-zero terms which is a significant improvement. +nonzero terms which is a significant improvement. The Cholesky@tie{}factorization itself can be used to determine the appropriate sparsity preserving reordering of the matrix during the @@ -793,12 +793,12 @@ @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 -The band density is defined as the number of non-zero values in the band +The band density is defined as the number of nonzero values in the band divided by the total number of values in the full band. The banded matrix solvers can be entirely disabled by using @dfn{spparms} to set @code{bandden} to 1 (i.e., @code{spparms ("bandden", 1)}). @@ -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 c59745865c7f -r dcb260e7a648 doc/interpreter/stmt.txi --- a/doc/interpreter/stmt.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/stmt.txi Fri Aug 01 12:10:05 2014 -0400 @@ -83,10 +83,10 @@ @var{condition} is true. The condition in an @code{if} statement is considered true if its value -is non-zero, and false if its value is zero. If the value of the +is nonzero, and false if its value is zero. If the value of the conditional expression in an @code{if} statement is a vector or a matrix, it is considered true only if it is non-empty and @emph{all} -of the elements are non-zero. +of the elements are nonzero. The second form of an if statement looks like this: @@ -398,10 +398,10 @@ The @code{while} statement is the simplest looping statement in Octave. It repeatedly executes a statement as long as a condition is true. As with the condition in an @code{if} statement, the condition in a -@code{while} statement is considered true if its value is non-zero, and +@code{while} statement is considered true if its value is nonzero, and false if its value is zero. If the value of the conditional expression in a @code{while} statement is a vector or a matrix, it is considered -true only if it is non-empty and @emph{all} of the elements are non-zero. +true only if it is non-empty and @emph{all} of the elements are nonzero. Octave's @code{while} statement looks like this: @@ -463,10 +463,10 @@ true, and the test of the condition is at the end of the loop, so the body of the loop is always executed at least once. As with the condition in an @code{if} statement, the condition in a @code{do-until} -statement is considered true if its value is non-zero, and false if its +statement is considered true if its value is nonzero, and false if its value is zero. If the value of the conditional expression in a @code{do-until} statement is a vector or a matrix, it is considered -true only if it is non-empty and @emph{all} of the elements are non-zero. +true only if it is non-empty and @emph{all} of the elements are nonzero. Octave's @code{do-until} statement looks like this: diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/testfun.txi --- a/doc/interpreter/testfun.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/testfun.txi Fri Aug 01 12:10:05 2014 -0400 @@ -297,14 +297,14 @@ @group function output = must_be_zero (@var{input}) if (@var{input} != 0) - error ("Non-zero input!") + error ("Nonzero input!") endif output = input; endfunction %!fail ("must_be_zero (1)"); %!assert (must_be_zero (0), 0); -%!error must_be_zero (1); +%!error must_be_zero (1); %!xtest error ("This code generates an error"); @end group @end example @@ -320,7 +320,7 @@ >>>>> /path/to/must_be_zero.m ***** fail ("must_be_zero (1)"); ***** assert (must_be_zero (0), 0); - ***** error must_be_zero (1); + ***** error must_be_zero (1); ***** xtest error ("This code generates an error"); !!!!! known failure This code generates an error diff -r c59745865c7f -r dcb260e7a648 doc/interpreter/var.txi --- a/doc/interpreter/var.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/var.txi Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 doc/interpreter/vectorize.txi --- a/doc/interpreter/vectorize.txi Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/interpreter/vectorize.txi Fri Aug 01 12:10:05 2014 -0400 @@ -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 @@ -713,3 +713,4 @@ a column vector. This is a common vectorization trick. @end itemize + diff -r c59745865c7f -r dcb260e7a648 doc/refcard/refcard.tex --- a/doc/refcard/refcard.tex Fri Aug 01 09:06:21 2014 -0400 +++ b/doc/refcard/refcard.tex Fri Aug 01 12:10:05 2014 -0400 @@ -536,7 +536,7 @@ speye ({\it n)}&create sparse identity matrix.\cr sprand ({\it n}, {\it m}, {\it d})&sparse rand matrix of density {\it d}.\cr spdiags (...)&sparse generalization of {\it diag}.\cr -nnz ({\it s})&No. non-zero elements in sparse matrix.\cr +nnz ({\it s})&No. nonzero elements in sparse matrix.\cr \endsec \sec Ranges; diff -r c59745865c7f -r dcb260e7a648 examples/mysparse.c --- a/examples/mysparse.c Fri Aug 01 09:06:21 2014 -0400 +++ b/examples/mysparse.c Fri Aug 01 12:10:05 2014 -0400 @@ -32,7 +32,7 @@ i = n; while (jc[i] == jc[i-1] && i != 0) i--; - mexPrintf ("last non-zero element (%d, %d) = (%g, %g)\n", + mexPrintf ("last nonzero element (%d, %d) = (%g, %g)\n", ir[nz-1]+ 1, i, pr[nz-1], pi[nz-1]); v = mxCreateSparse (m, n, nz, mxCOMPLEX); @@ -65,7 +65,7 @@ i = n; while (jc[i] == jc[i-1] && i != 0) i--; - mexPrintf ("last non-zero element (%d, %d) = %d\n", + mexPrintf ("last nonzero element (%d, %d) = %d\n", ir[nz-1]+ 1, i, pbr[nz-1]); v = mxCreateSparseLogicalMatrix (m, n, nz); @@ -95,7 +95,7 @@ i = n; while (jc[i] == jc[i-1] && i != 0) i--; - mexPrintf ("last non-zero element (%d, %d) = %g\n", + mexPrintf ("last nonzero element (%d, %d) = %g\n", ir[nz-1]+ 1, i, pr[nz-1]); v = mxCreateSparse (m, n, nz, mxREAL); diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/Backend.cc --- a/libgui/graphics/Backend.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Backend.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 tmp (reinterpret_cast (proxy)); + gObj.get_properties ().set(toolkitObjectProperty (go), tmp); 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 c59745865c7f -r dcb260e7a648 libgui/graphics/BaseControl.cc --- a/libgui/graphics/BaseControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/BaseControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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: @@ -147,62 +147,62 @@ } } -bool BaseControl::eventFilter (QObject* watched, QEvent* event) +bool BaseControl::eventFilter (QObject* watched, QEvent* xevent) { - switch (event->type ()) + switch (xevent->type ()) { 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 (xevent); + 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 (xevent); + graphics_object go = object (); + graphics_object fig = go.get_ancestor ("figure"); gh_manager::post_set (fig.get_handle (), "currentpoint", Utils::figureCurrentPoint (fig, m), false); @@ -215,7 +215,7 @@ gh_manager::auto_lock lock; octave_scalar_map keyData = - Utils::makeKeyEventStruct (dynamic_cast (event)); + Utils::makeKeyEventStruct (dynamic_cast (xevent)); graphics_object fig = object ().get_ancestor ("figure"); gh_manager::post_set (fig.get_handle (), "currentcharacter", @@ -226,7 +226,7 @@ default: break; } - return Object::eventFilter (watched, event); + return Object::eventFilter (watched, xevent); } }; // namespace QtHandles diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/ButtonControl.cc --- a/libgui/graphics/ButtonControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ButtonControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/Canvas.cc --- a/libgui/graphics/Canvas.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Canvas.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/Canvas.h --- a/libgui/graphics/Canvas.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Canvas.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/CheckBoxControl.cc --- a/libgui/graphics/CheckBoxControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/CheckBoxControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/Container.cc --- a/libgui/graphics/Container.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Container.cc Fri Aug 01 12:10:05 2014 -0400 @@ -37,8 +37,8 @@ namespace QtHandles { -Container::Container (QWidget* parent) - : ContainerBase (parent), m_canvas (0) +Container::Container (QWidget* xparent) + : ContainerBase (xparent), m_canvas (0) { setFocusPolicy (Qt::ClickFocus); } @@ -47,25 +47,25 @@ { } -Canvas* Container::canvas (const graphics_handle& handle, bool create) +Canvas* Container::canvas (const graphics_handle& xhandle, bool xcreate) { - if (! m_canvas && create) + if (! m_canvas && xcreate) { - graphics_object go = gh_manager::get_object (handle); + graphics_object go = gh_manager::get_object (xhandle); 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, xhandle); - 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,26 +81,26 @@ 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))); + } + } } } -void Container::childEvent (QChildEvent* event) +void Container::childEvent (QChildEvent* xevent) { - if (event->child ()->isWidgetType ()) + if (xevent->child ()->isWidgetType ()) { - qobject_cast (event->child ())->setMouseTracking (hasMouseTracking ()); + qobject_cast (xevent->child ())->setMouseTracking (hasMouseTracking ()); } } diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/ContextMenu.cc --- a/libgui/graphics/ContextMenu.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ContextMenu.cc Fri Aug 01 12:10:05 2014 -0400 @@ -35,11 +35,11 @@ ContextMenu* ContextMenu::create (const graphics_object& go) { - Object* parent = Object::parentObject (go); + Object* xparent = Object::parentObject (go); - if (parent) + if (xparent) { - QWidget* w = parent->qWidget (); + QWidget* w = xparent->qWidget (); return new ContextMenu (go, new QMenu (w)); } @@ -47,13 +47,13 @@ return 0; } -ContextMenu::ContextMenu (const graphics_object& go, QMenu* menu) - : Object (go, menu) +ContextMenu::ContextMenu (const graphics_object& go, QMenu* xmenu) + : Object (go, xmenu) { - menu->setAutoFillBackground (true); + xmenu->setAutoFillBackground (true); - connect (menu, SIGNAL (aboutToShow (void)), SLOT (aboutToShow (void))); - connect (menu, SIGNAL (aboutToHide (void)), SLOT (aboutToHide (void))); + connect (xmenu, SIGNAL (aboutToShow (void)), SLOT (aboutToShow (void))); + connect (xmenu, SIGNAL (aboutToHide (void)), SLOT (aboutToHide (void))); } ContextMenu::~ContextMenu (void) @@ -63,25 +63,25 @@ void ContextMenu::update (int pId) { uicontextmenu::properties& up = properties (); - QMenu* menu = qWidget (); + QMenu* xmenu = qWidget (); switch (pId) { 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 = xmenu->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); - } + xmenu->popup (pt); + } else - menu->hide (); + xmenu->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 c59745865c7f -r dcb260e7a648 libgui/graphics/EditControl.cc --- a/libgui/graphics/EditControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/EditControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/Figure.cc --- a/libgui/graphics/Figure.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Figure.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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; @@ -493,103 +493,103 @@ gh_manager::post_function (Figure::updateBoundingBoxHelper, d); } -bool Figure::eventNotifyBefore (QObject* obj, QEvent* event) +bool Figure::eventNotifyBefore (QObject* obj, QEvent* xevent) { 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 (xevent->type ()) + { + case QEvent::ActionRemoved: + { + QAction* a = dynamic_cast (xevent)->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 (xevent->type ()) + { + case QEvent::Close: + xevent->ignore (); + gh_manager::post_callback (m_handle, "closerequestfcn"); + return true; + default: + break; + } + } } return false; } -void Figure::eventNotifyAfter (QObject* watched, QEvent* event) +void Figure::eventNotifyAfter (QObject* watched, QEvent* xevent) { if (! m_blockUpdates) { 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 (xevent->type ()) + { + case QEvent::Resize: + updateBoundingBox (true, UpdateBoundingBoxSize); + break; + case QEvent::ChildAdded: + if (dynamic_cast (xevent)->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 (xevent->type ()) + { + case QEvent::ActionAdded: + { + QAction* a = dynamic_cast (xevent)->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 (xevent->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 c59745865c7f -r dcb260e7a648 libgui/graphics/Figure.h --- a/libgui/graphics/Figure.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Figure.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/FigureWindow.cc --- a/libgui/graphics/FigureWindow.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/FigureWindow.cc Fri Aug 01 12:10:05 2014 -0400 @@ -31,8 +31,8 @@ namespace QtHandles { -FigureWindow::FigureWindow (QWidget* parent) - : FigureWindowBase (parent) +FigureWindow::FigureWindow (QWidget* xparent) + : FigureWindowBase (xparent) { } diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/GLCanvas.cc --- a/libgui/graphics/GLCanvas.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/GLCanvas.cc Fri Aug 01 12:10:05 2014 -0400 @@ -37,8 +37,8 @@ namespace QtHandles { -GLCanvas::GLCanvas (QWidget* parent, const graphics_handle& handle) - : QGLWidget (parent), Canvas (handle) +GLCanvas::GLCanvas (QWidget* xparent, const graphics_handle& xhandle) + : QGLWidget (xparent), Canvas (xhandle) { setFocusPolicy (Qt::ClickFocus); } @@ -47,9 +47,9 @@ { } -void GLCanvas::draw (const graphics_handle& handle) +void GLCanvas::draw (const graphics_handle& xhandle) { - graphics_object go = gh_manager::get_object (handle); + graphics_object go = gh_manager::get_object (xhandle); if (go) { @@ -119,31 +119,31 @@ canvasPaintEvent (); } -void GLCanvas::mouseMoveEvent (QMouseEvent* event) +void GLCanvas::mouseMoveEvent (QMouseEvent* xevent) { - canvasMouseMoveEvent (event); + canvasMouseMoveEvent (xevent); } -void GLCanvas::mousePressEvent (QMouseEvent* event) +void GLCanvas::mousePressEvent (QMouseEvent* xevent) { - canvasMousePressEvent (event); + canvasMousePressEvent (xevent); } -void GLCanvas::mouseReleaseEvent (QMouseEvent* event) +void GLCanvas::mouseReleaseEvent (QMouseEvent* xevent) { - canvasMouseReleaseEvent (event); + canvasMouseReleaseEvent (xevent); } -void GLCanvas::keyPressEvent (QKeyEvent* event) +void GLCanvas::keyPressEvent (QKeyEvent* xevent) { - if (! canvasKeyPressEvent (event)) - QGLWidget::keyPressEvent (event); + if (! canvasKeyPressEvent (xevent)) + QGLWidget::keyPressEvent (xevent); } -void GLCanvas::keyReleaseEvent (QKeyEvent* event) +void GLCanvas::keyReleaseEvent (QKeyEvent* xevent) { - if (! canvasKeyReleaseEvent (event)) - QGLWidget::keyReleaseEvent (event); + if (! canvasKeyReleaseEvent (xevent)) + QGLWidget::keyReleaseEvent (xevent); } }; // namespace QtHandles diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/GLCanvas.h --- a/libgui/graphics/GLCanvas.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/GLCanvas.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/GenericEventNotify.h --- a/libgui/graphics/GenericEventNotify.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/GenericEventNotify.h Fri Aug 01 12:10:05 2014 -0400 @@ -86,7 +86,7 @@ class T : public B, public GenericEventNotifySender \ { \ public: \ - T (QWidget* parent) : B (parent), GenericEventNotifySender () { } \ + T (QWidget* xparent) : B (xparent), GenericEventNotifySender () { } \ ~ T (void) { } \ \ bool event (QEvent* evt) \ diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/ListBoxControl.cc --- a/libgui/graphics/ListBoxControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ListBoxControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/Menu.cc --- a/libgui/graphics/Menu.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Menu.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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,13 +65,13 @@ QObject* qObj = parent->qObject (); if (qObj) - return new Menu (go, new QAction (qObj), parent); + return new Menu (go, new QAction (qObj), parent); } return 0; } -Menu::Menu (const graphics_object& go, QAction* action, Object* parent) +Menu::Menu (const graphics_object& go, QAction* action, Object* xparent) : Object (go, action), m_parent (0), m_separator (0) { uimenu::properties& up = properties (); @@ -92,7 +92,7 @@ m_separator->setVisible (up.is_visible ()); } - MenuContainer* menuContainer = dynamic_cast (parent); + MenuContainer* menuContainer = dynamic_cast (xparent); if (menuContainer) m_parent = menuContainer->menu (); @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/MouseModeActionGroup.cc --- a/libgui/graphics/MouseModeActionGroup.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/MouseModeActionGroup.cc Fri Aug 01 12:10:05 2014 -0400 @@ -33,17 +33,17 @@ namespace QtHandles { -MouseModeActionGroup::MouseModeActionGroup (QObject* parent) - : QObject (parent), m_current (0) +MouseModeActionGroup::MouseModeActionGroup (QObject* xparent) + : QObject (xparent), 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 c59745865c7f -r dcb260e7a648 libgui/graphics/Object.cc --- a/libgui/graphics/Object.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Object.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/Object.h --- a/libgui/graphics/Object.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Object.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/ObjectFactory.cc --- a/libgui/graphics/ObjectFactory.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ObjectFactory.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/ObjectProxy.cc --- a/libgui/graphics/ObjectProxy.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ObjectProxy.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/Panel.cc --- a/libgui/graphics/Panel.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/Panel.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 (); @@ -144,71 +144,71 @@ { } -bool Panel::eventFilter (QObject* watched, QEvent* event) +bool Panel::eventFilter (QObject* watched, QEvent* xevent) { if (! m_blockUpdates) { if (watched == qObject ()) - { - switch (event->type ()) - { - case QEvent::Resize: - { - gh_manager::auto_lock lock; - graphics_object go = object (); + { + switch (xevent->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 (xevent); - 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 (xevent->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 c59745865c7f -r dcb260e7a648 libgui/graphics/PopupMenuControl.cc --- a/libgui/graphics/PopupMenuControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/PopupMenuControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/PushButtonControl.cc --- a/libgui/graphics/PushButtonControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/PushButtonControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/PushTool.cc --- a/libgui/graphics/PushTool.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/PushTool.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/QtHandlesUtils.cc --- a/libgui/graphics/QtHandlesUtils.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/QtHandlesUtils.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/QtHandlesUtils.h --- a/libgui/graphics/QtHandlesUtils.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/QtHandlesUtils.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/RadioButtonControl.cc --- a/libgui/graphics/RadioButtonControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/RadioButtonControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/SliderControl.cc --- a/libgui/graphics/SliderControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/SliderControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/TextControl.cc --- a/libgui/graphics/TextControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/TextControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/TextEdit.cc --- a/libgui/graphics/TextEdit.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/TextEdit.cc Fri Aug 01 12:10:05 2014 -0400 @@ -31,20 +31,20 @@ namespace QtHandles { -void TextEdit::focusOutEvent (QFocusEvent* event) +void TextEdit::focusOutEvent (QFocusEvent* xevent) { - QTextEdit::focusOutEvent (event); + QTextEdit::focusOutEvent (xevent); emit editingFinished (); } -void TextEdit::keyPressEvent (QKeyEvent* event) +void TextEdit::keyPressEvent (QKeyEvent* xevent) { - QTextEdit::keyPressEvent (event); + QTextEdit::keyPressEvent (xevent); - if ((event->key () == Qt::Key_Return - || event->key () == Qt::Key_Enter) - && event->modifiers () == Qt::ControlModifier) + if ((xevent->key () == Qt::Key_Return + || xevent->key () == Qt::Key_Enter) + && xevent->modifiers () == Qt::ControlModifier) emit editingFinished (); } diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/TextEdit.h --- a/libgui/graphics/TextEdit.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/TextEdit.h Fri Aug 01 12:10:05 2014 -0400 @@ -33,7 +33,7 @@ Q_OBJECT public: - TextEdit (QWidget* parent) : QTextEdit(parent) { } + TextEdit (QWidget* xparent) : QTextEdit (xparent) { } ~TextEdit (void) { } signals: diff -r c59745865c7f -r dcb260e7a648 libgui/graphics/ToggleButtonControl.cc --- a/libgui/graphics/ToggleButtonControl.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ToggleButtonControl.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/ToggleTool.cc --- a/libgui/graphics/ToggleTool.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ToggleTool.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/ToolBar.cc --- a/libgui/graphics/ToolBar.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ToolBar.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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); @@ -118,36 +118,36 @@ } } -bool ToolBar::eventFilter (QObject* watched, QEvent* event) +bool ToolBar::eventFilter (QObject* watched, QEvent* xevent) { if (watched == qObject ()) { - switch (event->type ()) - { - case QEvent::ActionAdded: - case QEvent::ActionRemoved: - { - QActionEvent* ae = dynamic_cast (event); - QToolBar* bar = qWidget (); + switch (xevent->type ()) + { + case QEvent::ActionAdded: + case QEvent::ActionRemoved: + { + QActionEvent* ae = dynamic_cast (xevent); + 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 (xevent->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 c59745865c7f -r dcb260e7a648 libgui/graphics/ToolBarButton.cc --- a/libgui/graphics/ToolBarButton.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/ToolBarButton.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/graphics/__init_qt__.cc --- a/libgui/graphics/__init_qt__.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/graphics/__init_qt__.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/languages/pt_BR.ts diff -r c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/QTerminal.cc --- a/libgui/qterminal/libqterminal/QTerminal.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/QTerminal.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp --- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h --- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/SelfListener.cpp --- a/libgui/qterminal/libqterminal/unix/SelfListener.cpp Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/SelfListener.cpp Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/SelfListener.h --- a/libgui/qterminal/libqterminal/unix/SelfListener.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/SelfListener.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/TerminalModel.cpp --- a/libgui/qterminal/libqterminal/unix/TerminalModel.cpp Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/TerminalModel.cpp Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/TerminalModel.h --- a/libgui/qterminal/libqterminal/unix/TerminalModel.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/TerminalModel.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/TerminalView.cpp --- a/libgui/qterminal/libqterminal/unix/TerminalView.cpp Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/TerminalView.cpp Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/qterminal/libqterminal/unix/TerminalView.h --- a/libgui/qterminal/libqterminal/unix/TerminalView.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/qterminal/libqterminal/unix/TerminalView.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/files-dock-widget.cc --- a/libgui/src/files-dock-widget.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/files-dock-widget.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/find-files-model.cc --- a/libgui/src/find-files-model.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/find-files-model.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/history-dock-widget.cc --- a/libgui/src/history-dock-widget.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/history-dock-widget.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/m-editor/file-editor-interface.h --- a/libgui/src/m-editor/file-editor-interface.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/m-editor/file-editor-interface.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/m-editor/find-dialog.cc --- a/libgui/src/m-editor/find-dialog.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/m-editor/find-dialog.cc Fri Aug 01 12:10:05 2014 -0400 @@ -255,7 +255,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 c59745865c7f -r dcb260e7a648 libgui/src/m-editor/octave-qscintilla.cc --- a/libgui/src/m-editor/octave-qscintilla.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/m-editor/octave-qscintilla.cc Fri Aug 01 12:10:05 2014 -0400 @@ -188,7 +188,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); @@ -273,7 +273,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 c59745865c7f -r dcb260e7a648 libgui/src/main-window.cc --- a/libgui/src/main-window.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/main-window.cc Fri Aug 01 12:10:05 2014 -0400 @@ -1944,7 +1944,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. " @@ -2425,7 +2425,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 c59745865c7f -r dcb260e7a648 libgui/src/octave-dock-widget.cc --- a/libgui/src/octave-dock-widget.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/octave-dock-widget.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 ()); @@ -198,11 +198,15 @@ // dock the widget void +#if defined (Q_OS_WIN32) octave_dock_widget::make_widget (bool dock) +#else +octave_dock_widget::make_widget (bool) +#endif { #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 c59745865c7f -r dcb260e7a648 libgui/src/octave-gui.cc --- a/libgui/src/octave-gui.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/octave-gui.cc Fri Aug 01 12:10:05 2014 -0400 @@ -89,7 +89,7 @@ // Disable all Qt messages by default. static void -message_handler (QtMsgType type, const char *msg) +message_handler (QtMsgType, const char *) { } diff -r c59745865c7f -r dcb260e7a648 libgui/src/octave-qt-link.cc --- a/libgui/src/octave-qt-link.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/octave-qt-link.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/qtinfo/parser.cc --- a/libgui/src/qtinfo/parser.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/qtinfo/parser.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/qtinfo/parser.h --- a/libgui/src/qtinfo/parser.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/qtinfo/parser.h Fri Aug 01 12:10:05 2014 -0400 @@ -22,7 +22,7 @@ */ // Author: P. L. Lucas -// Author: Jacob Dawid +// Author: Jacob Dawid #include #include diff -r c59745865c7f -r dcb260e7a648 libgui/src/qtinfo/webinfo.cc --- a/libgui/src/qtinfo/webinfo.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/qtinfo/webinfo.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libgui/src/qtinfo/webinfo.h --- a/libgui/src/qtinfo/webinfo.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/qtinfo/webinfo.h Fri Aug 01 12:10:05 2014 -0400 @@ -22,7 +22,7 @@ */ // Author: P. L. Lucas -// Author: 2012 Jacob Dawid +// Author: 2012 Jacob Dawid #include #include "parser.h" diff -r c59745865c7f -r dcb260e7a648 libgui/src/settings-dialog.cc --- a/libgui/src/settings-dialog.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/settings-dialog.cc Fri Aug 01 12:10:05 2014 -0400 @@ -138,7 +138,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", @@ -150,7 +150,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 ( @@ -161,7 +161,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 ( @@ -211,7 +211,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 ( @@ -270,7 +270,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++; @@ -581,7 +581,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 ()); @@ -690,7 +690,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 c59745865c7f -r dcb260e7a648 libgui/src/shortcut-manager.cc diff -r c59745865c7f -r dcb260e7a648 libgui/src/workspace-model.cc --- a/libgui/src/workspace-model.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libgui/src/workspace-model.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/Makefile.am diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/__contourc__.cc --- a/libinterp/corefcn/__contourc__.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/__contourc__.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/__pchip_deriv__.cc --- a/libinterp/corefcn/__pchip_deriv__.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/__pchip_deriv__.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/balance.cc --- a/libinterp/corefcn/balance.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/balance.cc Fri Aug 01 12:10:05 2014 -0400 @@ -68,7 +68,7 @@ \n\ If four output values are requested, compute @code{@var{AA} =\n\ @var{CC}*@var{A}*@var{DD}} and @code{@var{BB} = @var{CC}*@var{B}*@var{DD}},\n\ -in which @var{AA} and @var{BB} have non-zero elements of approximately the\n\ +in which @var{AA} and @var{BB} have nonzero elements of approximately the\n\ same magnitude and @var{CC} and @var{DD} are permuted diagonal matrices as\n\ in @var{DD} for the algebraic eigenvalue problem.\n\ \n\ @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/besselj.cc --- a/libinterp/corefcn/besselj.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/besselj.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/betainc.cc --- a/libinterp/corefcn/betainc.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/betainc.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/bitfcns.cc --- a/libinterp/corefcn/bitfcns.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/bitfcns.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/bsxfun.cc --- a/libinterp/corefcn/bsxfun.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/bsxfun.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/cdisplay.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/cdisplay.c Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,164 @@ +/* + +Copyright (C) 2009-2014 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 + +#if defined (OCTAVE_USE_WINDOWS_API) +#include +#elif defined (HAVE_FRAMEWORK_CARBON) +#include +#elif defined (HAVE_X_WINDOWS) +#include +#endif + +#include "cdisplay.h" + +const char * +octave_get_display_info (int *ht, int *wd, int *dp, double *rx, double *ry, + int *dpy_avail) +{ + const char *msg = 0; + + *dpy_avail = 0; + +#if defined (OCTAVE_USE_WINDOWS_API) + + HDC hdc = GetDC (0); + + if (hdc) + { + *dp = GetDeviceCaps (hdc, BITSPIXEL); + + *ht = GetDeviceCaps (hdc, VERTRES); + *wd = GetDeviceCaps (hdc, HORZRES); + + double ht_mm = GetDeviceCaps (hdc, VERTSIZE); + double wd_mm = GetDeviceCaps (hdc, HORZSIZE); + + *rx = *wd * 25.4 / wd_mm; + *ry = *ht * 25.4 / ht_mm; + + *dpy_avail = 1; + } + else + msg = "no graphical display found"; + +#elif defined (HAVE_FRAMEWORK_CARBON) + + CGDirectDisplayID display = CGMainDisplayID (); + + if (display) + { +#if defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL) + + *dp = CGDisplayBitsPerPixel (display); + +#else + + /* FIXME: This will only work for MacOS > 10.5. For earlier versions + this code is not needed (use CGDisplayBitsPerPixel instead). */ + + CGDisplayModeRef mode = CGDisplayCopyDisplayMode (display); + CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding (mode); + + if (CFStringCompare (pixelEncoding, CFSTR (IO32BitDirectPixels), 0) == 0) + *dp = 32; + else if (CFStringCompare (pixelEncoding, + CFSTR (IO16BitDirectPixels), 0) == 0) + *dp = 16; + else + *dp = 8; + +#endif + + *ht = CGDisplayPixelsHigh (display); + *wd = CGDisplayPixelsWide (display); + + CGSize sz_mm = CGDisplayScreenSize (display); + + /* For MacOS >= 10.6, CGSize is a struct keeping 2 CGFloat + values, but the CGFloat typedef is not present on older + systems, so use double instead. */ + + double ht_mm = sz_mm.height; + double wd_mm = sz_mm.width; + + *rx = *wd * 25.4 / wd_mm; + *ry = *ht * 25.4 / ht_mm; + + *dpy_avail = 1; + } + else + msg = "no graphical display found"; + +#elif defined (HAVE_X_WINDOWS) + + const char *display_name = getenv ("DISPLAY"); + + if (display_name && *display_name) + { + Display *display = XOpenDisplay (display_name); + + if (display) + { + Screen *screen = DefaultScreenOfDisplay (display); + + if (screen) + { + *dp = DefaultDepthOfScreen (screen); + + *ht = HeightOfScreen (screen); + *wd = WidthOfScreen (screen); + + int screen_number = XScreenNumberOfScreen (screen); + + double ht_mm = DisplayHeightMM (display, screen_number); + double wd_mm = DisplayWidthMM (display, screen_number); + + *rx = *wd * 25.4 / wd_mm; + *ry = *ht * 25.4 / ht_mm; + } + else + msg = "X11 display has no default screen"; + + XCloseDisplay (display); + + *dpy_avail = 1; + } + else + msg = "unable to open X11 DISPLAY"; + } + else + msg = "X11 DISPLAY environment variable not set"; + +#else + + msg = "no graphical display found"; + +#endif + + return msg; +} diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/cdisplay.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/cdisplay.h Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,38 @@ +/* + +Copyright (C) 2014 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_cdisplay_h) +#define octave_cdisplay_h 1 + +#ifdef __cplusplus +extern "C" { +#endif + +OCTINTERP_API extern const char * +octave_get_display_info (int *ht, int *wd, int *dp, double *rx, double *ry, + int *dpy_avail); + +#ifdef __cplusplus +} +#endif + +#endif diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/cellfun.cc --- a/libinterp/corefcn/cellfun.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/cellfun.cc Fri Aug 01 12:10:05 2014 -0400 @@ -319,9 +319,9 @@ \n\ Additionally, @code{cellfun} accepts an arbitrary function @var{func}\n\ in the form of an inline function, function handle, or the name of a\n\ -function (in a character string). The function can take one or more arguments,\n\ -with the inputs arguments given by @var{C}, @var{D}, etc. Equally the\n\ -function can return one or more output arguments. For example:\n\ +function (in a character string). The function can take one or more\n\ +arguments, with the inputs arguments given by @var{C}, @var{D}, etc. \n\ +Equally the function can return one or more output arguments. For example:\n\ \n\ @example\n\ @group\n\ @@ -440,7 +440,7 @@ if (! valid_identifier (name)) { - std::string fcn_name = unique_symbol_name ("__cellfun_fcn_"); + std::string fcn_name = unique_symbol_name ("__cellfun_fcn__"); std::string fname = "function y = " + fcn_name + "(x) y = "; octave_function *ptr_func @@ -1193,7 +1193,7 @@ if (! valid_identifier (name)) { - std::string fcn_name = unique_symbol_name ("__arrayfun_fcn_"); + std::string fcn_name = unique_symbol_name ("__arrayfun_fcn__"); std::string fname = "function y = " + fcn_name + "(x) y = "; octave_function *ptr_func @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/data.cc --- a/libinterp/corefcn/data.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/data.cc Fri Aug 01 12:10:05 2014 -0400 @@ -112,15 +112,15 @@ @deftypefn {Built-in Function} {} all (@var{x})\n\ @deftypefnx {Built-in Function} {} all (@var{x}, @var{dim})\n\ For a vector argument, return true (logical 1) if all elements of the vector\n\ -are non-zero.\n\ +are nonzero.\n\ \n\ For a matrix argument, return a row vector of logical ones and\n\ zeros with each element indicating whether all of the elements of the\n\ -corresponding column of the matrix are non-zero. For example:\n\ +corresponding column of the matrix are nonzero. For example:\n\ \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\ @@ -159,11 +159,11 @@ @deftypefn {Built-in Function} {} any (@var{x})\n\ @deftypefnx {Built-in Function} {} any (@var{x}, @var{dim})\n\ For a vector argument, return true (logical 1) if any element of the vector\n\ -is non-zero.\n\ +is nonzero.\n\ \n\ For a matrix argument, return a row vector of logical ones and\n\ zeros with each element indicating whether any of the elements of the\n\ -corresponding column of the matrix are non-zero. For example:\n\ +corresponding column of the matrix are nonzero. For example:\n\ \n\ @example\n\ @group\n\ @@ -333,7 +333,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 ()) @@ -621,7 +622,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); @@ -780,7 +781,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); @@ -1262,7 +1263,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); @@ -1438,6 +1439,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) @@ -1458,12 +1464,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\n\ +used for calculations. If the argument @qcode{\"native\"} is given, then\n\ +the operation is performed in the same type as the original argument, rather\n\ +than the default double 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\n\ +in 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; } /* @@ -1477,6 +1615,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) @@ -1507,7 +1652,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 @@ -1921,7 +2083,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) @@ -1935,12 +2097,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) { @@ -2399,8 +2561,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]) @@ -2686,7 +2848,7 @@ DEFUN (nnz, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{n} =} nnz (@var{a})\n\ -Return the number of non-zero elements in @var{a}.\n\ +Return the number of nonzero elements in @var{a}.\n\ @seealso{nzmax, nonzeros, find}\n\ @end deftypefn") { @@ -2762,12 +2924,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\n\ +used for calculations. If the argument @qcode{\"native\"} is given, then\n\ +the operation is performed in the same type as the original argument, rather\n\ +than the default double type.\n\ +\n\ +For example:\n\ \n\ @example\n\ @group\n\ @@ -2781,8 +2947,8 @@ 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\ +For double precision inputs, the @qcode{\"extra\"} option will use a more\n\ +accurate algorithm than straightforward summation. For single precision\n\ inputs, @qcode{\"extra\"} is the same as @qcode{\"double\"}. Otherwise,\n\ @qcode{\"extra\"} has no effect.\n\ @seealso{cumsum, sumsq, prod}\n\ @@ -2809,7 +2975,7 @@ else if (str == "extra") isextra = true; else - error ("sum: unrecognized string argument"); + error ("sum: unrecognized type argument '%s'", str.c_str ()); nargin --; } } @@ -2876,7 +3042,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); @@ -2886,7 +3052,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); @@ -2919,11 +3086,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) @@ -2974,10 +3136,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, , @@ -3488,6 +3658,164 @@ %!assert (isnumeric (sparse ([true, false])), false) */ +DEFUN (isscalar, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} isscalar (@var{x})\n\ +Return true if @var{x} is a scalar.\n\ +@seealso{isvector, ismatrix}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + retval = args(0).numel () == 1; + else + print_usage (); + + return retval; +} + +/* +%!assert (isscalar (1)) +%!assert (isscalar ([1, 2]), false) +%!assert (isscalar ([]), false) +%!assert (isscalar ([1, 2; 3, 4]), false) + +%!assert (isscalar ("t")) +%!assert (isscalar ("test"), false) +%!assert (isscalar (["test"; "ing"]), false) + +%!test +%! s.a = 1; +%! assert (isscalar (s)); + +%% Test input validation +%!error isscalar () +%!error isscalar (1, 2) +*/ + +DEFUN (isvector, args, , + "-*- texinfo -*-\n\ +@deftypefn {Function File} {} isvector (@var{x})\n\ +Return true if @var{x} is a vector.\n\ +\n\ +A vector is a 2-D array where one of the dimensions is equal to 1. As a\n\ +consequence a 1x1 array, or scalar, is also a vector.\n\ +@seealso{isscalar, ismatrix, size, rows, columns, length}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + { + dim_vector sz = args(0).dims (); + retval = sz.length () == 2 && (sz(0) == 1 || sz(1) == 1); + } + else + print_usage (); + + return retval; +} + +/* +%!assert (isvector (1)) +%!assert (isvector ([1; 2; 3])) +%!assert (isvector ([]), false) +%!assert (isvector ([1, 2; 3, 4]), false) + +%!assert (isvector ("t")) +%!assert (isvector ("test")) +%!assert (isvector (["test"; "ing"]), false) + +%!test +%! s.a = 1; +%! assert (isvector (s)); + +%% Test input validation +%!error isvector () +%!error isvector ([1, 2], 2) +*/ + +DEFUN (isrow, args, , + "-*- texinfo -*-\n\ +@deftypefn {Function File} {} isrow (@var{x})\n\ +Return true if @var{x} is a row vector.\n\ +@seealso{iscolumn, isscalar, isvector, ismatrix}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + { + dim_vector sz = args(0).dims (); + retval = sz.length () == 2 && sz(0) == 1; + } + else + print_usage (); + + return retval; +} + +/* +%!assert (isrow ([1, 2, 3])) +%!assert (isrow ([1; 2; 3]), false) +%!assert (isrow (1)) +%!assert (isrow ([]), false) +%!assert (isrow ([1, 2; 3, 4]), false) + +%!assert (isrow ("t")) +%!assert (isrow ("test")) +%!assert (isrow (["test"; "ing"]), false) + +%!test +%! s.a = 1; +%! assert (isrow (s)); + +%% Test input validation +%!error isrow () +%!error isrow ([1, 2], 2) +*/ + +DEFUN (iscolumn, args, , + "-*- texinfo -*-\n\ +@deftypefn {Function File} {} iscolumn (@var{x})\n\ +Return true if @var{x} is a column vector.\n\ +@seealso{isrow, isscalar, isvector, ismatrix}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + { + dim_vector sz = args(0).dims (); + retval = sz.length () == 2 && sz(1) == 1; + } + else + print_usage (); + + return retval; +} + +/* +%!assert (iscolumn ([1, 2, 3]), false) +%!assert (iscolumn ([1; 2; 3])) +%!assert (iscolumn (1)) +%!assert (iscolumn ([]), false) +%!assert (iscolumn ([1, 2; 3, 4]), false) + +%!assert (iscolumn ("t")) +%!assert (iscolumn ("test"), false) +%!assert (iscolumn (["test"; "ing"]), false) + +%!test +%! s.a = 1; +%! assert (iscolumn (s)); + +%% Test input validation +%!error iscolumn () +%!error iscolumn ([1, 2], 2) +*/ + DEFUN (ismatrix, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} ismatrix (@var{a})\n\ @@ -3538,6 +3866,47 @@ %!error ismatrix ([1, 2; 3, 4], 2) */ +DEFUN (issquare, args, , + "-*- texinfo -*-\n\ +@deftypefn {Function File} {} issquare (@var{x})\n\ +Return true if @var{x} is a square matrix.\n\ +@seealso{isscalar, isvector, ismatrix, size}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + { + dim_vector sz = args(0).dims (); + retval = sz.length () == 2 && sz(0) == sz(1); + } + else + print_usage (); + + return retval; +} + +/* +%!assert (issquare ([])) +%!assert (issquare (1)) +%!assert (! issquare ([1, 2])) +%!assert (issquare ([1, 2; 3, 4])) +%!assert (! issquare ([1, 2; 3, 4; 5, 6])) +%!assert (! issquare (ones (3,3,3))) +%!assert (issquare ("t")) +%!assert (! issquare ("test")) +%!assert (issquare (["test"; "ing"; "1"; "2"])) +%!test +%! s.a = 1; +%! assert (issquare (s)); +%!assert (issquare ({1, 2; 3, 4})) +%!assert (sparse (([1, 2; 3, 4]))) + +%% Test input validation +%!error issquare () +%!error issquare ([1, 2; 3, 4], 2) +*/ + static octave_value fill_matrix (const octave_value_list& args, int val, const char *fcn) { @@ -4683,7 +5052,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\ @@ -5429,7 +5798,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)); @@ -6646,7 +7015,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); @@ -6790,7 +7159,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 ()) { @@ -6817,7 +7187,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); @@ -6872,7 +7242,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 (); @@ -6951,7 +7322,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)) @@ -6961,14 +7333,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; } @@ -7045,7 +7419,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 ()) @@ -7323,7 +7698,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); @@ -7410,7 +7786,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/debug.cc --- a/libinterp/corefcn/debug.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/debug.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/display.cc --- a/libinterp/corefcn/display.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/display.cc Fri Aug 01 12:10:05 2014 -0400 @@ -24,143 +24,28 @@ #include #endif -#include - -#if defined (OCTAVE_USE_WINDOWS_API) -#include -#elif defined (HAVE_FRAMEWORK_CARBON) -#include -#elif defined (HAVE_X_WINDOWS) -#include -#endif - #include "singleton-cleanup.h" +#include "cdisplay.h" #include "display.h" #include "error.h" display_info *display_info::instance = 0; -#if defined (HAVE_FRAMEWORK_CARBON) && ! defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL) -// FIXME: This will only work for MacOS > 10.5. For earlier versions -// this code is not needed (use CGDisplayBitsPerPixel instead). -size_t DisplayBitsPerPixel (CGDirectDisplayID display) -{ - CGDisplayModeRef mode = CGDisplayCopyDisplayMode (display); - CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding (mode); - - if (CFStringCompare (pixelEncoding, CFSTR (IO32BitDirectPixels), 0) == 0) - return 32; - else if (CFStringCompare (pixelEncoding, CFSTR (IO16BitDirectPixels), 0) == 0) - return 16; - else - return 8; -} -#endif - void display_info::init (bool query) { if (query) { -#if defined (OCTAVE_USE_WINDOWS_API) - - HDC hdc = GetDC (0); - - if (hdc) - { - dp = GetDeviceCaps (hdc, BITSPIXEL); - - ht = GetDeviceCaps (hdc, VERTRES); - wd = GetDeviceCaps (hdc, HORZRES); - - double ht_mm = GetDeviceCaps (hdc, VERTSIZE); - double wd_mm = GetDeviceCaps (hdc, HORZSIZE); - - rx = wd * 25.4 / wd_mm; - ry = ht * 25.4 / ht_mm; - - dpy_avail = true; - } - else - err_msg = "no graphical display found"; - -#elif defined (HAVE_FRAMEWORK_CARBON) + int avail = 0; - CGDirectDisplayID display = CGMainDisplayID (); - - if (display) - { -# if defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL) - // For MacOS < 10.7 use the line below - dp = CGDisplayBitsPerPixel (display); -# else - // For MacOS > 10.5 use the line below - dp = DisplayBitsPerPixel (display); -# endif - - ht = CGDisplayPixelsHigh (display); - wd = CGDisplayPixelsWide (display); - - CGSize sz_mm = CGDisplayScreenSize (display); - // For MacOS >= 10.6, CGSize is a struct keeping 2 CGFloat values, - // but the CGFloat typedef is not present on older systems, - // so use double instead. - double ht_mm = sz_mm.height; - double wd_mm = sz_mm.width; - - rx = wd * 25.4 / wd_mm; - ry = ht * 25.4 / ht_mm; + const char *msg = octave_get_display_info (&ht, &wd, &dp, &rx, &ry, + &avail); - dpy_avail = true; - } - else - err_msg = "no graphical display found"; - -#elif defined (HAVE_X_WINDOWS) - - const char *display_name = getenv ("DISPLAY"); - - if (display_name && *display_name) - { - Display *display = XOpenDisplay (display_name); - - if (display) - { - Screen *screen = DefaultScreenOfDisplay (display); - - if (screen) - { - dp = DefaultDepthOfScreen (screen); - - ht = HeightOfScreen (screen); - wd = WidthOfScreen (screen); + dpy_avail = avail; - int screen_number = XScreenNumberOfScreen (screen); - - double ht_mm = DisplayHeightMM (display, screen_number); - double wd_mm = DisplayWidthMM (display, screen_number); - - rx = wd * 25.4 / wd_mm; - ry = ht * 25.4 / ht_mm; - } - else - err_msg = "X11 display has no default screen"; - - XCloseDisplay (display); - - dpy_avail = true; - } - else - err_msg = "unable to open X11 DISPLAY"; - } - else - err_msg = "X11 DISPLAY environment variable not set"; -#else - - err_msg = "no graphical display found"; - -#endif + if (msg) + err_msg = msg; } } diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/dlmread.cc --- a/libinterp/corefcn/dlmread.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/dlmread.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/dot.cc --- a/libinterp/corefcn/dot.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/dot.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/eig.cc --- a/libinterp/corefcn/eig.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/eig.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/error.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/file-io.cc --- a/libinterp/corefcn/file-io.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/file-io.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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") { @@ -1833,6 +1837,7 @@ @print{} drwxrwxrwt 15 root root 2048 Feb 17 14:53 tmp\n\ @end group\n\ @end example\n\ +@seealso{popen2}\n\ @end deftypefn") { octave_value retval = -1; diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/filter.cc --- a/libinterp/corefcn/filter.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/filter.cc Fri Aug 01 12:10:05 2014 -0400 @@ -77,7 +77,7 @@ if (norm == static_cast(0.0)) { - error ("filter: the first element of A must be non-zero"); + error ("filter: the first element of A must be nonzero"); return y; } diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/find.cc --- a/libinterp/corefcn/find.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/find.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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) @@ -263,33 +263,15 @@ if (count > 0) { - const octave_idx_type* p = v.data (); - if (v.is_col_perm ()) + const Array& p = v.col_perm_vec (); + for (octave_idx_type k = 0; k < count; k++) { - for (octave_idx_type k = 0; k < count; k++) - { - OCTAVE_QUIT; - const octave_idx_type j = start_nc + k; - const octave_idx_type i = p[j]; - i_idx(k) = static_cast (1+i); - j_idx(k) = static_cast (1+j); - idx(k) = j * nc + i + 1; - } - } - else - { - for (octave_idx_type k = 0; k < count; k++) - { - OCTAVE_QUIT; - const octave_idx_type i = start_nc + k; - const octave_idx_type j = p[i]; - // Scatter into the index arrays according to - // j adjusted by the start point. - const octave_idx_type koff = j - start_nc; - i_idx(koff) = static_cast (1+i); - j_idx(koff) = static_cast (1+j); - idx(koff) = j * nc + i + 1; - } + OCTAVE_QUIT; + const octave_idx_type j = start_nc + k; + const octave_idx_type i = p(j); + i_idx(k) = static_cast (1+i); + j_idx(k) = static_cast (1+j); + idx(k) = j * nc + i + 1; } } else @@ -394,7 +376,7 @@ ascending order.\n\ \n\ Note that this function is particularly useful for sparse matrices, as\n\ -it extracts the non-zero elements as vectors, which can then be used to\n\ +it extracts the nonzero elements as vectors, which can then be used to\n\ create the original matrix. For example:\n\ \n\ @example\n\ diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/gcd.cc --- a/libinterp/corefcn/gcd.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/gcd.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/gl-render.cc --- a/libinterp/corefcn/gl-render.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/gl-render.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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,11 +2203,19 @@ } } -// 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) { + // Do not render if the patch has incoherent data + std::string msg; + if (props.has_bad_data (msg)) + { + warning ("opengl_renderer: %s. Not rendering.", msg.c_str ()); + return; + } + const Matrix f = props.get_faces ().matrix_value (); const Matrix v = xform.scale (props.get_vertices ().matrix_value ()); Matrix c; @@ -2162,7 +2223,6 @@ Matrix a; int nv = v.rows (); - // int vmax = v.columns (); int nf = f.rows (); int fcmax = f.columns (); @@ -2228,13 +2288,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 +2320,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 +2344,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 +2360,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 +2380,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 +2394,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 +2450,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,19 +2473,25 @@ 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++) + glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD) + ? GL_SMOOTH : GL_FLAT); + + // Add vertices in reverse order for Matlab compatibility + for (int j = count_f(i)-1; j >= 0; j--) { if (! clip(int (f(i,j) - 1))) { @@ -2404,6 +2503,13 @@ flag = true; glBegin (GL_LINE_STRIP); } + if (ec_mode != UNIFORM) + { + Matrix col = vv->color; + + if (col.numel () == 3) + glColor3dv (col.data ()); + } glVertex3d (m(0), m(1), m(2)); } else if (flag) @@ -2412,16 +2518,33 @@ glEnd (); } } + // Do loop body with vertex N to "close" GL_LINE_STRIP + // from vertex 0 to vertex N. + int j = count_f(i)-1; + if (flag && ! clip(int (f(i,j) - 1))) + { + vertex_data::vertex_data_rep *vv + = vdata[i+j*fr].get_rep (); + const Matrix m = vv->coords; + if (ec_mode != UNIFORM) + { + Matrix col = vv->color; + + if (col.numel () == 3) + glColor3dv (col.data ()); + } + glVertex3d (m(0), m(1), m(2)); + } if (flag) glEnd (); } - else + else // Normal edge contour drawn with tesselator { 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 +2675,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 +2696,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 +2729,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 +2767,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 +2791,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 +2848,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 +2891,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 { @@ -2782,7 +2925,7 @@ else if (s == ":") glLineStipple (1, static_cast (0x8888)); else if (s == "--") - glLineStipple (1, static_cast (0x0FFF)); + glLineStipple (1, static_cast (0xF0F0)); else if (s == "-.") glLineStipple (1, static_cast (0x020F)); else @@ -2934,30 +3077,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 +3141,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 +3200,7 @@ } break; default: - warning ("opengl_renderer: unsupported marker '%s'", - marker.c_str ()); + warning ("opengl_renderer: unsupported marker '%s'", marker.c_str ()); break; } @@ -3106,7 +3248,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/gl-render.h --- a/libinterp/corefcn/gl-render.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/gl-render.h Fri Aug 01 12:10:05 2014 -0400 @@ -99,7 +99,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, @@ -206,7 +206,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/gl2ps-renderer.cc --- a/libinterp/corefcn/gl2ps-renderer.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/gl2ps-renderer.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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,13 +53,13 @@ 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 { - error ("gl2ps-renderer:: Unknown terminal"); + error ("gl2ps-renderer::draw: Unknown terminal %s", term.c_str ()); return; } @@ -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) { @@ -92,16 +95,25 @@ else include_graph = "foobar-inc"; buffsize += 1024*1024; - gl2psBeginPage ("glps_renderer figure", "Octave", viewport, - gl2ps_term, gl2ps_sort, - (GL2PS_SILENT | GL2PS_SIMPLE_LINE_OFFSET - | GL2PS_NO_BLENDING | GL2PS_OCCLUSION_CULL - | GL2PS_BEST_ROOT | gl2ps_text - | GL2PS_NO_PS3_SHADING), - GL_RGBA, 0, NULL, 0, 0, 0, - buffsize, fp, include_graph.c_str ()); + // GL2PS_SILENT was removed to allow gl2ps printing errors on stderr + GLint ret = gl2psBeginPage ("glps_renderer figure", "Octave", viewport, + gl2ps_term, gl2ps_sort, + ( GL2PS_NO_BLENDING + | GL2PS_OCCLUSION_CULL + | GL2PS_BEST_ROOT + | gl2ps_text + | GL2PS_NO_PS3_SHADING), + GL_RGBA, 0, NULL, 0, 0, 0, + buffsize, fp, include_graph.c_str ()); + if (ret == GL2PS_ERROR) + error ("gl2ps-renderer::draw: gl2psBeginPage returned GL2PS_ERROR"); old_print_cmd = print_cmd; opengl_renderer::draw (go); + + // Force execution of GL commands in finite time. + // Without glFlush () there may primitives be missing in the gl2ps output. + glFlush (); + state = gl2psEndPage (); } @@ -158,7 +170,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,9 +207,9 @@ 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 +237,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/graphics.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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,93 @@ } 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_patch_xdata (void) +{ + Matrix m (3, 1, 0.0); + m(1) = 1.0; + return m; +} + +static Matrix +default_patch_ydata (void) +{ + Matrix m (3, 1, 1.0); + m(2) = 0.0; + return m; +} + +static Matrix default_axes_position (void) { Matrix m (1, 4, 0.0); @@ -274,6 +362,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 +764,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 +796,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 +811,7 @@ { dim_vector dv (cdata.dims ()); + // TrueColor data doesn't require conversion if (dv.length () == cdim && dv(cdim-1) == 3) return cdata; @@ -758,22 +856,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 +1122,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 +1137,10 @@ retval += " | " + *it; } } - if (retval != "") + + if (! retval.empty ()) retval = "[ " + retval + " ]"; + return retval; } @@ -1044,10 +1156,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 +1347,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); @@ -2640,6 +2755,39 @@ finalize (go); } +static void +xreset_default_properties (graphics_handle gh, + property_list::pval_map_type factory_pval) +{ + graphics_object obj = gh_manager::get_object (gh); + + property_list::pval_map_type pval; + + for (property_list::pval_map_const_iterator it = factory_pval.begin (); + it != factory_pval.end (); it++) + { + std::string pname = it->first; + + // Don't reset internal properties and handle_properties + if (! obj.has_readonly_property (pname) && + pname.find ("__") != 0 && pname.find ("current") != 0 && + pname != "uicontextmenu" && pname != "parent") + { + // Store *mode prop/val in order to set them last + if (pname.find ("mode") == (pname.length () - 4)) + pval.insert (std::pair + (pname, it->second)); + else + obj.set (pname, it->second); + } + } + + // set *mode properties + for (property_list::pval_map_const_iterator it = pval.begin (); + it != pval.end (); it++) + obj.set (it->first, it->second); +} + // --------------------------------------------------------------------- void @@ -2659,7 +2807,7 @@ q++) { std::string pname = q->first; - + obj.set (pname, q->second); if (error_state) @@ -2772,7 +2920,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 +2949,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) { @@ -2953,6 +3119,21 @@ } } +void +base_graphics_object::reset_default_properties (void) + { + if (valid_object ()) + { + property_list::pval_map_type factory_pval = + gh_manager::get_object (0).get_factory_defaults_list () + .find (type ())->second; + + xreset_default_properties (get_handle (), factory_pval); + + override_defaults (*this); + } + } + std::string base_graphics_object::values_as_string (void) { @@ -2961,10 +3142,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 +3159,8 @@ } } } - if (retval != "") + + if (! retval.empty ()) retval += "\n"; } else @@ -2985,6 +3169,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 +3206,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 +3232,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 +3272,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 +3302,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) @@ -3220,39 +3618,14 @@ property_list root_figure::factory_properties = root_figure::init_factory_properties (); -static void -reset_default_properties (property_list& default_properties) -{ - property_list new_defaults; - - for (property_list::plist_map_const_iterator p = default_properties.begin (); - p != default_properties.end (); p++) - { - const property_list::pval_map_type pval_map = p->second; - std::string prefix = p->first; - - for (property_list::pval_map_const_iterator q = pval_map.begin (); - q != pval_map.end (); - q++) - { - std::string s = q->first; - - if (prefix == "axes" && (s == "position" || s == "units")) - new_defaults.set (prefix + s, q->second); - else if (prefix == "figure" && (s == "position" || s == "units" - || s == "windowstyle" - || s == "paperunits")) - new_defaults.set (prefix + s, q->second); - } - } - - default_properties = new_defaults; -} - void root_figure::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + xreset_default_properties (get_handle (), + xproperties.factory_defaults ()); } // --------------------------------------------------------------------- @@ -3409,6 +3782,9 @@ position.run_listeners (POSTSET); mark_modified (); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } } @@ -3628,6 +4004,122 @@ 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", "paperpositionmode", "auto"); +%! in_pos = [0 0 4 5]; +%! tol = 20 * eps (); +%! unwind_protect +%! ## paperpositionmode "auto" converts figure size to paper units +%! set (hf, "units", "inches"); +%! set (hf, "position", in_pos); +%! set (hf, "paperunits", "centimeters"); +%! psz = get (hf, "papersize"); +%! fsz = in_pos(3:4) * 2.54; +%! pos = [(psz/2 .- fsz/2) fsz]; +%! set (hf, "paperpositionmode", "auto"); +%! assert (get (hf, "paperposition"), pos, tol) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off", "paperpositionmode", "auto"); +%! in_pos = [0 0 4 5]; +%! tol = 20 * eps (); +%! unwind_protect +%! ## likewise with normalized units +%! set (hf, "units", "inches"); +%! set (hf, "position", in_pos); +%! psz = get (hf, "papersize"); +%! set (hf, "paperunits", "normalized"); +%! fsz = in_pos(3:4) ./ psz; +%! pos = [([0.5 0.5] .- fsz/2) fsz]; +%! assert (get (hf, "paperposition"), pos, tol) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off", "paperpositionmode", "auto"); +%! in_pos = [0 0 4 5]; +%! tol = 20 * eps (); +%! unwind_protect +%! ## changing papertype updates paperposition +%! set (hf, "units", "inches"); +%! set (hf, "position", in_pos); +%! set (hf, "papertype", "a4"); +%! psz = get (hf, "papersize"); +%! fsz = in_pos(3:4); +%! pos = [(psz/2 .- fsz/2) fsz]; +%! assert (get (hf, "paperposition"), pos, tol) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off", "paperpositionmode", "auto"); +%! in_pos = [0 0 4 5]; +%! tol = 20 * eps (); +%! unwind_protect +%! ## lanscape updates paperposition +%! set (hf, "units", "inches"); +%! set (hf, "position", in_pos); +%! set (hf, "paperorientation", "landscape"); +%! psz = get (hf, "papersize"); +%! fsz = in_pos(3:4); +%! pos = [(psz/2 .- fsz/2) fsz]; +%! assert (get (hf, "paperposition"), pos, tol) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off", "paperpositionmode", "auto"); +%! in_pos = [0 0 4 5]; +%! unwind_protect +%! ## back to manual mode +%! set (hf, "paperposition", in_pos * 1.1) +%! assert (get (hf, "paperpositionmode"), "manual") +%! assert (get (hf, "paperposition"), in_pos * 1.1) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect +*/ + void figure::properties::update_paperunits (const caseless_str& old_paperunits) { @@ -3696,6 +4188,9 @@ // between update_papersize and update_papertype papersize.set (octave_value (sz)); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } void @@ -3828,6 +4323,9 @@ std::swap (sz(0), sz(1)); papersize.set (octave_value (sz)); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } /* @@ -3879,6 +4377,9 @@ papersize.set (octave_value (sz)); paperposition.set (octave_value (pos)); } + + if (paperpositionmode.is ("auto")) + paperposition.set (get_auto_paperposition ()); } /* @@ -3984,7 +4485,23 @@ void figure::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + property_list::pval_map_type plist = xproperties.factory_defaults (); + plist.erase ("units"); + plist.erase ("position"); + plist.erase ("paperunits"); + plist.erase ("paperposition"); + plist.erase ("windowstyle"); + xreset_default_properties (get_handle (), plist); + + // FIXME: the following short sleep is needed in order + // to avoid a crash when using qt toolkit + Fsleep (octave_value (0.001)); + + // override with parents' defaults + override_defaults (*this); } // --------------------------------------------------------------------- @@ -4405,27 +4922,42 @@ visible = "on"; - // Replace preserves Position and Units properties - if (mode != "replace") + // Replace/Reset preserves Position and Units properties + if (mode != "replace" && mode != "reset") { outerposition = default_axes_outerposition (); position = default_axes_position (); activepositionproperty = "outerposition"; } - - delete_children (true); - - xlabel = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); - - ylabel = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); - - zlabel = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); - - title = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); + + if (mode != "reset") + { + delete_children (true); + + xlabel = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + ylabel = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + zlabel = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + title = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + adopt (xlabel.handle_value ()); + adopt (ylabel.handle_value ()); + adopt (zlabel.handle_value ()); + adopt (title.handle_value ()); + } + else + { + graphics_object go = gh_manager::get_object (xlabel.handle_value ()); + go.reset_default_properties (); + go = gh_manager::get_object (ylabel.handle_value ()); + go.reset_default_properties (); + go = gh_manager::get_object (zlabel.handle_value ()); + go.reset_default_properties (); + go = gh_manager::get_object (title.handle_value ()); + go.reset_default_properties (); + } xset (xlabel.handle_value (), "handlevisibility", "off"); xset (ylabel.handle_value (), "handlevisibility", "off"); @@ -4463,11 +4995,6 @@ xset (zlabel.handle_value (), "autopos_tag", "zlabel"); xset (title.handle_value (), "autopos_tag", "title"); - adopt (xlabel.handle_value ()); - adopt (ylabel.handle_value ()); - adopt (zlabel.handle_value ()); - adopt (title.handle_value ()); - update_transform (); sync_positions (); override_defaults (obj); @@ -4508,13 +5035,25 @@ axes::properties::remove_child (const graphics_handle& h) { if (xlabel.handle_value ().ok () && h == xlabel.handle_value ()) - delete_text_child (xlabel); + { + delete_text_child (xlabel); + update_xlabel_position (); + } else if (ylabel.handle_value ().ok () && h == ylabel.handle_value ()) - delete_text_child (ylabel); + { + delete_text_child (ylabel); + update_ylabel_position (); + } else if (zlabel.handle_value ().ok () && h == zlabel.handle_value ()) - delete_text_child (zlabel); + { + delete_text_child (zlabel); + update_zlabel_position (); + } else if (title.handle_value ().ok () && h == title.handle_value ()) - delete_text_child (title); + { + delete_text_child (title); + update_title_position (); + } else base_properties::remove_child (h); } @@ -4704,7 +5243,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 +5269,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 +5332,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 +5439,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 +5555,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 +5578,7 @@ Matrix viewmat = get_view ().matrix_value (); nearhoriz = std::abs (viewmat(1)) <= 5; + is2D = viewmat(1) == 90; update_ticklength (); } @@ -5139,7 +5680,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 +5783,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 +5878,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 +6041,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 +6113,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); @@ -5889,6 +6437,23 @@ } void +axes::properties::set_rotate3d (const octave_value& v) +{ + rotate3d.set (v, false, false); + if (rotate3d_is ("on")) + { + // Disable rotate3d for 2D plots + if (get_is2D ()) + { + rotate3d.set ("off", false, false); + pan.set ("on", false, false); + } + else + pan.set ("off", false, false); + } +} + +void axes::properties::set_units (const octave_value& v) { if (! error_state) @@ -6248,11 +6813,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 +6830,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 +6965,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 +7078,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 +7244,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 +7287,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 +7406,7 @@ unwind_protect frame; frame.protect_var (updating_axis_limits); - updating_axis_limits = true; + updating_axis_limits.insert (get_handle ().value ()); switch (update_type) { @@ -6875,17 +7443,20 @@ } xproperties.update_transform (); + + // Disable rotate3d and select pan for 2D plots + xproperties.set_rotate3d (xproperties.get_rotate3d ()); } 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 @@ -7127,7 +7698,11 @@ void axes::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + // reset factory defaults + set_defaults ("reset"); } void @@ -7225,7 +7800,8 @@ { #ifdef HAVE_FREETYPE - int halign = 0, valign = 0; + int halign = 0; + int valign = 0; if (horizontalalignment_is ("center")) halign = 1; @@ -7340,6 +7916,197 @@ return convert_cdata (*this, fvc,cdatamapping_is ("scaled"), 2); } +static bool updating_patch_data = false; + +void +patch::properties::update_fvc (void) +{ + if (updating_patch_data) + return; + + Matrix xd = get_xdata ().matrix_value (); + Matrix yd = get_ydata ().matrix_value (); + Matrix zd = get_zdata ().matrix_value (); + NDArray cd = get_cdata ().array_value (); + + bad_data_msg = std::string (); + if (xd.dims () != yd.dims () || + (xd.dims () != zd.dims () && ! zd.is_empty ())) + { + bad_data_msg = "x/y/zdata should have the same dimensions"; + return; + } + + // Faces and Vertices + dim_vector dv; + bool is3D = false; + octave_idx_type nr = xd.rows (); + octave_idx_type nc = xd.columns (); + if (nr == 1 && nc > 1) + { + nr = nc; + nc = 1; + xd = xd.as_column (); + yd = yd.as_column (); + zd = zd.as_column (); + } + + dv(0) = nr * nc; + if (zd.is_empty ()) + dv(1) = 2; + else + { + dv(1) = 3; + is3D = true; + } + + Matrix vert (dv); + Matrix idx (nc, nr); + + octave_idx_type kk = 0; + for (octave_idx_type jj = 0; jj < nc; jj++) + { + for (octave_idx_type ii = 0; ii < nr; ii++) + { + vert(kk,0) = xd(ii,jj); + vert(kk,1) = yd(ii,jj); + if (is3D) + vert(kk,2) = zd(ii,jj); + + idx(jj,ii) = static_cast (kk+1); + + kk++; + } + } + + // facevertexcdata + Matrix fvc; + if (cd.ndims () == 3) + { + dv(0) = cd.rows () * cd.columns (); + dv(1) = cd.dims ()(2); + fvc = cd.reshape (dv); + } + else + fvc = cd.as_column (); + + // FIXME: shouldn't we update facevertexalphadata here ? + + unwind_protect frame; + frame.protect_var (updating_patch_data); + updating_patch_data = true; + + faces.set (idx); + vertices.set (vert); + facevertexcdata.set (fvc); +} + + +void +patch::properties::update_data (void) +{ + if (updating_patch_data) + return; + + Matrix idx = get_faces ().matrix_value ().transpose (); + Matrix vert = get_vertices ().matrix_value (); + NDArray fvc = get_facevertexcdata ().array_value (); + + octave_idx_type nfaces = idx.columns (); + octave_idx_type nvert = vert.rows (); + + // Check all vertices in faces are defined + bad_data_msg = std::string (); + if (static_cast (nvert) < idx.row_max ().max ()) + { + bad_data_msg = "some vertices in \"faces\" property are undefined"; + return; + } + + // Replace NaNs + if (idx.any_element_is_inf_or_nan ()) + { + for (octave_idx_type jj = 0; jj < idx.columns (); jj++) + { + double valid_vert = idx(0,jj); + bool turn_valid = false; + for (octave_idx_type ii = 0; ii < idx.rows (); ii++) + { + if (xisnan (idx(ii,jj)) || turn_valid) + { + idx(ii,jj) = valid_vert; + turn_valid = true; + } + else + valid_vert = idx(ii,jj); + } + } + } + + // Build cdata + dim_vector dv = dim_vector::alloc (3); + NDArray cd; + bool pervertex = false; + + if (fvc.rows () == nfaces || fvc.rows () == 1) + { + dv(0) = 1; + dv(1) = fvc.rows (); + dv(2) = fvc.columns (); + cd = fvc.reshape (dv); + } + else + { + if (! fvc.is_empty ()) + { + dv(0) = idx.rows (); + dv(1) = nfaces; + dv(2) = fvc.columns (); + cd.resize (dv); + pervertex = true; + } + } + + // Build x,y,zdata and eventually per vertex cdata + Matrix xd (idx.dims ()); + Matrix yd (idx.dims ()); + Matrix zd; + bool has_zd = false; + if (vert.columns () > 2) + { + zd = Matrix (idx.dims ()); + has_zd = true; + } + + + for (octave_idx_type jj = 0; jj < nfaces; jj++) + { + for (octave_idx_type ii = 0; ii < idx.rows (); ii++) + { + octave_idx_type row = static_cast (idx(ii,jj)-1); + xd(ii,jj) = vert(row,0); + yd(ii,jj) = vert(row,1); + + if (has_zd) + zd(ii,jj) = vert(row,2); + + if (pervertex) + for (int kk = 0; kk < fvc.columns (); kk++) + cd(ii,jj,kk) = fvc(row,kk); + } + } + + + unwind_protect frame; + frame.protect_var (updating_patch_data); + updating_patch_data = true; + + set_xdata (xd); + set_ydata (yd); + set_zdata (zd); + set_cdata (cd); +} + // --------------------------------------------------------------------- octave_value @@ -7367,15 +8134,26 @@ Matrix y = get_ydata ().matrix_value (); 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 (); + + // FIXME: There might be a cleaner way to do this. When data is changed + // the update_xdata, update_ydata, update_zdata routines are called in a + // serial fashion. Until the final call to update_zdata the matrices + // will be of mismatched dimensions which can cause an out-of-bound + // indexing in the code below. This one-liner prevents calculating + // normals until dimensions match. + if (x.columns () != p || y.rows () != q) + return; + + NDArray n (dim_vector (q, p, 3), 0.0); bool x_mat = (x.rows () == q); bool y_mat = (y.columns () == p); - NDArray n (dim_vector (q, p, 3), 0.0); + int i1, i2, i3, j1, j2, j3; + i1 = i2 = i3 = 0; + j1 = j2 = j3 = 0; for (int i = 0; i < p; i++) { @@ -7969,7 +8747,14 @@ void uitoolbar::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + xreset_default_properties (get_handle (), + xproperties.factory_defaults ()); + + // override with parents' defaults + override_defaults (*this); } // --------------------------------------------------------------------- @@ -8144,9 +8929,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 +9133,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 +9183,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; @@ -8595,12 +9380,17 @@ DEFUN (reset, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} reset (@var{h}, @var{property})\n\ -Remove any defaults set for the handle @var{h}. The default figure\n\ -properties of @qcode{\"position\"}, @qcode{\"units\"},\n\ -@qcode{\"windowstyle\"} and @qcode{\"paperunits\"} and the default axes\n\ -properties of @qcode{\"position\"} and @qcode{\"units\"} are not reset.\n\ -@seealso{cla, clf}\n\ +@deftypefn {Built-in Function} {} reset (@var{h})\n\ +Reset the properties of the graphic object @var{h} to their default values.\n\ +\n\ +For figures, the properties @qcode{\"position\"}, @qcode{\"units\"},\n\ +@qcode{\"windowstyle\"}, and @qcode{\"paperunits\"} are not affected.\n\ +For axes, the properties @qcode{\"position\"} and @qcode{\"units\"} are\n\ +not affected.\n\ +\n\ +The input @var{h} may also be a vector of graphic handles in which case\n\ +each individual object will be reset.\n\ +@seealso{cla, clf, newplot}\n\ @end deftypefn") { int nargin = args.length (); @@ -8617,20 +9407,148 @@ // loop over graphics objects for (octave_idx_type n = 0; n < hcv.length (); n++) gh_manager::get_object (hcv(n)).reset_default_properties (); + + if (! error_state) + Fdrawnow (); } } return octave_value (); } +/* + +%!test # line object +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! hax = axes ("defaultlinelinewidth", 3); +%! +%! hli = line (1:10, 1:10, 1:10, "marker", "o", +%! "markerfacecolor", "b", "linestyle", ":"); +%! +%! reset (hli); +%! assert (get (hli, "marker"), get (0, "defaultlinemarker")); +%! assert (get (hli, "markerfacecolor"), +%! get (0, "defaultlinemarkerfacecolor")); +%! assert (get (hli, "linestyle"), +%! get (0, "defaultlinelinestyle")); +%! assert (get (hli, "linewidth"), 3, tol); # parent axes defaults +%! +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test # patch object +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! t1 = (1/16:1/8:1)' * 2*pi; +%! t2 = ((1/16:1/16:1)' + 1/32) * 2*pi; +%! x1 = sin (t1) - 0.8; +%! y1 = cos (t1); +%! x2 = sin (t2) + 0.8; +%! y2 = cos (t2); +%! vert = [x1, y1; x2, y2]; +%! fac = [1:8,NaN(1,8);9:24]; +%! hpa = patch ("Faces",fac, "Vertices",vert, "FaceColor","r"); +%! +%! reset (hpa); +%! assert (get (hpa, "faces"), get (0, "defaultpatchfaces"), tol); +%! assert (get (hpa, "vertices"), get (0, "defaultpatchvertices"), tol); +%! assert (get (hpa, "facevertexcdata"), +%! get (0, "defaultpatchfacevertexcdata"), tol); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test # surface object +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! hsu = surface (peaks, "edgecolor", "none"); +%! +%! reset (hsu); +%! assert (get (hsu, "xdata"), get (0, "defaultsurfacexdata"), tol); +%! assert (get (hsu, "ydata"), get (0, "defaultsurfaceydata"), tol); +%! assert (get (hsu, "zdata"), get (0, "defaultsurfacezdata"), tol); +%! assert (get (hsu, "edgecolor"), +%! get (0, "defaultsurfaceedgecolor"), tol); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test # image object +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! him = image (rand (10,10), "cdatamapping", "scaled"); +%! +%! reset (him); +%! assert (get (him, "cdata"), get (0, "defaultimagecdata"), tol); +%! assert (get (him, "cdatamapping"), +%! get (0, "defaultimagecdatamapping"), tol); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test # text object +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! hte = text (5, 5, "Hi!", "fontsize", 20 ,"color", "r"); +%! +%! reset (hte); +%! assert (get (hte, "position"), get (0, "defaulttextposition"), tol); +%! assert (get (hte, "fontsize"), get (0, "defaulttextfontsize"), tol); +%! assert (get (hte, "color"), get (0, "defaulttextcolor"), tol); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test # axes object +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! pos = get (0, "defaultaxesposition") * .5; +%! hax = axes ("linewidth", 2, "position", pos); +%! title ("Reset me, please!"); +%! +%! reset (hax); +%! assert (get (hax, "linewidth"), get (0, "defaultaxeslinewidth"), tol); +%! assert (get (hax, "position"), pos, tol); # axes position is unchanged +%! assert (get (hax, "default"), struct ()); # no more axes' defaults +%! assert (get (get (hax, "title"), "string"), ""); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test # root figure object +%! set (0, "defaultfigurevisible", "off"); +%! hf = figure ("visible", "off", "paperunits", "centimeters", +%! "papertype", "a4"); +%! unwind_protect +%! reset (hf); +%! assert (get (hf, "papertype"), get (0, "defaultfigurepapertype")); +%! assert (get (hf, "paperunits"), "centimeters"); # paperunits is unchanged +%! assert (get (hf, "visible"), get (0, "defaultfigurevisible")); +%! unwind_protect_cleanup +%! close (hf); +%! set (0, "defaultfigurevisible", "remove"); +%! end_unwind_protect + +*/ + DEFUN (set, args, nargout, "-*- texinfo -*-\n\ @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 +9574,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 +9650,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 +9721,7 @@ } static std::string -get_graphics_object_type (const double val) +get_graphics_object_type (double val) { std::string retval; @@ -9380,7 +10353,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 +10630,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 +11180,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/graphics.in.h Fri Aug 01 12:10:05 2014 -0400 @@ -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,21 @@ return octave_value (); } + virtual property_list get_factory_defaults_list (void) const + { + error ("base_graphics_object::get_factory_defaults_list: invalid graphics object"); + return property_list (); + } + + 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 @@ -2822,16 +2835,7 @@ virtual void remove_all_listeners (void); - virtual void reset_default_properties (void) - { - if (valid_object ()) - { - std::string msg = (type () + "::reset_default_properties"); - gripe_not_implemented (msg.c_str ()); - } - else - error ("base_graphics_object::default: invalid graphics object"); - } + virtual void reset_default_properties (void); protected: virtual void initialize (const graphics_object& go) @@ -2969,8 +2973,23 @@ return rep->get_factory_defaults (); } + property_list get_factory_defaults_list (void) const + { + return rep->get_factory_defaults_list (); + } + + 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 +3109,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 +3120,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 +3141,7 @@ private: std::list cbo_stack; + }; private: @@ -3217,6 +3227,11 @@ return factory_properties.as_struct ("factory"); } + property_list get_factory_defaults_list (void) const + { + return factory_properties; + } + base_properties& get_properties (void) { return xproperties; } const base_properties& get_properties (void) const { return xproperties; } @@ -3224,6 +3239,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 +3356,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 +3404,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 +3479,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 +3672,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 +3711,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 @@ -3684,6 +3724,13 @@ void delete_text_child (handle_property& h); + void set_pan (const octave_value& val) + { + pan.set (val, false, false); + if (pan_is ("on") || pan_is ("xon") || pan_is ("yon")) + rotate3d.set ("off", false, false); + } + // See the genprops.awk script for an explanation of the // properties declarations. // Programming note: Keep property list sorted if new ones are added. @@ -3698,7 +3745,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" @@ -3724,12 +3771,15 @@ any_property linestyleorder S , "-" double_property linewidth , 0.5 radio_property minorgridlinestyle , "-|--|{:}|-.|none" + double_property mouse_wheel_zoom , 0.05 radio_property nextplot , "add|replacechildren|{replace}" array_property outerposition u , default_axes_outerposition () + radio_property pan s , "{on}|xon|yon|off" array_property plotboxaspectratio mu , Matrix (1, 3, 1.0) radio_property plotboxaspectratiomode u , "{auto}|manual" array_property position u , default_axes_position () radio_property projection , "{orthographic}|perspective" + radio_property rotate3d S , "{off}|on" radio_property tickdir mu , "{in}|out" radio_property tickdirmode u , "{auto}|manual" array_property ticklength u , default_axes_ticklength () @@ -3737,7 +3787,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 +4183,6 @@ void set_defaults (const std::string& mode) { - remove_all_listeners (); xproperties.set_defaults (*this, mode); } @@ -4170,6 +4219,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 +4307,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 +4372,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 +4398,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 +4480,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,13 +4515,14 @@ // 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 () + row_vector_property xdata mu , Matrix () + row_vector_property ydata mu , Matrix () // hidden properties for limit computation row_vector_property alim hlr , Matrix () row_vector_property clim hlr , Matrix () @@ -4458,6 +4532,8 @@ bool_property climinclude hlg , "on" bool_property xliminclude hl , "on" bool_property yliminclude hl , "on" + radio_property xdatamode ha , "{auto}|manual" + radio_property ydatamode ha , "{auto}|manual" END_PROPERTIES protected: @@ -4494,10 +4570,25 @@ set_clim (cdata.get_limits ()); else clim = cdata.get_limits (); + + if (xdatamode.is ("auto")) + update_xdata (); + + if (ydatamode.is ("auto")) + update_ydata (); } void update_xdata (void) { + if (xdata.get ().is_empty ()) + set_xdatamode ("auto"); + + if (xdatamode.is ("auto")) + { + set_xdata (get_auto_xdata ()); + set_xdatamode ("auto"); + } + Matrix limits = xdata.get_limits (); float dp = pixel_xsize (); @@ -4508,6 +4599,15 @@ void update_ydata (void) { + if (ydata.get ().is_empty ()) + set_ydatamode ("auto"); + + if (ydatamode.is ("auto")) + { + set_ydata (get_auto_ydata ()); + set_ydatamode ("auto"); + } + Matrix limits = ydata.get_limits (); float dp = pixel_ysize (); @@ -4516,6 +4616,30 @@ set_ylim (limits); } + Matrix get_auto_xdata (void) + { + dim_vector dv = get_cdata ().dims (); + Matrix data; + if (dv(1) > 0.) + { + data = Matrix (1, 2, 1); + data(1) = dv(1); + } + return data; + } + + Matrix get_auto_ydata (void) + { + dim_vector dv = get_cdata ().dims (); + Matrix data; + if (dv(0) > 0.) + { + data = Matrix (1, 2, 1); + data(1) = dv(0); + } + return data; + } + float pixel_size (octave_idx_type dim, const Matrix limits) { octave_idx_type l = dim - 1; @@ -4562,6 +4686,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; + } }; // --------------------------------------------------------------------- @@ -4574,6 +4706,14 @@ public: octave_value get_color_data (void) const; + // Matlab allows incoherent data to be stored into patch properties. + // The patch should then be ignored by the renderer. + bool has_bad_data (std::string &msg) const + { + msg = bad_data_msg; + return ! msg.empty (); + } + bool is_aliminclude (void) const { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); } std::string get_aliminclude (void) const @@ -4603,9 +4743,9 @@ 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 u , default_patch_faces () array_property facevertexalphadata , Matrix () - array_property facevertexcdata , Matrix () + array_property facevertexcdata u , Matrix () // FIXME: interpreter is not a property of a Matlab patch. // Octave uses this for legend() with the string displayname. radio_property interpreter , "{tex}|none|latex" @@ -4618,11 +4758,11 @@ 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 xdata u , Matrix () - array_property ydata u , Matrix () + array_property vertices u , default_patch_vertices () + array_property xdata u , default_patch_xdata () + array_property ydata u , default_patch_ydata () array_property zdata u , Matrix () // hidden properties for limit computation @@ -4656,17 +4796,67 @@ } private: - void update_xdata (void) { set_xlim (xdata.get_limits ()); } - void update_ydata (void) { set_ylim (ydata.get_limits ()); } - void update_zdata (void) { set_zlim (zdata.get_limits ()); } + std::string bad_data_msg; + + void update_faces (void) { update_data ();} + + void update_vertices (void) { update_data ();} + + void update_facevertexcdata (void) { update_data ();} + + void update_fvc (void); + + void update_xdata (void) + { + if (get_xdata ().is_empty ()) + { + // For compatibility with matlab behavior, + // if x/ydata are set empty, silently empty other *data and + // faces properties while vertices remain unchanged. + set_ydata (Matrix ()); + set_zdata (Matrix ()); + set_cdata (Matrix ()); + set_faces (Matrix ()); + } + else + update_fvc (); + + set_xlim (xdata.get_limits ()); + } + + void update_ydata (void) + { + if (get_ydata ().is_empty ()) + { + set_xdata (Matrix ()); + set_zdata (Matrix ()); + set_cdata (Matrix ()); + set_faces (Matrix ()); + } + else + update_fvc (); + + set_ylim (ydata.get_limits ()); + } + + void update_zdata (void) + { + update_fvc (); + set_zlim (zdata.get_limits ()); + } void update_cdata (void) { + update_fvc (); + if (cdatamapping_is ("scaled")) set_clim (cdata.get_limits ()); else clim = cdata.get_limits (); } + + + void update_data (void); }; private: @@ -4686,6 +4876,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 +4911,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 +4942,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 +4976,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 +5040,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 +5126,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 +5195,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 +5250,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 +5350,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 +5425,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 +5520,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 +5580,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 +5641,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 +6129,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/help.cc --- a/libinterp/corefcn/help.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/help.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/input.cc --- a/libinterp/corefcn/input.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/input.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/inv.cc diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/jit-typeinfo.cc Fri Aug 01 12:10:05 2014 -0400 @@ -34,7 +34,12 @@ #include "jit-typeinfo.h" +#ifdef HAVE_LLVM_IR_VERIFIER_H +#include +#else #include +#endif + #include #ifdef HAVE_LLVM_IR_FUNCTION_H @@ -1247,6 +1252,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 +1342,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 +1850,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/jit-util.h --- a/libinterp/corefcn/jit-util.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/jit-util.h Fri Aug 01 12:10:05 2014 -0400 @@ -42,8 +42,15 @@ { class Value; class Module; +#ifdef LEGACY_PASSMANAGER + namespace legacy { + class FunctionPassManager; + class PassManager; + } +#else class FunctionPassManager; class PassManager; +#endif class ExecutionEngine; class Function; class BasicBlock; diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/kron.cc --- a/libinterp/corefcn/kron.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/kron.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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,38 +134,20 @@ 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 (); - PermMatrix c(na*nb); // Row permutation. - octave_idx_type *pc = c.fortran_vec (); - - bool cola = a.is_col_perm (), colb = b.is_col_perm (); - if (cola && colb) - { - for (octave_idx_type i = 0; i < na; i++) - for (octave_idx_type j = 0; j < nb; j++) - pc[pa[i]*nb+pb[j]] = i*nb+j; - } - else if (cola) + octave_idx_type na = a.rows (); + octave_idx_type nb = b.rows (); + const Array& pa = a.col_perm_vec (); + const Array& pb = b.col_perm_vec (); + Array res_perm; + octave_idx_type rescol = 0; + for (octave_idx_type i = 0; i < na; i++) { - for (octave_idx_type i = 0; i < na; i++) - for (octave_idx_type j = 0; j < nb; j++) - pc[pa[i]*nb+j] = i*nb+pb[j]; - } - else if (colb) - { - for (octave_idx_type i = 0; i < na; i++) - for (octave_idx_type j = 0; j < nb; j++) - pc[i*nb+pb[j]] = pa[i]*nb+j; - } - else - { - for (octave_idx_type i = 0; i < na; i++) - for (octave_idx_type j = 0; j < nb; j++) - pc[i*nb+j] = pa[i]*nb+pb[j]; + octave_idx_type a_add = pa(i) * nb; + for (octave_idx_type j = 0; j < nb; j++) + res_perm.xelem (rescol++) = a_add + pb(j); } - return c; + return PermMatrix (res_perm, true); } template @@ -195,7 +182,7 @@ // the diagonals as vectors and compute the product. That // will be another vector, which we then use to construct a // diagonal matrix object. Note that this will fail if our - // digaonal matrix object is modified to allow the non-zero + // digaonal matrix object is modified to allow the nonzero // values to be stored off of the principal diagonal (i.e., if // diag ([1,2], 3) is modified to return a diagonal matrix // object instead of a full matrix object). @@ -282,7 +269,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/load-path.cc --- a/libinterp/corefcn/load-path.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/load-path.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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,67 @@ // 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) + { + // Even for private functions, dir_name doesn't contain the + // "private" directory component so we append it here in all + // cases. + + 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 +1295,42 @@ { std::string retval; + if (octave_env::absolute_pathname (file) + || octave_env::rooted_relative_pathname (file)) + { + file_stat fs (file); + + return fs.exists () ? file : retval; + } + 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 +1653,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 +1801,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 +1829,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 +1947,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 +1956,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 +2026,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 +2112,7 @@ { retval = dirname; - string_vector dirlist = dir.read (); + string_vector dirlist = dir.read ().sort (false); octave_idx_type len = dirlist.length (); @@ -1937,7 +2120,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 +2148,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 +2538,10 @@ return retval; } + +DEFUN (__dump_load_path__, , , "") +{ + load_path::display (octave_stdout); + + return octave_value_list (); +} diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/load-path.h --- a/libinterp/corefcn/load-path.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/load-path.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/load-save.cc --- a/libinterp/corefcn/load-save.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/load-save.cc Fri Aug 01 12:10:05 2014 -0400 @@ -503,17 +503,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; } } @@ -1066,7 +1073,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++) { @@ -1495,9 +1503,10 @@ @deftypefnx {Command} {} save options file\n\ @deftypefnx {Command} {} save options file @var{v1} @var{v2} @dots{}\n\ @deftypefnx {Command} {} save options file -struct @var{STRUCT} @var{f1} @var{f2} @dots{}\n\ +@deftypefnx {Command} {} {@var{s} =} save @samp{-} @var{v1} @var{v2} @dots{}\n\ Save the named variables @var{v1}, @var{v2}, @dots{}, in the file\n\ -@var{file}. The special filename @samp{-} may be used to write\n\ -output to the terminal. If no variable names are listed, Octave saves\n\ +@var{file}. The special filename @samp{-} may be used to return the\n\ +content of the variables as a string. If no variable names are listed, Octave saves\n\ all the variables in the current scope. Otherwise, full variable names or\n\ pattern syntax can be used to specify the variables to save.\n\ If the @option{-struct} modifier is used, fields @var{f1} @var{f2} @dots{}\n\ @@ -1616,8 +1625,6 @@ { octave_value_list retval; - int argc = args.length (); - string_vector argv = args.make_argv (); if (error_state) @@ -1641,7 +1648,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) @@ -1674,11 +1681,10 @@ if (append) warning ("save: ignoring -append option for output to stdout"); - // FIXME: should things intended for the screen - // end up in an octave_value (string)? - - save_vars (argv, i, argc, octave_stdout, format, + std::ostringstream output_buf; + save_vars (argv, i, argc, output_buf, format, save_as_floats, true); + retval = octave_value (output_buf.str()); } } diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/lookup.cc --- a/libinterp/corefcn/lookup.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/lookup.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/ls-hdf5.cc --- a/libinterp/corefcn/ls-hdf5.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/ls-hdf5.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/ls-mat4.cc --- a/libinterp/corefcn/ls-mat4.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/ls-mat4.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/ls-mat5.cc --- a/libinterp/corefcn/ls-mat5.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/ls-mat5.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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); @@ -650,7 +651,7 @@ arrayclass = static_cast (flags & 0xff); int32_t tmp_nzmax; - read_int (is, swap, tmp_nzmax); // max number of non-zero in sparse + read_int (is, swap, tmp_nzmax); // max number of nonzero in sparse nzmax = tmp_nzmax; // dimensions array subelement @@ -709,7 +710,7 @@ if (len) { - if (! is.read (name, len )) + if (! is.read (name, len)) goto data_read_error; is.seekg (tmp_pos + static_cast @@ -937,7 +938,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) { @@ -966,7 +967,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) { @@ -991,7 +992,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) { @@ -1171,7 +1172,7 @@ if (len) { - if (! is.read (name, len )) + if (! is.read (name, len)) goto data_read_error; is.seekg (tmp_pos + static_cast @@ -1201,7 +1202,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) @@ -1568,7 +1569,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); @@ -1674,7 +1676,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/lu.cc --- a/libinterp/corefcn/lu.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/lu.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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)); @@ -840,6 +842,20 @@ %! assert (norm (vec (P'*L*U - A - u*v.'), Inf) < norm (A)*1e1*eps); %! %!testif HAVE_QRUPDATE_LUU +%! [L,U,P] = lu (A); +%! [~,ordcols] = max (P,[],1); +%! [~,ordrows] = max (P,[],2); +%! P1 = eye (size(P))(:,ordcols); +%! P2 = eye (size(P))(ordrows,:); +%! assert(P1 == P); +%! assert(P2 == P); +%! [L,U,P] = luupdate (L,U,P,u,v); +%! [L,U,P1] = luupdate (L,U,P1,u,v); +%! [L,U,P2] = luupdate (L,U,P2,u,v); +%! assert(P1 == P); +%! assert(P2 == P); +%! +%!testif HAVE_QRUPDATE_LUU %! [L,U,P] = lu (Ac); %! [L,U,P] = luupdate (L,U,P,uc,vc); %! assert (norm (vec (tril (L)-L), Inf) == 0); diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/luinc.cc --- a/libinterp/corefcn/luinc.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/luinc.cc Fri Aug 01 12:10:05 2014 -0400 @@ -49,7 +49,7 @@ \n\ Called with a second argument of @qcode{'0'}, the zero-level incomplete\n\ LU@tie{}factorization is produced. This creates a factorization of @var{A}\n\ -where the position of the non-zero arguments correspond to the same\n\ +where the position of the nonzero arguments correspond to the same\n\ positions as in the matrix @var{A}.\n\ \n\ Alternatively, the fill-in of the incomplete LU@tie{}factorization can\n\ @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/mappers.cc --- a/libinterp/corefcn/mappers.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/mappers.cc Fri Aug 01 12:10:05 2014 -0400 @@ -1886,7 +1886,7 @@ Return logical true if the value of @var{x} has its sign bit set.\n\ Otherwise return logical false. This behavior is consistent with the other\n\ logical functions. See@ref{Logical Values}. The behavior differs from the\n\ -C language function which returns non-zero if the sign bit is set.\n\ +C language function which returns nonzero if the sign bit is set.\n\ \n\ This is not the same as @code{x < 0.0}, because IEEE 754 floating point\n\ allows zero to be signed. The comparison @code{-0.0 < 0.0} is false,\n\ @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/matrix_type.cc --- a/libinterp/corefcn/matrix_type.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/matrix_type.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/max.cc --- a/libinterp/corefcn/max.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/max.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -44,6 +44,7 @@ COREFCN_INC = \ corefcn/Cell.h \ corefcn/c-file-ptr-stream.h \ + corefcn/cdisplay.h \ corefcn/comment-list.h \ corefcn/cutils.h \ corefcn/data.h \ @@ -91,6 +92,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 \ @@ -143,6 +145,7 @@ corefcn/bitfcns.cc \ corefcn/bsxfun.cc \ corefcn/c-file-ptr-stream.cc \ + corefcn/cdisplay.c \ corefcn/cellfun.cc \ corefcn/colloc.cc \ corefcn/comment-list.cc \ diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-fstrm.cc --- a/libinterp/corefcn/oct-fstrm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-fstrm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -77,7 +77,7 @@ return -1; } -// Return non-zero if EOF has been reached on this stream. +// Return nonzero if EOF has been reached on this stream. bool octave_fstream::eof (void) const diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-fstrm.h --- a/libinterp/corefcn/oct-fstrm.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-fstrm.h Fri Aug 01 12:10:05 2014 -0400 @@ -52,7 +52,7 @@ off_t tell (void); - // Return non-zero if EOF has been reached on this stream. + // Return nonzero if EOF has been reached on this stream. bool eof (void) const; diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-iostrm.cc --- a/libinterp/corefcn/oct-iostrm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-iostrm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -45,7 +45,7 @@ return -1; } -// Return non-zero if EOF has been reached on this stream. +// Return nonzero if EOF has been reached on this stream. bool octave_base_iostream::eof (void) const @@ -60,7 +60,7 @@ ::error ("%s: invalid operation", stream_type ()); } -// Return non-zero if EOF has been reached on this stream. +// Return nonzero if EOF has been reached on this stream. bool octave_istream::eof (void) const @@ -74,7 +74,7 @@ return octave_stream (new octave_istream (arg, n)); } -// Return non-zero if EOF has been reached on this stream. +// Return nonzero if EOF has been reached on this stream. bool octave_ostream::eof (void) const diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-iostrm.h --- a/libinterp/corefcn/oct-iostrm.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-iostrm.h Fri Aug 01 12:10:05 2014 -0400 @@ -46,7 +46,7 @@ off_t tell (void); - // Return non-zero if EOF has been reached on this stream. + // Return nonzero if EOF has been reached on this stream. bool eof (void) const; @@ -87,7 +87,7 @@ static octave_stream create (std::istream *arg = 0, const std::string& n = std::string ()); - // Return non-zero if EOF has been reached on this stream. + // Return nonzero if EOF has been reached on this stream. bool eof (void) const; @@ -126,7 +126,7 @@ static octave_stream create (std::ostream *arg, const std::string& n = std::string ()); - // Return non-zero if EOF has been reached on this stream. + // Return nonzero if EOF has been reached on this stream. bool eof (void) const; diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-map.cc --- a/libinterp/corefcn/oct-map.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-map.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-map.h --- a/libinterp/corefcn/oct-map.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-map.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-obj.cc --- a/libinterp/corefcn/oct-obj.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-obj.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-obj.h --- a/libinterp/corefcn/oct-obj.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-obj.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-stdstrm.h --- a/libinterp/corefcn/oct-stdstrm.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-stdstrm.h Fri Aug 01 12:10:05 2014 -0400 @@ -50,7 +50,7 @@ off_t tell (void) { return s ? s->tell () : -1; } - // Return non-zero if EOF has been reached on this stream. + // Return nonzero if EOF has been reached on this stream. bool eof (void) const { return s ? s->eof () : true; } diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-stream.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-stream.h --- a/libinterp/corefcn/oct-stream.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-stream.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/oct-strstrm.h --- a/libinterp/corefcn/oct-strstrm.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/oct-strstrm.h Fri Aug 01 12:10:05 2014 -0400 @@ -96,7 +96,7 @@ oct_mach_info::float_format ff = oct_mach_info::native_float_format ()); - // Return non-zero if EOF has been reached on this stream. + // Return nonzero if EOF has been reached on this stream. bool eof (void) const { return is.eof (); } @@ -142,7 +142,7 @@ oct_mach_info::float_format ff = oct_mach_info::native_float_format ()); - // Return non-zero if EOF has been reached on this stream. + // Return nonzero if EOF has been reached on this stream. bool eof (void) const { return os.eof (); } diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/octave-default-image.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/octave-default-image.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/octave-link.cc --- a/libinterp/corefcn/octave-link.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/octave-link.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/pager.cc --- a/libinterp/corefcn/pager.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/pager.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/pinv.cc --- a/libinterp/corefcn/pinv.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/pinv.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/pr-output.cc --- a/libinterp/corefcn/pr-output.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/pr-output.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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; @@ -2487,11 +2485,10 @@ if (pr_as_read_syntax) { - Array pvec = m.pvec (); - bool colp = m.is_col_perm (); + Array pvec = m.col_perm_vec (); os << "eye ("; - if (colp) os << ":, "; + os << ":, "; octave_idx_type col = 0; while (col < nc) @@ -2522,7 +2519,6 @@ else os << " ...\n"; } - if (! colp) os << ", :"; os << ")"; } else @@ -3387,8 +3383,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 +3434,7 @@ rat_format = true; std::ostringstream buf; - args(0).print (buf); + arg.print (buf); std::string s = buf.str (); std::list lst; @@ -3501,11 +3496,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 +3538,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 +3546,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 +3610,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 +3669,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 +3747,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 +3804,7 @@ if (--argc > 0) { arg = argv[idx++]; + format.append (arg); if (arg.length () == 3) plus_format_chars = arg; @@ -3774,21 +3843,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 +4051,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__, , , + "-*- 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\ @@ -4002,7 +4099,7 @@ \n\ @noindent\n\ Notice that the first value appears to be 0 when it is actually 1. Because\n\ -of the possibilty for confusion you should be careful about enabling\n\ +of the possibility for confusion you should be careful about enabling\n\ @code{fixed_point_format}.\n\ \n\ When called from inside a function with the @qcode{\"local\"} option, the\n\ diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/profiler.cc --- a/libinterp/corefcn/profiler.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/profiler.cc Fri Aug 01 12:10:05 2014 -0400 @@ -106,7 +106,7 @@ } profile_data_accumulator::tree_node* -profile_data_accumulator::tree_node::exit (octave_idx_type fcn) +profile_data_accumulator::tree_node::exit (octave_idx_type /* fcn */) { // FIXME: These assert statements don't make sense if profile() is called // from within a function hierarchy to begin with. See bug #39587. diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/pt-jit.cc --- a/libinterp/corefcn/pt-jit.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/pt-jit.cc Fri Aug 01 12:10:05 2014 -0400 @@ -46,13 +46,26 @@ static int Vjit_startcnt = 1000; +static int Vjit_failure_count = 0; + #include #include + +#ifdef HAVE_LLVM_IR_VERIFIER_H +#include +#else #include +#endif + #include #include #include + +#ifdef LEGACY_PASSMANAGER +#include +#else #include +#endif #ifdef HAVE_LLVM_IR_FUNCTION_H #include @@ -164,7 +177,7 @@ if (expr) { jit_variable *retvar = get_variable ("#return"); - jit_value *retval; + jit_value *retval = 0; try { retval = visit (expr); @@ -230,13 +243,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 +350,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 +477,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 +531,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 +552,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 +642,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 +691,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 +739,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 +823,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 +1014,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 @@ -1888,10 +2064,15 @@ if (! engine) return false; +#ifdef LEGACY_PASSMANAGER + module_pass_manager = new llvm::legacy::PassManager (); + pass_manager = new llvm::legacy::FunctionPassManager (module); +#else module_pass_manager = new llvm::PassManager (); + pass_manager = new llvm::FunctionPassManager (module); +#endif module_pass_manager->add (llvm::createAlwaysInlinerPass ()); - pass_manager = new llvm::FunctionPassManager (module); #ifdef HAVE_LLVM_DATALAYOUT pass_manager->add (new llvm::DataLayout (*engine->getDataLayout ())); #else @@ -2006,8 +2187,13 @@ if (Vdebug_jit) { std::string error; +#ifdef RAW_FD_OSTREAM_ARG_IS_LLVM_SYS_FS + llvm::raw_fd_ostream fout ("test.bc", error, + llvm::sys::fs::F_Binary); +#else llvm::raw_fd_ostream fout ("test.bc", error, llvm::raw_fd_ostream::F_Binary); +#endif llvm::WriteBitcodeToFile (module, fout); } } @@ -2123,6 +2309,8 @@ std::cout << "jit fail: " << e.what () << std::endl; } + Vjit_failure_count++; + wrapper.erase (); raw_fn.erase (); } @@ -2279,6 +2467,9 @@ if (e.known ()) std::cout << "jit fail: " << e.what () << std::endl; } + + Vjit_failure_count++; + } if (llvm_function) @@ -2314,7 +2505,37 @@ #endif -DEFUN (debug_jit, args, nargout, +#if defined (HAVE_LLVM) +#define UNUSED_WITHOUT_LLVM(x) x +#else +#define UNUSED_WITHOUT_LLVM(x) x GCC_ATTR_UNUSED +#endif + +DEFUN (jit_failure_count, UNUSED_WITHOUT_LLVM (args), + UNUSED_WITHOUT_LLVM (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, UNUSED_WITHOUT_LLVM (args), + UNUSED_WITHOUT_LLVM (nargout), "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} debug_jit ()\n\ @deftypefnx {Built-in Function} {@var{old_val} =} debug_jit (@var{new_val})\n\ @@ -2336,7 +2557,8 @@ #endif } -DEFUN (jit_enable, args, nargout, +DEFUN (jit_enable, UNUSED_WITHOUT_LLVM (args), + UNUSED_WITHOUT_LLVM (nargout), "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} jit_enable ()\n\ @deftypefnx {Built-in Function} {@var{old_val} =} jit_enable (@var{new_val})\n\ @@ -2357,7 +2579,8 @@ #endif } -DEFUN (jit_startcnt, args, nargout, +DEFUN (jit_startcnt, UNUSED_WITHOUT_LLVM (args), + UNUSED_WITHOUT_LLVM (nargout), "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {@var{val} =} jit_startcnt ()\n\ @deftypefnx {Built-in Function} {@var{old_val} =} jit_startcnt (@var{new_val})\n\ diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/pt-jit.h --- a/libinterp/corefcn/pt-jit.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/pt-jit.h Fri Aug 01 12:10:05 2014 -0400 @@ -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&); @@ -384,8 +386,13 @@ size_t trip_count (const octave_value& bounds) const; llvm::Module *module; +#ifdef LEGACY_PASSMANAGER + llvm::legacy::PassManager *module_pass_manager; + llvm::legacy::FunctionPassManager *pass_manager; +#else llvm::PassManager *module_pass_manager; llvm::FunctionPassManager *pass_manager; +#endif llvm::ExecutionEngine *engine; }; diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/quad.cc --- a/libinterp/corefcn/quad.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/quad.cc Fri Aug 01 12:10:05 2014 -0400 @@ -235,7 +235,7 @@ quad_fcn = args(0).function_value (); else { - fcn_name = unique_symbol_name ("__quad_fcn_"); + fcn_name = unique_symbol_name ("__quad_fcn__"); std::string fname = "function y = "; fname.append (fcn_name); fname.append ("(x) y = "); diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/qz.cc --- a/libinterp/corefcn/qz.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/qz.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/rand.cc --- a/libinterp/corefcn/rand.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/rand.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/sparse-xdiv.cc --- a/libinterp/corefcn/sparse-xdiv.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/sparse-xdiv.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/sparse.cc --- a/libinterp/corefcn/sparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/sparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -135,7 +135,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 ()) @@ -178,7 +178,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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/spparms.cc --- a/libinterp/corefcn/spparms.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/spparms.cc Fri Aug 01 12:10:05 2014 -0400 @@ -86,7 +86,7 @@ The pivot tolerance of the @sc{umfpack} symmetric solvers (default 0.001)\n\ \n\ @item bandden\n\ -The density of non-zero elements in a banded matrix before it is treated\n\ +The density of nonzero elements in a banded matrix before it is treated\n\ by the @sc{lapack} banded solvers (default 0.5)\n\ \n\ @item umfpack\n\ diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/sqrtm.cc --- a/libinterp/corefcn/sqrtm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/sqrtm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/str2double.cc --- a/libinterp/corefcn/str2double.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/str2double.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/strfind.cc --- a/libinterp/corefcn/strfind.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/strfind.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/strfns.cc --- a/libinterp/corefcn/strfns.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/strfns.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/symtab.cc --- a/libinterp/corefcn/symtab.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/symtab.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/symtab.h --- a/libinterp/corefcn/symtab.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/symtab.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/syscalls.cc --- a/libinterp/corefcn/syscalls.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/syscalls.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/toplev.cc --- a/libinterp/corefcn/toplev.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/toplev.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 @@ -612,7 +615,7 @@ { if (! (interactive || forced_interactive)) { - // We should exit with a non-zero status. + // We should exit with a nonzero status. retval = 1; break; } @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/toplev.h --- a/libinterp/corefcn/toplev.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/toplev.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/tril.cc --- a/libinterp/corefcn/tril.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/tril.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/txt-eng-ft.cc --- a/libinterp/corefcn/txt-eng-ft.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/txt-eng-ft.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/txt-eng-ft.h --- a/libinterp/corefcn/txt-eng-ft.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/txt-eng-ft.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/urlwrite.cc --- a/libinterp/corefcn/urlwrite.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/urlwrite.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/utils.cc --- a/libinterp/corefcn/utils.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/utils.cc Fri Aug 01 12:10:05 2014 -0400 @@ -238,7 +238,7 @@ return status; } -// Return non-zero if either NR or NC is zero. Return -1 if this +// Return nonzero if either NR or NC is zero. Return -1 if this // should be considered fatal; return 1 if this is ok. int @@ -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 c59745865c7f -r dcb260e7a648 libinterp/corefcn/variables.cc --- a/libinterp/corefcn/variables.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/variables.cc Fri Aug 01 12:10:05 2014 -0400 @@ -388,17 +388,7 @@ int symbol_exist (const std::string& name, const std::string& type) { - std::string struct_elts; - std::string symbol_name = name; - - size_t pos = name.find ('.'); - - if (pos != std::string::npos && pos > 0) - { - struct_elts = name.substr (pos+1); - symbol_name = name.substr (0, pos); - } - else if (is_keyword (symbol_name)) + if (is_keyword (name)) return 0; bool search_any = type == "any"; @@ -409,21 +399,38 @@ if (search_any || search_var) { - bool not_a_struct = struct_elts.empty (); - bool var_ok = not_a_struct; // || val.is_map_element (struct_elts) - octave_value val = symbol_table::varval (name); - if (var_ok && (val.is_constant () || val.is_object () - || val.is_function_handle () - || val.is_anonymous_function () - || val.is_inline_function ())) + if (val.is_constant () || val.is_object () + || val.is_function_handle () + || val.is_anonymous_function () + || val.is_inline_function ()) return 1; if (search_var) return 0; } + // We shouldn't need to look in the global symbol table, since any name + // that is visible in the current scope will be in the local symbol table. + + octave_value val; + + if (search_any || search_builtin) + { + // FIXME: safe_symbol_lookup will attempt unsafe load of .oct/.mex file. + // This can cause a segfault. To catch this would require temporarily + // diverting the SIGSEGV exception handler and then restoring it. + // See bug #36067. + val = safe_symbol_lookup (name); + + if (val.is_defined () && val.is_builtin_function ()) + return 5; + + if (search_builtin) + return 0; + } + if (search_any || search_file || search_dir) { std::string file_name = lookup_autoload (name); @@ -455,7 +462,18 @@ if (fs) { if (search_any || search_file) - return fs.is_dir () ? 7 : 2; + { + if (fs.is_dir ()) + return 7; + + len = file_name.length (); + + if (len > 4 && (file_name.substr (len-4) == ".oct" + || file_name.substr (len-4) == ".mex")) + return 3; + else + return 2; + } else if (search_dir && fs.is_dir ()) return 7; } @@ -464,27 +482,9 @@ return 0; } - // We shouldn't need to look in the global symbol table, since any - // name that is visible in the current scope will be in the local - // symbol table. - - octave_value val = safe_symbol_lookup (symbol_name); - - if (val.is_defined () && struct_elts.empty ()) - { - if ((search_any || search_builtin) - && val.is_builtin_function ()) - return 5; - - if ((search_any || search_file) - && (val.is_user_function () || val.is_dld_function ())) - { - octave_function *f = val.function_value (true); - std::string s = f ? f->fcn_file_name () : std::string (); - - return s.empty () ? 103 : (val.is_user_function () ? 2 : 3); - } - } + // Command line function which Matlab does not support + if (search_any && val.is_defined () && val.is_user_function ()) + return 103; return 0; } @@ -515,21 +515,38 @@ DEFUN (exist, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} exist (@var{name}, @var{type})\n\ -Return 1 if the name exists as a variable, 2 if the name is an\n\ -absolute file name, an ordinary file in Octave's @code{path}, or (after\n\ -appending @samp{.m}) a function file in Octave's @code{path}, 3 if the\n\ -name is a @samp{.oct} or @samp{.mex} file in Octave's @code{path},\n\ -5 if the name is a built-in function, 7 if the name is a directory, or 103\n\ -if the name is a function not associated with a file (entered on\n\ -the command line).\n\ +@deftypefn {Built-in Function} {@var{c} =} exist (@var{name})\n\ +@deftypefnx {Built-in Function} {@var{c} =} exist (@var{name}, @var{type})\n\ +Check for the existence of @var{name} as a variable, function, file,\n\ +directory, or class.\n\ +\n\ +The return code @var{c} is one of\n\ +\n\ +@table @asis\n\ +@item 1\n\ +@var{name} is a variable.\n\ +\n\ +@item 2\n\ +@var{name} is an absolute file name, an ordinary file in Octave's\n\ +@code{path}, or (after appending @samp{.m}) a function file in Octave's\n\ +@code{path}.\n\ \n\ -Otherwise, return 0.\n\ +@item 3\n\ +@var{name} is a @samp{.oct} or @samp{.mex} file in Octave's @code{path}.\n\ +\n\ +@item 5\n\ +@var{name} is a built-in function.\n\ \n\ -This function also returns 2 if a regular file called @var{name}\n\ -exists in Octave's search path. If you want information about\n\ -other types of files, you should use some combination of the functions\n\ -@code{file_in_path} and @code{stat} instead.\n\ +@item 7\n\ +@var{name} is a directory.\n\ +\n\ +@item 103\n\ +@var{name} is a function not associated with a file (entered on the command\n\ +line).\n\ +\n\ +@item 0\n\ +@var{name} does not exist.\n\ +@end table\n\ \n\ If the optional argument @var{type} is supplied, check only for\n\ symbols of the specified type. Valid types are\n\ @@ -541,14 +558,26 @@ @item @qcode{\"builtin\"}\n\ Check only for built-in functions.\n\ \n\ +@item @qcode{\"dir\"}\n\ +Check only for directories.\n\ +\n\ @item @qcode{\"file\"}\n\ Check only for files and directories.\n\ \n\ -@item @qcode{\"dir\"}\n\ -Check only for directories.\n\ +@item @qcode{\"class\"}\n\ +Check only for classes. (Note: This option is accepted, but not currently implemented)\n\ @end table\n\ \n\ -@seealso{file_in_loadpath, file_in_path, find_dir_in_path, stat}\n\ +If no type is given, and there are multiple possible matches for name,\n\ +@code{exist} will return a code according to the following priority list:\n\ +variable, built-in function, oct-file, directory, file, class. \n\ +\n\ +@code{exist} returns 2 if a regular file called @var{name} is present in\n\ +Octave's search path. If you want information about other types of files\n\ +not on the search path you should use some combination of the functions\n\ +@code{file_in_path} and @code{stat} instead.\n\ +\n\ +@seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}\n\ @end deftypefn") { octave_value retval = false; @@ -557,16 +586,21 @@ if (nargin == 1 || nargin == 2) { - std::string name = args(0).string_value (); - - if (! error_state) + if (args(0).is_string ()) { + std::string name = args(0).string_value (); + if (nargin == 2) { - std::string type = args(1).string_value (); - - if (! error_state) - retval = symbol_exist (name, type); + if (args(1).is_string ()) + { + std::string type = args(1).string_value (); + + if (type == "class") + warning ("exist: \"class\" type argument is not implemented"); + + retval = symbol_exist (name, type); + } else error ("exist: TYPE must be a string"); } @@ -583,18 +617,62 @@ } /* +%!shared dirtmp, __var1 +%! dirtmp = P_tmpdir (); +%! __var1 = 1; + +%!assert (exist ("__%Highly_unlikely_name%__"), 0) +%!assert (exist ("__var1"), 1) +%!assert (exist ("__var1", "var"), 1) +%!assert (exist ("__var1", "builtin"), 0) +%!assert (exist ("__var1", "dir"), 0) +%!assert (exist ("__var1", "file"), 0) + %!test %! if (isunix ()) -%! assert (exist ("/tmp") == 7); -%! assert (exist ("/tmp", "file") == 7); -%! assert (exist ("/tmp", "dir") == 7); -%! assert (exist ("/bin/sh") == 2); -%! assert (exist ("/bin/sh", "file") == 2); -%! assert (exist ("/bin/sh", "dir") == 0); -%! assert (exist ("/dev/null") == 2); -%! assert (exist ("/dev/null", "file") == 2); -%! assert (exist ("/dev/null", "dir") == 0); +%! assert (exist ("/bin/sh"), 2); +%! assert (exist ("/bin/sh", "file"), 2); +%! assert (exist ("/bin/sh", "dir"), 0); +%! assert (exist ("/dev/null"), 2); +%! assert (exist ("/dev/null", "file"), 2); +%! assert (exist ("/dev/null", "dir"), 0); %! endif + +%!assert (exist ("colon"), 2) +%!assert (exist ("colon.m"), 2) +%!assert (exist ("colon", "file"), 2) +%!assert (exist ("colon", "dir"), 0) + +%!testif HAVE_CHOLMOD +%! assert (exist ("chol"), 3); +%! assert (exist ("chol.oct"), 3); +%! assert (exist ("chol", "file"), 3); +%! assert (exist ("chol", "builtin"), 0); + +%!assert (exist ("sin"), 5) +%!assert (exist ("sin", "builtin"), 5) +%!assert (exist ("sin", "file"), 0) + +%!assert (exist (dirtmp), 7) +%!assert (exist (dirtmp, "dir"), 7) +%!assert (exist (dirtmp, "file"), 7) + +%!error exist () +%!error exist (1,2,3) +%!warning <"class" type argument is not implemented> exist ("a", "class"); +%!error exist ("a", 1) +%!error exist (1) + +%!test +%! flist = dir (); +%! fname = flist(3).name; ## skip . and .. +%! assert (exist (fullfile (pwd (), fname), "file"), 2) +%! assert (exist (fullfile (pwd (), "nonexistentfile"), "file"), 0) + +%!assert (exist ("plot.m", "file"), 2); +%!assert (exist ("./plot.m", "file"), 0); +%!assert (exist ("./nonexistentfile", "file"), 0); +%!assert (exist ("nonexistentfile", "file"), 0); */ octave_value @@ -1405,7 +1483,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 +2335,7 @@ { symbol_table::clear_objects (); octave_class::clear_exemplar_map (); + symbol_table::clear_all (); } else { @@ -2464,6 +2545,7 @@ { symbol_table::clear_objects (); octave_class::clear_exemplar_map (); + symbol_table::clear_all (); } else { diff -r c59745865c7f -r dcb260e7a648 libinterp/corefcn/xdiv.cc --- a/libinterp/corefcn/xdiv.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/corefcn/xdiv.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/__delaunayn__.cc --- a/libinterp/dldfcn/__delaunayn__.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/__delaunayn__.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/__eigs__.cc --- a/libinterp/dldfcn/__eigs__.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/__eigs__.cc Fri Aug 01 12:10:05 2014 -0400 @@ -211,7 +211,7 @@ { std::string name = args(0).string_value (); std::string fname = "function y = "; - fcn_name = unique_symbol_name ("__eigs_fcn_"); + fcn_name = unique_symbol_name ("__eigs_fcn__"); fname.append (fcn_name); fname.append ("(x) y = "); eigs_fcn = extract_function (args(0), "eigs", fcn_name, fname, diff -r c59745865c7f -r dcb260e7a648 libinterp/dldfcn/__init_fltk__.cc --- a/libinterp/dldfcn/__init_fltk__.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/__init_fltk__.cc Fri Aug 01 12:10:05 2014 -0400 @@ -1,6 +1,7 @@ /* Copyright (C) 2007-2013 Shai Ayal +Copyright (C) 2014 Andreas Weber This file is part of Octave. @@ -61,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -91,9 +93,6 @@ #define FLTK_GRAPHICS_TOOLKIT_NAME "fltk" -// Give FLTK no more than 0.01 sec to do its stuff. -static double fltk_maxtime = 1e-2; - const char* help_text = "\ Keyboard Shortcuts\n\ a - autoscale\n\ @@ -113,7 +112,7 @@ public: OpenGL_fltk (int xx, int yy, int ww, int hh, double num) : Fl_Gl_Window (xx, yy, ww, hh, 0), number (num), renderer (), - in_zoom (false), zoom_box (), print_mode (false) + in_zoom (false), zoom_box () { // Ask for double buffering and a depth buffer. mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE); @@ -133,16 +132,21 @@ void print (const std::string& cmd, const std::string& term) { - print_mode = true; - print_cmd = cmd; - print_term = term; + //std::cout << "OpenGL_fltk::print(cmd=" << cmd << ", term=" << term << ") canvas size = " << w () << "x" << h () << std::endl; +#ifdef HAVE_GL2PS_H + FILE *fp; + fp = octave_popen (cmd.c_str (), "w"); + glps_renderer rend (fp, term); + rend.draw (gh_manager::get_object (number), cmd); + octave_pclose (fp); +#else + error ("fltk: printing not available without gl2ps library"); +#endif } void resize (int xx, int yy, int ww, int hh) { Fl_Gl_Window::resize (xx, yy, ww, hh); - setup_viewport (ww, hh); - redraw (); } bool renumber (double new_number) @@ -165,48 +169,19 @@ // (x1,y1,x2,y2) Matrix zoom_box; - bool print_mode; - std::string print_cmd; - std::string print_term; - - void setup_viewport (int ww, int hh) - { - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - glViewport (0, 0, ww, hh); - } - void draw (void) { if (! valid ()) { - valid (1); - setup_viewport (w (), h ()); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + glViewport (0, 0, w (), h ()); } - if (print_mode) - { -#ifdef HAVE_GL2PS_H - FILE *fp = octave_popen (print_cmd.c_str (), "w"); - glps_renderer rend (fp, print_term); - - rend.draw (gh_manager::get_object (number), print_cmd); + renderer.draw (gh_manager::get_object (number)); - octave_pclose (fp); - print_mode = false; -#else - print_mode = false; - error ("fltk: printing not available without gl2ps library"); - return; -#endif - } - else - { - renderer.draw (gh_manager::get_object (number)); - - if (zoom ()) - overlay (); - } + if (zoom ()) + overlay (); } void zoom_box_vertex (void) @@ -249,28 +224,20 @@ int handle (int event) { - int retval = Fl_Gl_Window::handle (event); - switch (event) { case FL_ENTER: - window ()->cursor (FL_CURSOR_CROSS); + cursor (FL_CURSOR_CROSS); return 1; case FL_LEAVE: - window ()->cursor (FL_CURSOR_DEFAULT); + cursor (FL_CURSOR_DEFAULT); return 1; } - - return retval; + return Fl_Gl_Window::handle (event); } }; -// Parameter controlling how fast we zoom when using the scrool wheel. -static double Vwheel_zoom_speed = 0.05; -// Parameter controlling the GUI mode. -static enum { pan_zoom, rotate_zoom, none } gui_mode; - void script_cb (Fl_Widget*, void* data) { static_cast (data)->execute_callback (); @@ -282,8 +249,7 @@ public: fltk_uimenu (int xx, int yy, int ww, int hh) { - menubar = new - Fl_Menu_Bar (xx, yy, ww, hh); + menubar = new Fl_Menu_Bar (xx, yy, ww, hh); } int items_to_show (void) @@ -291,7 +257,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])); @@ -305,11 +271,13 @@ void show (void) { menubar->show (); + menubar->redraw (); } void hide (void) { menubar->hide (); + menubar->redraw (); } bool is_visible (void) @@ -326,7 +294,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 +304,7 @@ menupath += "/"; menupath += m->label (); - if (menupath.compare (findname) == 0 ) + if (menupath.compare (findname) == 0) return (t); } else @@ -692,13 +660,17 @@ friend class fltk_uimenu; public: plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp) - : Fl_Window (xx, yy - menu_h, ww, hh + menu_h + status_h, "octave"), - window_label (), shift (0), ndim (2), fp (xfp), canvas (0), + : Fl_Window (xx, yy, ww, hh + menu_h + status_h + 2, "octave"), + window_label (), shift (0), fp (xfp), canvas (0), autoscale (0), togglegrid (0), panzoom (0), rotate (0), help (0), - status (0), ax_obj (), pos_x (0), pos_y (0) + status (0), resize_dummy (0), ax_obj (), pos_x (0), pos_y (0) { callback (window_close, static_cast (this)); - size_range (4*status_h, 2*status_h); + + // The size of the resize_dummy box also determines the minimum window size + resize_dummy = new Fl_Box(5 * status_h + 1, menu_h + 1, ww - 5 * status_h - 1, hh); + // read on http://fltk.org/articles.php?L415+I0+T+M1000+P1 how resizable works + resizable (resize_dummy); // FIXME: The function below is only available in FLTK >= 1.3 // At some point support for FLTK 1.1 will be dropped in Octave. @@ -708,114 +680,79 @@ // windows. Otherwise, the class is just "FLTK" //default_xclass ("Octave"); - begin (); - { - // bbox of plot canvas = [xx, yy, ww, hh]; - // (xx, yy) = UL coordinate relative to UL window. + uimenu = new fltk_uimenu (0, 0, ww, menu_h); + canvas = new OpenGL_fltk (0, menu_h, ww, hh, number ()); - canvas = new OpenGL_fltk (0, menu_h, ww, hh, number ()); + // The bottom toolbar is a composite of "autoscale", "togglegrid", + // "panzoom", "rotate", "help", and "status". Only "status" should be resized. - uimenu = new fltk_uimenu (0, 0, ww, menu_h); - uimenu->hide (); - - // Toolbar is a composite of "bottom", "autoscale", "togglegrid", - // "panzoom", "rotate", "help", and "status". + int toolbar_y = menu_h + hh + 1; + status = new Fl_Output (5 * status_h + 1, toolbar_y, ww - 5 * status_h - 1, status_h, ""); - yy = hh + menu_h; - bottom = new Fl_Box (0, yy, ww, status_h); - bottom->box (FL_FLAT_BOX); - - ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); - - autoscale = new Fl_Button (0, yy, status_h, status_h, "A"); - autoscale->callback (button_callback, static_cast (this)); - autoscale->tooltip ("Autoscale"); + status->textcolor (FL_BLACK); + status->color (FL_GRAY); + status->textfont (FL_COURIER); + status->textsize (10); + status->box (FL_ENGRAVED_BOX); - togglegrid = new Fl_Button (status_h, yy, status_h, - status_h, "G"); - togglegrid->callback (button_callback, static_cast (this)); - togglegrid->tooltip ("Toggle Grid"); + autoscale = new Fl_Button (0, toolbar_y, status_h, status_h, "A"); + autoscale->callback (button_callback, static_cast (this)); + autoscale->tooltip ("Autoscale"); - panzoom = new Fl_Button (2 * status_h, yy, status_h, - status_h, "P"); - panzoom->callback (button_callback, static_cast (this)); - panzoom->tooltip ("Mouse Pan/Zoom"); + togglegrid = new Fl_Button (status_h, toolbar_y, status_h, status_h, "G"); + togglegrid->callback (button_callback, static_cast (this)); + togglegrid->tooltip ("Toggle Grid"); - rotate = new Fl_Button (3 * status_h, yy, status_h, - status_h, "R"); - rotate->callback (button_callback, static_cast (this)); - rotate->tooltip ("Mouse Rotate"); - - if (ndim == 2) - rotate->deactivate (); + panzoom = new Fl_Button (2* status_h, toolbar_y, status_h, status_h, "P"); + panzoom->callback (button_callback, static_cast (this)); + panzoom->tooltip ("Mouse Pan/Zoom"); - help = new Fl_Button (4 * status_h, yy, status_h, - status_h, "?"); - help->callback (button_callback, static_cast (this)); - help->tooltip ("Help"); + rotate = new Fl_Button (3 * status_h, toolbar_y, status_h, status_h, "R"); + rotate->callback (button_callback, static_cast (this)); + rotate->tooltip ("Mouse Rotate"); - status = new Fl_Output (5 * status_h, yy, - ww > 2*status_h ? ww - status_h : 0, - status_h, ""); + help = new Fl_Button (4 * status_h, toolbar_y, status_h, status_h, "?"); + help->callback (button_callback, static_cast (this)); + help->tooltip ("Help"); - status->textcolor (FL_BLACK); - status->color (FL_GRAY); - status->textfont (FL_COURIER); - status->textsize (10); - status->box (FL_ENGRAVED_BOX); + end (); - // This allows us to have a valid OpenGL context right away. - canvas->mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE); - if (fp.is_visible ()) - { - // FIXME: This code should be removed when Octave drops support - // for FLTK 1.1. Search for default_xclass in this file to find - // code that should be uncommented to take its place. - // - // Set WM_CLASS which allows window managers to properly group - // related windows. Otherwise, the class is just "FLTK" - xclass ("Octave"); + if (fp.is_visible ()) + { + // FIXME: This code should be removed when Octave drops support + // for FLTK 1.1. Search for default_xclass in this file to find + // code that should be uncommented to take its place. + // + // Set WM_CLASS which allows window managers to properly group + // related windows. Otherwise, the class is just "FLTK" + xclass ("Octave"); - show (); + show (); #if defined (HAVE_X_WINDOWS) - std::string show_gui_msgs - = octave_env::getenv ("OCTAVE_SHOW_GUI_MESSAGES"); + std::string show_gui_msgs + = octave_env::getenv ("OCTAVE_SHOW_GUI_MESSAGES"); - // Installing our handler suppresses the messages. - if (show_gui_msgs.empty ()) - XSetErrorHandler (xerror_handler); + // Installing our handler suppresses the messages. + if (show_gui_msgs.empty ()) + XSetErrorHandler (xerror_handler); #endif - if (fp.get_currentaxes ().ok ()) - show_canvas (); - else - hide_canvas (); - } - } - end (); - - status->show (); - autoscale->show (); - togglegrid->show (); - panzoom->show (); - rotate->show (); + if (fp.get_currentaxes ().ok ()) + show_canvas (); + else + hide_canvas (); + } set_name (); - resizable (canvas); - gui_mode = (ndim == 3 ? rotate_zoom : pan_zoom); + uimenu->add_to_menu (fp); - if (uimenu->items_to_show ()) - show_menubar (); - else + if (!uimenu->items_to_show ()) hide_menubar (); } ~plot_window (void) { - canvas->hide (); - status->hide (); - uimenu->hide (); this->hide (); } @@ -835,31 +772,18 @@ void print (const std::string& cmd, const std::string& term) { canvas->print (cmd, term); - - // Print immediately so the output file will exist when the drawnow - // command is done. - mark_modified (); - Fl::wait (fltk_maxtime); } void show_menubar (void) { - if (!uimenu->is_visible ()) - { - // FIXME: Toolbar and menubar do not update - uimenu->show (); - mark_modified (); - } + uimenu->show (); + update_toolbar_position (); } void hide_menubar (void) { - if (uimenu->is_visible ()) - { - // FIXME: Toolbar and menubar do not update - uimenu->hide (); - mark_modified (); - } + uimenu->hide (); + update_toolbar_position (); } void uimenu_update (const graphics_handle& gh, int id) @@ -922,8 +846,6 @@ show_menubar (); else hide_menubar (); - - mark_modified (); } } @@ -941,19 +863,40 @@ canvas->hide (); } + // Move the toolbar at the bottom of the plot_window. + // The only reason for moving the toolbar is hiding and + // showing the menubar. All other resizing is done by fltk. + + void update_toolbar_position () + { + int old_canvas_h = canvas->h (); + size(w (), old_canvas_h + menu_dy () + status_h + 2); + canvas->resize (0, menu_dy (), w (), old_canvas_h); + + int toolbar_y = canvas->h () + menu_dy () + 1; + autoscale->position (0, toolbar_y); + togglegrid->position (status_h, toolbar_y); + panzoom->position (2 * status_h, toolbar_y); + rotate->position (3 * status_h, toolbar_y); + help->position (4 * status_h, toolbar_y); + status->resize (5 * status_h + 1, toolbar_y, w () - 5 * status_h - 1, status_h); + + init_sizes(); + redraw (); + } + + // Called from figure::properties::ID_POSITION + // (someone has requested a position change with set(h, "position", [...])) + // ww and hh refers to the canvas size, not the plot_window size. + + void update_position (int xx, int yy, int ww, int hh) + { + Fl_Window::resize (xx, yy + menu_dy (), ww, hh + menu_dy () + status_h + 2); + } + void mark_modified (void) { - damage (FL_DAMAGE_ALL); - canvas->damage (FL_DAMAGE_ALL); - ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ())); - - if (ndim == 3) - rotate->activate (); - else if (ndim == 2 && gui_mode == rotate_zoom) - { - rotate->deactivate (); - gui_mode = pan_zoom; - } + canvas->redraw (); } void set_name (void) @@ -977,9 +920,6 @@ // Mod keys status int shift; - // Number of dimensions, 2 or 3. - int ndim; - // Figure properties. figure::properties& fp; @@ -987,7 +927,7 @@ static const int status_h = 20; // Menu height - static const int menu_h = 20; + static const int menu_h = 25; // Window callback. static void window_close (Fl_Widget*, void* data) @@ -1007,40 +947,60 @@ { if (widg == autoscale) axis_auto (); - - if (widg == togglegrid) + else if (widg == togglegrid) toggle_grid (); + else if (widg == panzoom) + set_on_ax_obj ("pan", "on"); + else if (widg == rotate) + set_on_ax_obj ("rotate3d", "on"); + else if (widg == help) + fl_message ("%s", help_text); + } - if (widg == panzoom) - gui_mode = pan_zoom; - - if (widg == rotate && ndim == 3) - gui_mode = rotate_zoom; - - if (widg == help) - fl_message ("%s", help_text); + void set_on_ax_obj (const std::string& name, const std::string& value) + { + // ax_obj is the last clicked axes object + if (ax_obj && ax_obj.isa ("axes")) + { + axes::properties& ap = dynamic_cast(ax_obj.get_properties ()); + ap.set (name, value); + } + else // no axes object clicked so far, take currentaxes + { + graphics_handle gh = fp.get_currentaxes (); + if (gh.ok ()) + { + graphics_object go = gh_manager::get_object (gh); + axes::properties& ap = dynamic_cast(go.get_properties ()); + ap.set (name, value); + } + } } fltk_uimenu* uimenu; OpenGL_fltk* canvas; - Fl_Box* bottom; Fl_Button* autoscale; Fl_Button* togglegrid; Fl_Button* panzoom; Fl_Button* rotate; Fl_Button* help; Fl_Output* status; + Fl_Box* resize_dummy; graphics_object ax_obj; int pos_x; int pos_y; + void axis_auto (void) { octave_value_list args; - args(0) = fp.get_currentaxes ().as_octave_value (); - args(1) = "auto"; - feval ("axis", args); - mark_modified (); + if (fp.get_currentaxes ().ok ()) + { + args(0) = fp.get_currentaxes ().as_octave_value (); + args(1) = "auto"; + feval ("axis", args); + mark_modified (); + } } void toggle_grid (void) @@ -1056,7 +1016,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 +1032,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 (); @@ -1123,7 +1083,6 @@ } status->value (cbuf.str ().c_str ()); - status->redraw (); } void view2status (graphics_object ax) @@ -1140,7 +1099,6 @@ cbuf << "[azimuth: " << v(0) << ", elevation: " << v(1) << "]"; status->value (cbuf.str ().c_str ()); - status->redraw (); } } @@ -1230,58 +1188,29 @@ return Cell (mod); } - void resize (int xx,int yy,int ww,int hh) + void resize (int xx, int yy, int ww, int hh) { Fl_Window::resize (xx, yy, ww, hh); Matrix pos (1,4,0); pos(0) = xx; pos(1) = yy + menu_dy (); - pos(2) = ww; - pos(3) = hh - menu_dy () - status_h; - - fp.set_boundingbox (pos, true); - } + pos(2) = canvas->w (); + pos(3) = canvas->h (); - void draw (void) - { - // FIXME: Toolbar and menubar do not update properly - Matrix pos = fp.get_boundingbox (true); - int canvas_h = pos(3); - int canvas_w = pos(2); - int canvas_y = menu_dy (); - int toolbar_y = menu_dy () + canvas_h; - pos(1) = pos(1) - menu_dy (); - pos(3) = pos(3) + menu_dy () + status_h; - - Fl_Window::resize (pos(0), pos(1), pos(2), pos(3)); - - bottom->resize (0, toolbar_y, status_h, status_h); - autoscale->resize (0, toolbar_y, status_h, status_h); - togglegrid->resize (status_h, toolbar_y, status_h, status_h); - panzoom->resize (2 * status_h, toolbar_y, status_h, status_h); - rotate->resize (3 * status_h, toolbar_y, status_h, status_h); - help->resize (4 * status_h, toolbar_y, status_h, status_h); - status->resize (5 * status_h, toolbar_y, pos(2) - 4 * status_h, status_h); - if (canvas->valid ()) - canvas->resize (0, canvas_y, canvas_w, canvas_h); - - return Fl_Window::draw (); + fp.set_position (pos, false); } int handle (int event) { - graphics_handle gh; + if (event == FL_FOCUS) + return 1; - graphics_object fig = gh_manager::get_object (fp.get___myhandle__ ()); - int retval = Fl_Window::handle (event); - - // We only handle events which are in the canvas area. - if (!Fl::event_inside (canvas)) - return retval; + graphics_handle gh; if (!fp.is_beingdeleted ()) { + //std::cout << "plot_window::handle event = " << fl_eventnames[event] << std::endl; switch (event) { case FL_KEYDOWN: @@ -1303,22 +1232,22 @@ case 'a': case 'A': axis_auto (); - break; + return 1; case 'g': case 'G': toggle_grid (); - break; + return 1; case 'p': case 'P': - gui_mode = pan_zoom; - break; + set_on_ax_obj ("pan", "on"); + return 1; case 'r': case 'R': - gui_mode = rotate_zoom; - break; + set_on_ax_obj ("rotate3d", "on"); + return 1; } } break; @@ -1336,21 +1265,30 @@ evt.assign ("Key", octave_value (std::tolower (key_a))); evt.assign ("Modifier", octave_value (modifier2cell ())); fp.execute_keyreleasefcn (evt); + return 1; } } break; + } + // Events we only handle if they are in the canvas area. + if (Fl::event_inside (canvas)) + switch (event) + { case FL_MOVE: pixel2status (pixel2axes_or_ca (Fl::event_x (), Fl::event_y () - menu_dy ()), Fl::event_x (), Fl::event_y () - menu_dy ()); - break; + return 1; case FL_PUSH: pos_x = Fl::event_x (); pos_y = Fl::event_y () - menu_dy (); - set_currentpoint (Fl::event_x (), Fl::event_y () - menu_dy ()); + set_currentpoint (pos_x, pos_y); + + if (fp.get_windowbuttonupfcn ().is_defined ()) + fp.execute_windowbuttondownfcn (Fl::event_button()); gh = pixel2axes_or_ca (pos_x, pos_y); @@ -1358,12 +1296,18 @@ { ax_obj = gh_manager::get_object (gh); set_axes_currentpoint (ax_obj, pos_x, pos_y); - } + + int ndim = calc_dimensions (ax_obj); - fp.execute_windowbuttondownfcn (Fl::event_button()); + if (ndim == 3) + rotate->activate (); + else // ndim == 2 + rotate->deactivate (); - if (Fl::event_button () == 1 || Fl::event_button () == 3) - return 1; + fp.set_currentobject (ax_obj.get_handle ().value ()); + + return 1; + } break; @@ -1378,32 +1322,48 @@ { if (ax_obj && ax_obj.isa ("axes")) { - if (gui_mode == pan_zoom) - pixel2status (ax_obj, pos_x, pos_y, - Fl::event_x (), - Fl::event_y () - menu_dy ()); - else - view2status (ax_obj); axes::properties& ap = dynamic_cast (ax_obj.get_properties ()); - double x0, y0, x1, y1; - Matrix pos = fp.get_boundingbox (true); - pixel2pos (ax_obj, pos_x, pos_y, x0, y0); - pixel2pos (ax_obj, Fl::event_x (), - Fl::event_y () - menu_dy (), - x1, y1); + // Don't pan or rotate legend + if (ap.get_tag().compare ("legend") < 0) + { + if (ap.rotate3d_is ("on")) + view2status (ax_obj); + else + pixel2status (ax_obj, pos_x, pos_y, + Fl::event_x (), + Fl::event_y () - menu_dy ()); + + double x0, y0, x1, y1; + Matrix pos = fp.get_boundingbox (true); + pixel2pos (ax_obj, pos_x, pos_y, x0, y0); + pixel2pos (ax_obj, Fl::event_x (), + Fl::event_y () - menu_dy (), + x1, y1); - if (gui_mode == pan_zoom) - ap.translate_view (x0, x1, y0, y1); - else if (gui_mode == rotate_zoom) - { - double daz, del; - daz = (Fl::event_x () - pos_x) / pos(2) * 360; - del = (Fl::event_y () - menu_dy () - pos_y) - / pos(3) * 360; - ap.rotate_view (del, daz); + if (ap.pan_is ("on")) + ap.translate_view (x0, x1, y0, y1); + else if (ap.pan_is ("xon")) + ap.translate_view (x0, x1, y1, y1); + else if (ap.pan_is ("yon")) + ap.translate_view (x1, x1, y0, y1); + else if (ap.rotate3d_is ("on")) + { + double daz, del; + daz = (Fl::event_x () - pos_x) / pos(2) * 360; + del = (Fl::event_y () - menu_dy () - pos_y) + / pos(3) * 360; + ap.rotate_view (del, daz); + } + } + else + { // move the position of the legend + Matrix pos = ap.get_position ().matrix_value (); + pos(0) += double (Fl::event_x () - pos_x) / canvas->w(); + pos(1) -= double (Fl::event_y () - menu_dy () - pos_y) / canvas->h(); + ap.set_position (pos); } pos_x = Fl::event_x (); @@ -1423,7 +1383,8 @@ zoom_box (3) = Fl::event_y () - menu_dy (); canvas->set_zoom_box (zoom_box); canvas->zoom (true); - canvas->redraw (); + mark_modified (); + return 1; } break; @@ -1439,6 +1400,9 @@ axes::properties& ap = dynamic_cast (ax.get_properties ()); + // Parameter controlling how fast we zoom when using the scrool wheel. + double Vwheel_zoom_speed = ap.get_mouse_wheel_zoom (); + // Determine if we're zooming in or out. const double factor = (Fl::event_dy () > 0) ? 1 / (1.0 - Vwheel_zoom_speed) @@ -1451,9 +1415,9 @@ ap.zoom_about_point (x1, y1, factor, false); mark_modified (); + return 1; } } - return 1; case FL_RELEASE: if (fp.get_windowbuttonupfcn ().is_defined ()) @@ -1462,20 +1426,12 @@ fp.execute_windowbuttonupfcn (); } - if (Fl::event_button () == 1) + if ((Fl::event_button () == 1) && Fl::event_clicks ()) //double click { - if ( Fl::event_clicks () == 1) - { - if (ax_obj && ax_obj.isa ("axes")) - { - axes::properties& ap = dynamic_cast - (ax_obj.get_properties ()); - ap.set_xlimmode ("auto"); - ap.set_ylimmode ("auto"); - ap.set_zlimmode ("auto"); - mark_modified (); - } - } + set_on_ax_obj ("xlimmode", "auto"); + set_on_ax_obj ("ylimmode", "auto"); + set_on_ax_obj ("zlimmode", "auto"); + return 1; } if (Fl::event_button () == 3) { @@ -1522,14 +1478,15 @@ ap.zoom (xl, yl); } mark_modified (); + return 1; } } } break; } } - - return retval; + //std::cout << "plot_window::handle wasn't interested in event " << fl_eventnames[event] << std::endl; + return Fl_Window::handle (event); } }; @@ -1653,16 +1610,18 @@ instance->do_update_canvas (hnd2idx (gh), ca); } - static void toggle_menubar_visibility (int fig_idx, bool menubar_is_figure) + static void update_position (const std::string& fig_idx_str, + const Matrix pos) { if (instance_ok ()) - instance->do_toggle_menubar_visibility (fig_idx, menubar_is_figure); + instance->do_update_position (str2idx (fig_idx_str), pos); } static void toggle_menubar_visibility (const std::string& fig_idx_str, bool menubar_is_figure) { - toggle_menubar_visibility (str2idx (fig_idx_str), menubar_is_figure); + if (instance_ok ()) + instance->do_toggle_menubar_visibility (str2idx (fig_idx_str), menubar_is_figure); } private: @@ -1765,7 +1724,9 @@ wm_iterator win = windows.find (idx); if (win != windows.end ()) - win->second->mark_modified (); + { + win->second->mark_modified (); + } } void do_set_name (int idx) @@ -1820,6 +1781,14 @@ } } + void do_update_position (int idx, Matrix pos) + { + wm_iterator win = windows.find (idx); + + if (win != windows.end ()) + win->second->update_position (pos(0), pos(1), pos(2), pos(3)); + } + static int str2idx (const caseless_str& clstr) { int ind; @@ -1905,9 +1874,6 @@ } } } - - // it seems that we have to call Fl::check twice to get everything drawn - Fl::check (); Fl::check (); } @@ -2014,6 +1980,14 @@ figure_manager::set_name (tmp); } break; + + case figure::properties::ID_POSITION: + { + std::string tmp = ov.string_value (); + Matrix pos = fp.get_position ().matrix_value (); + figure_manager::update_position (tmp, pos); + } + break; } } } @@ -2030,8 +2004,6 @@ void redraw_figure (const graphics_object& go) const { figure_manager::mark_modified (go.get_handle ()); - - __fltk_redraw__ (); } void print_figure (const graphics_object& go, @@ -2040,7 +2012,6 @@ const std::string& /*debug_file*/) const { figure_manager::print (go.get_handle (), file_cmd, term); - redraw_figure (go); } Matrix get_canvas_size (const graphics_handle& fh) const @@ -2048,11 +2019,16 @@ return figure_manager::get_size (fh); } +/* double get_screen_resolution (void) const { // FLTK doesn't give this info. return 72.0; + + // FIXME: FLTK >= 1.3.0 could do this with Fl::screen_dpi (h, v, n) + // but do we need it? } +*/ Matrix get_screen_size (void) const { @@ -2068,16 +2044,12 @@ { munlock ("__init_fltk__"); - figure_manager::close_all (); - octave_value_list args = input_event_hook_fcn_id; args.append (false); Fremove_input_event_hook (args, 0); - input_event_hook_fcn_id = octave_value_list (); - // FIXME: ??? - Fl::wait (fltk_maxtime); + figure_manager::close_all (); } } @@ -2140,31 +2112,6 @@ return octave_value (); } -DEFUN_DLD (__fltk_maxtime__, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{maxtime} =} __fltk_maxtime__ ()\n\ -@deftypefnx {Loadable Function} {} __fltk_maxtime__ (@var{maxtime})\n\ -Undocumented internal function.\n\ -@end deftypefn") -{ -#ifdef HAVE_FLTK - octave_value retval = fltk_maxtime; - - if (args.length () == 1) - { - if (args(0).is_real_scalar ()) - fltk_maxtime = args(0).double_value (); - else - error ("argument must be a real scalar"); - } - - return retval; -#else - error ("__fltk_maxtime__: not available without OpenGL and FLTK libraries"); - return octave_value (); -#endif -} - DEFUN_DLD (__have_fltk__, , , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{FLTK_available} =} __have_fltk__ ()\n\ @@ -2181,101 +2128,3 @@ return retval; } - -// FIXME: This function should be abstracted and made potentially -// available to all graphics toolkits. This suggests putting it in -// graphics.cc as is done for drawnow() and having the master -// mouse_wheel_zoom function call fltk_mouse_wheel_zoom. The same -// should be done for gui_mode and fltk_gui_mode. For now (2011.01.30), -// just changing function names and docstrings. - -DEFUN_DLD (mouse_wheel_zoom, args, nargout, - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{val} =} mouse_wheel_zoom ()\n\ -@deftypefnx {Loadable Function} {@var{old_val} =} mouse_wheel_zoom (@var{new_val})\n\ -@deftypefnx {Loadable Function} {} mouse_wheel_zoom (@var{new_val}, \"local\")\n\ -Query or set the mouse wheel zoom factor.\n\ -\n\ -The zoom factor is a number in the range (0,1) which is the percentage of the\n\ -current axis limits that will be used when zooming. For example, if the\n\ -current x-axis limits are [0, 50] and @code{mouse_wheel_zoom} is 0.4 (40%),\n\ -then a zoom operation will change the limits by 20.\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\ -\n\ -This function is currently implemented only for the FLTK graphics toolkit.\n\ -@seealso{gui_mode}\n\ -@end deftypefn") -{ -#ifdef HAVE_FLTK - return SET_INTERNAL_VARIABLE_WITH_LIMITS(wheel_zoom_speed, 0.0001, 0.9999); -#else - error ("mouse_wheel_zoom: not available without OpenGL and FLTK libraries"); - return octave_value (); -#endif -} - -DEFUN_DLD (gui_mode, args, , - "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {@var{mode} =} gui_mode ()\n\ -@deftypefnx {Built-in Function} {} gui_mode (@var{mode})\n\ -Query or set the GUI mode for the current graphics toolkit.\n\ -The @var{mode} argument can be one of the following strings:\n\ -\n\ -@table @asis\n\ -@item @qcode{\"2d\"}\n\ -Allows panning and zooming of current axes.\n\ -\n\ -@item @qcode{\"3d\"}\n\ -Allows rotating and zooming of current axes.\n\ -\n\ -@item @qcode{\"none\"}\n\ -Mouse inputs have no effect.\n\ -@end table\n\ -\n\ -This function is currently implemented only for the FLTK graphics toolkit.\n\ -@seealso{mouse_wheel_zoom}\n\ -@end deftypefn") -{ -#ifdef HAVE_FLTK - caseless_str mode_str; - - if (gui_mode == pan_zoom) - mode_str = "2d"; - else if (gui_mode == rotate_zoom) - mode_str = "3d"; - else - mode_str = "none"; - - bool failed = false; - - if (args.length () == 1) - { - if (args(0).is_string ()) - { - mode_str = args(0).string_value (); - - if (mode_str.compare ("2d")) - gui_mode = pan_zoom; - else if (mode_str.compare ("3d")) - gui_mode = rotate_zoom; - else if (mode_str.compare ("none")) - gui_mode = none; - else - failed = true; - } - else - failed = true; - } - - if (failed) - error ("MODE must be one of the strings: \"2D\", \"3D\", or \"none\""); - - return octave_value (mode_str); -#else - error ("gui_mode: not available without OpenGL and FLTK libraries"); - return octave_value (); -#endif -} diff -r c59745865c7f -r dcb260e7a648 libinterp/dldfcn/amd.cc --- a/libinterp/dldfcn/amd.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/amd.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/ccolamd.cc --- a/libinterp/dldfcn/ccolamd.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/ccolamd.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/chol.cc --- a/libinterp/dldfcn/chol.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/chol.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/fftw.cc --- a/libinterp/dldfcn/fftw.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/fftw.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/qr.cc --- a/libinterp/dldfcn/qr.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/qr.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/symrcm.cc --- a/libinterp/dldfcn/symrcm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/symrcm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -322,7 +322,7 @@ return x.id; } -// Calculates the node's degrees. This means counting the non-zero elements +// Calculates the node's degrees. This means counting the nonzero elements // in the symmetric matrix' rows. This works for non-symmetric matrices // as well. @@ -341,7 +341,7 @@ { OCTAVE_QUIT; octave_idx_type k = ridx[i]; - // there is a non-zero element (k,j) + // there is a nonzero element (k,j) D[k]++; if (D[k] > max_deg) max_deg = D[k]; @@ -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 c59745865c7f -r dcb260e7a648 libinterp/dldfcn/tsearch.cc --- a/libinterp/dldfcn/tsearch.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/dldfcn/tsearch.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/genprops.awk --- a/libinterp/genprops.awk Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/genprops.awk Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/module.mk --- a/libinterp/octave-value/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-diag.cc --- a/libinterp/octave-value/ov-base-diag.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-diag.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-diag.h --- a/libinterp/octave-value/ov-base-diag.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-diag.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-int.cc --- a/libinterp/octave-value/ov-base-int.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-int.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-int.h --- a/libinterp/octave-value/ov-base-int.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-int.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-mat.cc --- a/libinterp/octave-value/ov-base-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-mat.h --- a/libinterp/octave-value/ov-base-mat.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-mat.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-scalar.cc --- a/libinterp/octave-value/ov-base-scalar.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-scalar.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-scalar.h --- a/libinterp/octave-value/ov-base-scalar.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-scalar.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-sparse.cc --- a/libinterp/octave-value/ov-base-sparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-sparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base-sparse.h --- a/libinterp/octave-value/ov-base-sparse.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base-sparse.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base.cc --- a/libinterp/octave-value/ov-base.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-base.h --- a/libinterp/octave-value/ov-base.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-base.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-bool-mat.cc --- a/libinterp/octave-value/ov-bool-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-bool-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 (); @@ -551,7 +552,7 @@ @deftypefn {Built-in Function} {} logical (@var{x})\n\ Convert the numeric object @var{x} to logical type.\n\ \n\ -Any non-zero values will be converted to true (1) while zero values\n\ +Any nonzero values will be converted to true (1) while zero values\n\ will be converted to false (0). The non-numeric value NaN cannot be\n\ converted and will produce an error.\n\ \n\ diff -r c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-bool-mat.h --- a/libinterp/octave-value/ov-bool-mat.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-bool-mat.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-bool-sparse.cc --- a/libinterp/octave-value/ov-bool-sparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-bool-sparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-bool.cc --- a/libinterp/octave-value/ov-bool.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-bool.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-cell.cc --- a/libinterp/octave-value/ov-cell.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-cell.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-cell.h --- a/libinterp/octave-value/ov-cell.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-cell.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-class.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 (); @@ -2054,7 +1950,7 @@ const Array cls = args(1).cellstr_value (); if (error_state) { - error ("isa: CLASSNAME must be a string or cell attay of strings"); + error ("isa: CLASSNAME must be a string or cell array of strings"); return retval; } @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-class.h --- a/libinterp/octave-value/ov-class.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-class.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-classdef.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/octave-value/ov-classdef.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-classdef.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/octave-value/ov-classdef.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-colon.cc --- a/libinterp/octave-value/ov-colon.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-colon.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-colon.h --- a/libinterp/octave-value/ov-colon.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-colon.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-complex.cc --- a/libinterp/octave-value/ov-complex.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-complex.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-cx-diag.cc --- a/libinterp/octave-value/ov-cx-diag.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-cx-diag.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-cx-mat.cc --- a/libinterp/octave-value/ov-cx-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-cx-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-cx-sparse.cc --- a/libinterp/octave-value/ov-cx-sparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-cx-sparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-fcn-handle.h --- a/libinterp/octave-value/ov-fcn-handle.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-fcn-inline.cc --- a/libinterp/octave-value/ov-fcn-inline.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-fcn-inline.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-fcn-inline.h --- a/libinterp/octave-value/ov-fcn-inline.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-fcn-inline.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-fcn.h --- a/libinterp/octave-value/ov-fcn.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-fcn.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-float.cc --- a/libinterp/octave-value/ov-float.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-float.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-flt-complex.cc --- a/libinterp/octave-value/ov-flt-complex.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-flt-complex.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-flt-cx-diag.cc --- a/libinterp/octave-value/ov-flt-cx-diag.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-flt-cx-diag.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-flt-cx-mat.cc --- a/libinterp/octave-value/ov-flt-cx-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-flt-cx-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-flt-re-diag.cc --- a/libinterp/octave-value/ov-flt-re-diag.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-flt-re-diag.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-flt-re-mat.cc --- a/libinterp/octave-value/ov-flt-re-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-flt-re-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-intx.h --- a/libinterp/octave-value/ov-intx.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-intx.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-java.cc --- a/libinterp/octave-value/ov-java.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-java.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-java.h --- a/libinterp/octave-value/ov-java.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-java.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-lazy-idx.h --- a/libinterp/octave-value/ov-lazy-idx.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-lazy-idx.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-oncleanup.cc --- a/libinterp/octave-value/ov-oncleanup.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-oncleanup.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-oncleanup.h --- a/libinterp/octave-value/ov-oncleanup.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-oncleanup.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-perm.cc --- a/libinterp/octave-value/ov-perm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-perm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -260,12 +260,10 @@ bool octave_perm_matrix::save_ascii (std::ostream& os) { - typedef octave_int idx_int_type; + os << "# size: " << matrix.rows () << "\n"; + os << "# orient: c\n"; - os << "# size: " << matrix.rows () << "\n"; - os << "# orient: " << (matrix.is_col_perm () ? 'c' : 'r') << '\n'; - - Array pvec = matrix.pvec (); + Array pvec = matrix.col_perm_vec (); octave_idx_type n = pvec.length (); ColumnVector tmp (n); for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1; @@ -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; @@ -317,18 +314,19 @@ { int32_t sz = matrix.rows (); - bool colp = matrix.is_col_perm (); + bool colp = true; os.write (reinterpret_cast (&sz), 4); os.write (reinterpret_cast (&colp), 1); - os.write (reinterpret_cast (matrix.data ()), - matrix.byte_size ()); + const Array& col_perm = matrix.col_perm_vec (); + os.write (reinterpret_cast (col_perm.data ()), + col_perm.byte_size ()); return true; } 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 +387,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 +449,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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-perm.h --- a/libinterp/octave-value/ov-perm.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-perm.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-range.cc --- a/libinterp/octave-value/ov-range.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-range.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-range.h --- a/libinterp/octave-value/ov-range.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-range.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-re-diag.cc --- a/libinterp/octave-value/ov-re-diag.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-re-diag.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-re-mat.cc --- a/libinterp/octave-value/ov-re-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-re-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-re-sparse.cc --- a/libinterp/octave-value/ov-re-sparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-re-sparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-scalar.cc --- a/libinterp/octave-value/ov-scalar.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-scalar.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-str-mat.cc --- a/libinterp/octave-value/ov-str-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-str-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-struct.cc --- a/libinterp/octave-value/ov-struct.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-struct.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-struct.h --- a/libinterp/octave-value/ov-struct.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-struct.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-usr-fcn.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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++) { @@ -849,7 +890,7 @@ { // Matlab gives up for histc, // so maybe it's ok that that we give up somtimes too? - error ("nargin: nargin information not available for builtin functions"); + error ("nargin: nargin information not available for built-in functions"); } } else @@ -971,7 +1012,7 @@ // without making intrusive changes to Octave. // Matlab gives up for histc, // so maybe it's ok that we give up somtimes too? - error ("nargout: nargout information not available for builtin functions."); + error ("nargout: nargout information not available for built-in functions."); } } else diff -r c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov-usr-fcn.h --- a/libinterp/octave-value/ov-usr-fcn.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov-usr-fcn.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave-value/ov.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/octave.cc --- a/libinterp/octave.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/octave.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/operators/op-b-b.cc --- a/libinterp/operators/op-b-b.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/operators/op-b-b.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/operators/op-cm-sm.cc --- a/libinterp/operators/op-cm-sm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/operators/op-cm-sm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/operators/op-int.h --- a/libinterp/operators/op-int.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/operators/op-int.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/operators/op-pm-sm.cc --- a/libinterp/operators/op-pm-sm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/operators/op-pm-sm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/operators/op-sbm-sbm.cc --- a/libinterp/operators/op-sbm-sbm.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/operators/op-sbm-sbm.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/lex.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/lex.ll Fri Aug 01 12:10:05 2014 -0400 @@ -54,6 +54,8 @@ %x DQ_STRING_START %x SQ_STRING_START +%x FQ_IDENT_START + %{ #include @@ -265,6 +267,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; @@ -272,11 +311,6 @@ // Internal variable for lexer debugging state. static bool lexer_debug_flag = false; -// Forward declarations for functions defined at the bottom of this -// file that are needed inside the lexer actions. - -static std::string strip_trailing_whitespace (char *s); - %} D [0-9] @@ -285,6 +319,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]+)) @@ -1017,6 +1052,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. %} @@ -1137,46 +1201,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 ()) { @@ -1191,7 +1234,7 @@ { curr_lexer->looking_for_object_index = true; - return curr_lexer->count_token_internal (SUPERCLASSREF); + return curr_lexer->count_token_internal (id_tok); } } } @@ -1200,9 +1243,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 ()) @@ -1218,7 +1260,7 @@ { curr_lexer->looking_for_object_index = true; - return curr_lexer->count_token_internal (METAQUERY); + return curr_lexer->count_token_internal (id_tok); } } } @@ -1886,21 +1928,6 @@ */ -// Used to delete trailing white space from tokens. - -static std::string -strip_trailing_whitespace (char *s) -{ - std::string retval = s; - - size_t pos = retval.find_first_of (" \t"); - - if (pos != std::string::npos) - retval.resize (pos); - - return retval; -} - DEFUN (__display_tokens__, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} __display_tokens__ ()\n\ @@ -1966,8 +1993,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; @@ -2369,20 +2398,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; @@ -2395,10 +2410,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; @@ -2584,6 +2598,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 () @@ -2755,36 +2797,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 (); @@ -2794,37 +2823,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. @@ -3382,6 +3415,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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/module.mk --- a/libinterp/parse-tree/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/oct-parse.in.yy Fri Aug 01 12:10:05 2014 -0400 @@ -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" @@ -161,6 +163,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; @@ -180,7 +184,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. @@ -207,21 +228,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 @@ -233,18 +255,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 @@ -254,25 +277,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 @@ -309,6 +334,8 @@ %destructor { delete $$; } %destructor { delete $$; } %destructor { delete $$; } +%destructor { delete $$; } +%destructor { delete $$; } %destructor { delete $$; } %destructor { delete $$; } %destructor { delete $$; } @@ -329,6 +356,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", @@ -436,11 +481,20 @@ 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); + } ; meta_identifier : METAQUERY - { $$ = new tree_identifier ($1->line (), $1->column ()); } + { + std::string class_nm = $1->text (); + + $$ = parser.make_meta_class_query (class_nm); + } ; string : DQ_STRING @@ -864,8 +918,6 @@ { $$ = $1; } | file { $$ = $1; } - | classdef - { $$ = $1; } ; // ===================== @@ -1291,6 +1343,13 @@ $$ = 0; } + | INPUT_FILE opt_nl classdef opt_sep END_OF_INPUT + { + if (lexer.reading_classdef_file) + parser.classdef_object = $3; + + $$ = 0; + } ; // =================== @@ -1333,12 +1392,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; } ; @@ -1349,6 +1410,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); } ; @@ -1408,158 +1477,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); } ; // ============= @@ -1657,6 +1867,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 (); @@ -1828,95 +2039,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 * @@ -1972,8 +2094,6 @@ e->preserve_base (); delete e; - // FIXME -- need to attempt constant folding here - // too (we need a generic way to do that). retval = base; } } @@ -2186,10 +2306,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. @@ -2218,10 +2335,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. @@ -2262,10 +2376,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. @@ -2302,10 +2413,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. @@ -2999,6 +3107,272 @@ lexer.looking_at_parameter_list = false; } +tree_funcall * +octave_base_parser::make_superclass_ref (const std::string& method_nm, + const std::string& class_nm) +{ + 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) +{ + 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 * @@ -3021,7 +3395,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 ()) { @@ -3048,6 +3423,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); @@ -3067,13 +3445,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); @@ -3461,6 +3843,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) { @@ -3494,6 +3877,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; @@ -3508,20 +3892,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) @@ -3562,7 +3963,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) { @@ -3626,6 +4028,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; @@ -3673,7 +4076,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, ""); @@ -3685,13 +4089,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 ()) { @@ -3901,7 +4306,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) @@ -4632,7 +5037,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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/octave.gperf --- a/libinterp/parse-tree/octave.gperf Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/octave.gperf Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/parse.h Fri Aug 01 12:10:05 2014 -0400 @@ -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,52 @@ void recover_from_parsing_function (void); + tree_funcall * + make_superclass_ref (const std::string& method_nm, + const std::string& class_nm); + + tree_funcall * + make_meta_class_query (const std::string& class_nm); + + 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 +432,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 +449,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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-all.h --- a/libinterp/parse-tree/pt-all.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-all.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-bp.cc --- a/libinterp/parse-tree/pt-bp.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-bp.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-bp.h --- a/libinterp/parse-tree/pt-bp.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-bp.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-cbinop.cc --- a/libinterp/parse-tree/pt-cbinop.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-cbinop.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-check.cc --- a/libinterp/parse-tree/pt-check.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-check.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-check.h --- a/libinterp/parse-tree/pt-check.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-check.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-classdef.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-classdef.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-classdef.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-classdef.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-eval.h --- a/libinterp/parse-tree/pt-eval.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-eval.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-exp.h --- a/libinterp/parse-tree/pt-exp.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-exp.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-funcall.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-funcall.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-funcall.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/parse-tree/pt-funcall.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-id.cc --- a/libinterp/parse-tree/pt-id.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-id.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-id.h --- a/libinterp/parse-tree/pt-id.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-id.h Fri Aug 01 12:10:05 2014 -0400 @@ -32,6 +32,7 @@ class tree_walker; +#include "oct-lvalue.h" #include "pt-bp.h" #include "pt-exp.h" #include "symtab.h" diff -r c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-idx.cc --- a/libinterp/parse-tree/pt-idx.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-idx.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-mat.cc --- a/libinterp/parse-tree/pt-mat.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-mat.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-pr-code.cc --- a/libinterp/parse-tree/pt-pr-code.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-pr-code.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-pr-code.h --- a/libinterp/parse-tree/pt-pr-code.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-pr-code.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-select.cc --- a/libinterp/parse-tree/pt-select.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-select.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/pt-walk.h --- a/libinterp/parse-tree/pt-walk.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/pt-walk.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/token.cc --- a/libinterp/parse-tree/token.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/token.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 libinterp/parse-tree/token.h --- a/libinterp/parse-tree/token.h Fri Aug 01 09:06:21 2014 -0400 +++ b/libinterp/parse-tree/token.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/Array.cc --- a/liboctave/array/Array.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/Array.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/CDiagMatrix.cc --- a/liboctave/array/CDiagMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/CDiagMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/CDiagMatrix.h --- a/liboctave/array/CDiagMatrix.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/CDiagMatrix.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/CMatrix.cc --- a/liboctave/array/CMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/CMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/CSparse.cc --- a/liboctave/array/CSparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/CSparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -1118,7 +1118,6 @@ { // Matrix is either singular or not positive definite mattype.mark_as_unsymmetric (); - typ = MatrixType::Full; } } @@ -1918,7 +1917,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -2014,7 +2013,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -2441,7 +2440,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -2537,7 +2536,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -2991,7 +2990,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -3100,7 +3099,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -3558,7 +3557,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -3667,7 +3666,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -4033,7 +4032,7 @@ work, b.rows (), err F77_CHAR_ARG_LEN (1))); - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -4315,7 +4314,7 @@ octave_idx_type b_nc = b.cols (); OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; @@ -4343,7 +4342,7 @@ break; } - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -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++) @@ -4735,7 +4734,7 @@ octave_idx_type b_nc = b.cols (); OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; @@ -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++) @@ -4909,7 +4908,7 @@ ldm, pipvt, work, b.rows (), err F77_CHAR_ARG_LEN (1))); - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -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++) @@ -5302,7 +5301,7 @@ octave_idx_type b_nc = b.cols (); OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; @@ -5329,7 +5328,7 @@ break; } - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -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++) @@ -5482,7 +5481,7 @@ ldm, pipvt, Bx, b.rows (), err F77_CHAR_ARG_LEN (1))); - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -6077,7 +6076,7 @@ OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr); #endif - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; @@ -6583,7 +6582,7 @@ OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; @@ -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; } @@ -7783,7 +7780,7 @@ EMPTY_RETURN_CHECK (SparseComplexMatrix); - // Count the number of non-zero elements + // Count the number of nonzero elements if (xmax (c, 0.) != 0.) { result = SparseComplexMatrix (nr, nc, c); @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/DiagArray2.cc --- a/liboctave/array/DiagArray2.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/DiagArray2.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/MSparse.cc --- a/liboctave/array/MSparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/MSparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/MatrixType.cc --- a/liboctave/array/MatrixType.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/MatrixType.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/PermMatrix.cc --- a/liboctave/array/PermMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/PermMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -36,8 +36,8 @@ ("PermMatrix: invalid permutation vector"); } -PermMatrix::PermMatrix (const Array& p, bool colp, bool check) - : Array (p), _colp(colp) +void +PermMatrix::setup (const Array& p, bool colp, bool check) { if (check) { @@ -47,12 +47,28 @@ Array::operator = (Array ()); } } + + if (!colp) + *this = this->transpose (); +} + +PermMatrix::PermMatrix (const Array& p) + : Array (p) +{ + setup (p, false, true); } -PermMatrix::PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n) - : Array (), _colp(colp) +PermMatrix::PermMatrix (const Array& p, bool colp, bool check) + : Array (p) +{ + setup (p, colp, check); +} + +void +PermMatrix::setup (const idx_vector& idx, bool colp, octave_idx_type n) { octave_idx_type len = idx.length (n); + if (! idx.is_permutation (len)) gripe_invalid_permutation (); else @@ -61,12 +77,28 @@ for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i); Array::operator = (idxa); } + + if (!colp) + *this = this->transpose (); +} + +PermMatrix::PermMatrix (const idx_vector& idx) + : Array () +{ + setup (idx, false, 0); +} + +PermMatrix::PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n) + : Array () +{ + setup (idx, colp, n); } PermMatrix::PermMatrix (octave_idx_type n) - : Array (dim_vector (n, 1)), _colp (false) + : Array (dim_vector (n, 1)) { - for (octave_idx_type i = 0; i < n; i++) xelem (i) = i; + for (octave_idx_type i = 0; i < n; i++) + xelem (i) = i; } octave_idx_type @@ -86,8 +118,13 @@ PermMatrix PermMatrix::transpose (void) const { - PermMatrix retval (*this); - retval._colp = ! retval._colp; + octave_idx_type len = Array::length (); + + PermMatrix retval (len); + + for (octave_idx_type i = 0; i < len; ++i) + retval.xelem (xelem (i)) = i; + return retval; } @@ -133,17 +170,20 @@ } PermMatrix -PermMatrix::power (octave_idx_type m) const +PermMatrix::power(octave_idx_type m) const +{ + if (m < 0) + return inverse ().pos_power (-m); + else if (m > 0) + return pos_power (m); + else + return PermMatrix (rows ()); +} + +PermMatrix +PermMatrix::pos_power (octave_idx_type m) const { octave_idx_type n = rows (); - bool res_colp = _colp; - if (m < 0) - { - res_colp = ! res_colp; - m = -m; - } - else if (m == 0) - return PermMatrix (n); const octave_idx_type *p = data (); Array res_pvec (dim_vector (n, 1), -1); @@ -176,43 +216,29 @@ } - return PermMatrix (res_pvec, res_colp, false); + return PermMatrix (res_pvec, true, false); } PermMatrix PermMatrix::eye (octave_idx_type n) { - Array p (dim_vector (n, 1)); - for (octave_idx_type i = 0; i < n; i++) - p(i) = i; - - return PermMatrix (p, false, false); + return PermMatrix (n); } PermMatrix operator *(const PermMatrix& a, const PermMatrix& b) { - const Array ia = a.pvec (); - const Array ib = b.pvec (); PermMatrix r; + + const Array ia = a.col_perm_vec (); + const Array ib = b.col_perm_vec (); + octave_idx_type n = a.columns (); + if (n != b.rows ()) gripe_nonconformant ("operator *", n, n, b.rows (), b.rows ()); - else if (a._colp == b._colp) - { - r = PermMatrix ((a._colp - ? ia.index (idx_vector (ib)) - : ib.index (idx_vector (ia))), a._colp, false); - } else - { - Array ra (dim_vector (n, 1)); - if (a._colp) - ra.assign (idx_vector (ia), ib); - else - ra.assign (idx_vector (ib), ia); - r = PermMatrix (ra, a._colp, false); - } + r = PermMatrix (ia.index (idx_vector (ib)), true, false); return r; } diff -r c59745865c7f -r dcb260e7a648 liboctave/array/PermMatrix.h --- a/liboctave/array/PermMatrix.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/PermMatrix.h Fri Aug 01 12:10:05 2014 -0400 @@ -31,20 +31,21 @@ class OCTAVE_API PermMatrix : protected Array { - public: - PermMatrix (void) : Array (), _colp (false) { } + PermMatrix (void) : Array () { } PermMatrix (octave_idx_type n); - PermMatrix (const Array& p, bool colp = false, - bool check = true); + PermMatrix (const Array& p) GCC_ATTR_DEPRECATED; + + PermMatrix (const Array& p, bool colp, bool check = true); - PermMatrix (const PermMatrix& m) - : Array (m), _colp(m._colp) { } + PermMatrix (const PermMatrix& m) : Array (m) { } - PermMatrix (const idx_vector& idx, bool colp = false, octave_idx_type n = 0); + PermMatrix (const idx_vector& idx) GCC_ATTR_DEPRECATED; + + PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n = 0); octave_idx_type dim1 (void) const { return Array::length (); } @@ -68,15 +69,13 @@ dim_vector dims (void) const { return dim_vector (dim1 (), dim2 ()); } - Array pvec (void) const + const Array& col_perm_vec (void) const { return *this; } octave_idx_type elem (octave_idx_type i, octave_idx_type j) const { - return (_colp - ? ((Array::elem (j) == i) ? 1 : 0) - : ((Array::elem (i) == j) ? 1 : 0)); + return (Array::elem (j) == i) ? 1 : 0; } octave_idx_type @@ -102,20 +101,8 @@ // Efficient integer power of a permutation. PermMatrix power (octave_idx_type n) const; - bool is_col_perm (void) const { return _colp; } - bool is_row_perm (void) const { return !_colp; } - - friend OCTAVE_API PermMatrix operator *(const PermMatrix& a, - const PermMatrix& b); - - const octave_idx_type *data (void) const - { return Array::data (); } - - const octave_idx_type *fortran_vec (void) const - { return Array::fortran_vec (); } - - octave_idx_type *fortran_vec (void) - { return Array::fortran_vec (); } + bool is_col_perm (void) const { return true; } + bool is_row_perm (void) const { return false; } void print_info (std::ostream& os, const std::string& prefix) const { Array::print_info (os, prefix); } @@ -123,12 +110,17 @@ static PermMatrix eye (octave_idx_type n); private: - bool _colp; + + PermMatrix pos_power (octave_idx_type m) const; + + void setup (const Array& p, bool colp, bool check); + + void setup (const idx_vector& idx, bool colp, octave_idx_type n); }; // Multiplying permutations together. PermMatrix OCTAVE_API -operator *(const PermMatrix& a, const PermMatrix& b); +operator * (const PermMatrix& a, const PermMatrix& b); #endif diff -r c59745865c7f -r dcb260e7a648 liboctave/array/Sparse.cc --- a/liboctave/array/Sparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/Sparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -61,18 +61,10 @@ for (octave_idx_type i = 0; i <= n; i++) cidx (i) = i; - const Array pv = a.pvec (); - - if (a.is_row_perm ()) - { - for (octave_idx_type i = 0; i < n; i++) - ridx (pv(i)) = i; - } - else - { - for (octave_idx_type i = 0; i < n; i++) - ridx (i) = pv(i); - } + const Array pv = a.col_perm_vec (); + + for (octave_idx_type i = 0; i < n; i++) + ridx (i) = pv(i); for (octave_idx_type i = 0; i < n; i++) data (i) = 1.0; @@ -657,7 +649,7 @@ octave_idx_type len = a.length (); octave_idx_type new_nzmx = 0; - // First count the number of non-zero terms + // First count the number of nonzero terms for (octave_idx_type i = 0; i < len; i++) if (a(i) != T ()) new_nzmx++; @@ -2427,7 +2419,7 @@ { octave_idx_type ndiag = (nnr < nnc) ? nnr : nnc; - // Count the number of non-zero elements + // Count the number of nonzero elements octave_idx_type nel = 0; if (k > 0) { @@ -2435,7 +2427,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 +2457,7 @@ } } } - else if ( k < 0) + else if (k < 0) { for (octave_idx_type i = 0; i < ndiag; i++) { @@ -2491,8 +2483,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 c59745865c7f -r dcb260e7a648 liboctave/array/Sparse.h --- a/liboctave/array/Sparse.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/Sparse.h Fri Aug 01 12:10:05 2014 -0400 @@ -242,7 +242,7 @@ Sparse& operator = (const Sparse& a); // Note that nzmax and capacity are the amount of storage for - // non-zero elements, while nnz is the actual number of non-zero + // nonzero elements, while nnz is the actual number of nonzero // terms. octave_idx_type nzmax (void) const { return rep->length (); } octave_idx_type capacity (void) const { return nzmax (); } diff -r c59745865c7f -r dcb260e7a648 liboctave/array/dDiagMatrix.cc --- a/liboctave/array/dDiagMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/dDiagMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/dDiagMatrix.h --- a/liboctave/array/dDiagMatrix.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/dDiagMatrix.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/dMatrix.cc --- a/liboctave/array/dMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/dMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -259,14 +259,10 @@ Matrix::Matrix (const PermMatrix& a) : MArray (a.dims (), 0.0) { - const Array ia (a.pvec ()); + const Array ia (a.col_perm_vec ()); octave_idx_type len = a.rows (); - if (a.is_col_perm ()) - for (octave_idx_type i = 0; i < len; i++) - elem (ia(i), i) = 1.0; - else - for (octave_idx_type i = 0; i < len; i++) - elem (i, ia(i)) = 1.0; + for (octave_idx_type i = 0; i < len; i++) + elem (ia(i), i) = 1.0; } // FIXME: could we use a templated mixed-type copy function here? @@ -1382,7 +1378,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 c59745865c7f -r dcb260e7a648 liboctave/array/dSparse.cc --- a/liboctave/array/dSparse.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/dSparse.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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; } } @@ -2005,7 +2004,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -2101,7 +2100,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -2530,7 +2529,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -2627,7 +2626,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -3085,7 +3084,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -3194,7 +3193,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -3653,7 +3652,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -3763,7 +3762,7 @@ } } - // Count non-zeros in work vector and adjust space in + // Count nonzeros in work vector and adjust space in // retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nc; i++) @@ -4130,7 +4129,7 @@ work, b.rows (), err F77_CHAR_ARG_LEN (1))); - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -4412,7 +4411,7 @@ OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; @@ -4459,7 +4458,7 @@ break; } - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -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++) @@ -4853,7 +4852,7 @@ octave_idx_type b_nc = b.cols (); OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; @@ -5027,7 +5026,7 @@ ldm, pipvt, work, b.rows (), err F77_CHAR_ARG_LEN (1))); - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -5474,7 +5473,7 @@ OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b volatile octave_idx_type x_nz = b.nnz (); volatile octave_idx_type ii = 0; @@ -5520,7 +5519,7 @@ break; } - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -5687,7 +5686,7 @@ ldm, pipvt, Bz, b.rows (), err F77_CHAR_ARG_LEN (1))); - // Count non-zeros in work vector and adjust + // Count nonzeros in work vector and adjust // space in retval if needed octave_idx_type new_nnz = 0; for (octave_idx_type i = 0; i < nr; i++) @@ -6246,7 +6245,7 @@ OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); OCTAVE_LOCAL_BUFFER (double, Xx, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; @@ -6743,7 +6742,7 @@ OCTAVE_LOCAL_BUFFER (double, Bx, b_nr); OCTAVE_LOCAL_BUFFER (double, Bz, b_nr); - // Take a first guess that the number of non-zero terms + // Take a first guess that the number of nonzero terms // will be as many as in b octave_idx_type x_nz = b.nnz (); octave_idx_type ii = 0; @@ -7743,7 +7742,7 @@ EMPTY_RETURN_CHECK (SparseMatrix); - // Count the number of non-zero elements + // Count the number of nonzero elements if (d < 0.) { result = SparseMatrix (nr, nc, d); @@ -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; } @@ -7893,7 +7893,7 @@ EMPTY_RETURN_CHECK (SparseMatrix); - // Count the number of non-zero elements + // Count the number of nonzero elements if (d > 0.) { result = SparseMatrix (nr, nc, d); @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fCDiagMatrix.cc --- a/liboctave/array/fCDiagMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fCDiagMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fCDiagMatrix.h --- a/liboctave/array/fCDiagMatrix.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fCDiagMatrix.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fCMatrix.cc --- a/liboctave/array/fCMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fCMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fCNDArray.cc --- a/liboctave/array/fCNDArray.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fCNDArray.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fCNDArray.h --- a/liboctave/array/fCNDArray.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fCNDArray.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fDiagMatrix.cc --- a/liboctave/array/fDiagMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fDiagMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fDiagMatrix.h --- a/liboctave/array/fDiagMatrix.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fDiagMatrix.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fMatrix.cc --- a/liboctave/array/fMatrix.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fMatrix.cc Fri Aug 01 12:10:05 2014 -0400 @@ -259,14 +259,10 @@ FloatMatrix::FloatMatrix (const PermMatrix& a) : MArray (a.dims (), 0.0) { - const Array ia (a.pvec ()); + const Array ia (a.col_perm_vec ()); octave_idx_type len = a.rows (); - if (a.is_col_perm ()) - for (octave_idx_type i = 0; i < len; i++) - elem (ia(i), i) = 1.0; - else - for (octave_idx_type i = 0; i < len; i++) - elem (i, ia(i)) = 1.0; + for (octave_idx_type i = 0; i < len; i++) + elem (ia(i), i) = 1.0; } // FIXME: could we use a templated mixed-type copy function here? @@ -1390,7 +1386,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 c59745865c7f -r dcb260e7a648 liboctave/array/fNDArray.cc --- a/liboctave/array/fNDArray.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fNDArray.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/fNDArray.h --- a/liboctave/array/fNDArray.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/fNDArray.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/intNDArray.cc --- a/liboctave/array/intNDArray.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/intNDArray.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/array/intNDArray.h --- a/liboctave/array/intNDArray.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/array/intNDArray.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/cruft/Faddeeva/Faddeeva.cc --- a/liboctave/cruft/Faddeeva/Faddeeva.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/cruft/Faddeeva/Faddeeva.cc Fri Aug 01 12:10:05 2014 -0400 @@ -694,7 +694,7 @@ else { const double pi = 3.14159265358979323846264338327950288419716939937510582; if (relerr > 0.1) relerr = 0.1; // not sensible to compute < 1 digit - a = pi / sqrt(-log(relerr*0.5)); + a = pi / sqrt(-gnulib::log(relerr*0.5)); c = (2/pi)*a; a2 = a*a; } diff -r c59745865c7f -r dcb260e7a648 liboctave/numeric/CmplxQRP.cc --- a/liboctave/numeric/CmplxQRP.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/CmplxQRP.cc Fri Aug 01 12:10:05 2014 -0400 @@ -103,7 +103,7 @@ RowVector ComplexQRP::Pvec (void) const { - Array pa (p.pvec ()); + Array pa (p.col_perm_vec ()); RowVector pv (MArray (pa) + 1.0); return pv; } diff -r c59745865c7f -r dcb260e7a648 liboctave/numeric/DASPK-opts.in --- a/liboctave/numeric/DASPK-opts.in Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/DASPK-opts.in Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/numeric/base-lu.cc --- a/liboctave/numeric/base-lu.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/base-lu.cc Fri Aug 01 12:10:05 2014 -0400 @@ -30,7 +30,7 @@ template base_lu::base_lu (const lu_type& l, const lu_type& u, const PermMatrix& p) - : a_fact (u), l_fact (l), ipvt (p.pvec ()) + : a_fact (u), l_fact (l), ipvt (p.transpose ().col_perm_vec ()) { if (l.columns () != u.rows ()) (*current_liboctave_error_handler) ("lu: dimension mismatch"); diff -r c59745865c7f -r dcb260e7a648 liboctave/numeric/bsxfun.h --- a/liboctave/numeric/bsxfun.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/bsxfun.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/numeric/dbleQRP.cc --- a/liboctave/numeric/dbleQRP.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/dbleQRP.cc Fri Aug 01 12:10:05 2014 -0400 @@ -100,7 +100,7 @@ RowVector QRP::Pvec (void) const { - Array pa (p.pvec ()); + Array pa (p.col_perm_vec ()); RowVector pv (MArray (pa) + 1.0); return pv; } diff -r c59745865c7f -r dcb260e7a648 liboctave/numeric/fCmplxQRP.cc --- a/liboctave/numeric/fCmplxQRP.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/fCmplxQRP.cc Fri Aug 01 12:10:05 2014 -0400 @@ -103,7 +103,7 @@ FloatRowVector FloatComplexQRP::Pvec (void) const { - Array pa (p.pvec ()); + Array pa (p.col_perm_vec ()); FloatRowVector pv (MArray (pa) + 1.0f); return pv; } diff -r c59745865c7f -r dcb260e7a648 liboctave/numeric/floatQRP.cc --- a/liboctave/numeric/floatQRP.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/floatQRP.cc Fri Aug 01 12:10:05 2014 -0400 @@ -100,7 +100,7 @@ FloatRowVector FloatQRP::Pvec (void) const { - Array pa (p.pvec ()); + Array pa (p.col_perm_vec ()); FloatRowVector pv (MArray (pa) + 1.0f); return pv; } diff -r c59745865c7f -r dcb260e7a648 liboctave/numeric/lo-mappers.cc --- a/liboctave/numeric/lo-mappers.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/lo-mappers.cc Fri Aug 01 12:10:05 2014 -0400 @@ -101,7 +101,7 @@ #if defined (M_LN2) static double ln2 = M_LN2; #else - static double ln2 = log (2); + static double ln2 = gnulib::log (2); #endif return std::log (x) / ln2; @@ -116,7 +116,7 @@ #if defined (M_LN2) static double ln2 = M_LN2; #else - static double ln2 = log (2); + static double ln2 = gnulib::log (2); #endif return exp (x * ln2); @@ -522,14 +522,16 @@ rc_log (double x) { const double pi = 3.14159265358979323846; - return x < 0.0 ? Complex (log (-x), pi) : Complex (log (x)); + return x < 0.0 ? Complex (gnulib::log (-x), pi) : Complex (gnulib::log (x)); } FloatComplex rc_log (float x) { const float pi = 3.14159265358979323846f; - return x < 0.0f ? FloatComplex (logf (-x), pi) : FloatComplex (logf (x)); + return (x < 0.0f + ? FloatComplex (gnulib::logf (-x), pi) + : FloatComplex (gnulib::logf (x))); } Complex diff -r c59745865c7f -r dcb260e7a648 liboctave/numeric/lo-specfun.cc --- a/liboctave/numeric/lo-specfun.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/lo-specfun.cc Fri Aug 01 12:10:05 2014 -0400 @@ -631,7 +631,7 @@ retval = 2 * (s + 1) * u; } else - retval = log (1 + x); + retval = gnulib::log (1 + x); return retval; } @@ -690,7 +690,7 @@ retval = 2 * (s + 1) * u; } else - retval = log (1 + x); + retval = gnulib::logf (1 + x); return retval; } @@ -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)); @@ -2984,13 +2976,15 @@ Complex rc_log1p (double x) { const double pi = 3.14159265358979323846; - return x < -1.0 ? Complex (log (-(1.0 + x)), pi) : Complex (log1p (x)); + return (x < -1.0 + ? Complex (gnulib::log (-(1.0 + x)), pi) + : Complex (log1p (x))); } FloatComplex rc_log1p (float x) { const float pi = 3.14159265358979323846f; - return x < -1.0f ? FloatComplex (logf (-(1.0f + x)), pi) + return x < -1.0f ? FloatComplex (gnulib::logf (-(1.0f + x)), pi) : FloatComplex (log1pf (x)); } @@ -3044,7 +3038,7 @@ else if (ax < 1.0) { // Tail region. - const double q = sqrt (-2*log (0.5*(1-ax))); + const double q = sqrt (-2*gnulib::log (0.5*(1-ax))); const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]; const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0; y = yn / yd * signum (-x); @@ -3122,7 +3116,7 @@ else if (x > 0.0 && x < 2.0) { // Tail region. - const double q = x < 1 ? sqrt (-2*log (0.5*x)) : sqrt (-2*log (0.5*(2-x))); + const double q = x < 1 ? sqrt (-2*gnulib::log (0.5*x)) : sqrt (-2*gnulib::log (0.5*(2-x))); const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]; const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0; y = yn / yd; @@ -3241,8 +3235,8 @@ if (temp <= acu && temp <= acu * value) { - value = value * exp (pp * log (xx) - + (qq - 1.0) * log (cx) - beta) / pp; + value = value * exp (pp * gnulib::log (xx) + + (qq - 1.0) * gnulib::log (cx) - beta) / pp; if (indx) { @@ -3340,7 +3334,7 @@ // Calculate the initial approximation. - r = sqrt (- log (a * a)); + r = sqrt (- gnulib::log (a * a)); ycur = r - (2.30753 + 0.27061 * r) / (1.0 + (0.99229 + 0.04481 * r) * r); @@ -3361,7 +3355,7 @@ if (t <= 0.0) { - value = 1.0 - exp ((log ((1.0 - a) * qq) + beta) / qq); + value = 1.0 - exp ((gnulib::log ((1.0 - a) * qq) + beta) / qq); } else { @@ -3369,7 +3363,7 @@ if (t <= 1.0) { - value = exp ((log (a * pp) + beta) / pp); + value = exp ((gnulib::log (a * pp) + beta) / pp); } else { @@ -3411,7 +3405,8 @@ } xin = value; - ycur = (ycur - a) * exp (beta + r * log (xin) + t * log (1.0 - xin)); + ycur = (ycur - a) * exp (beta + r * gnulib::log (xin) + + t * gnulib::log (1.0 - xin)); if (ycur * yprev <= 0.0) { @@ -3641,7 +3636,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 +3646,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 +3658,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 c59745865c7f -r dcb260e7a648 liboctave/numeric/randmtzig.c --- a/liboctave/numeric/randmtzig.c Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/numeric/randmtzig.c Fri Aug 01 12:10:05 2014 -0400 @@ -249,7 +249,7 @@ } } - state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ + state[0] = 0x80000000UL; /* MSB is 1; assuring nonzero initial array */ left = 1; initf = 1; } diff -r c59745865c7f -r dcb260e7a648 liboctave/operators/Sparse-op-defs.h --- a/liboctave/operators/Sparse-op-defs.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/operators/Sparse-op-defs.h Fri Aug 01 12:10:05 2014 -0400 @@ -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); \ @@ -1184,7 +1184,7 @@ { \ if (m1_nr != 0 || m1_nc != 0) \ { \ - /* Count num of non-zero elements */ \ + /* Count num of nonzero elements */ \ octave_idx_type nel = 0; \ for (octave_idx_type j = 0; j < m1_nc; j++) \ for (octave_idx_type i = 0; i < m1_nr; i++) \ @@ -1252,7 +1252,7 @@ { \ if (m1_nr != 0 || m1_nc != 0) \ { \ - /* Count num of non-zero elements */ \ + /* Count num of nonzero elements */ \ octave_idx_type nel = 0; \ for (octave_idx_type j = 0; j < m1_nc; j++) \ for (octave_idx_type i = 0; i < m1_nr; i++) \ @@ -1424,7 +1424,7 @@ { \ if (m1_nr != 0 || m1_nc != 0) \ { \ - /* Count num of non-zero elements */ \ + /* Count num of nonzero elements */ \ octave_idx_type nel = 0; \ for (octave_idx_type j = 0; j < m1_nc; j++) \ for (octave_idx_type i = 0; i < m1_nr; i++) \ @@ -1492,7 +1492,7 @@ { \ if (m1_nr != 0 || m1_nc != 0) \ { \ - /* Count num of non-zero elements */ \ + /* Count num of nonzero elements */ \ octave_idx_type nel = 0; \ for (octave_idx_type j = 0; j < m1_nc; j++) \ for (octave_idx_type i = 0; i < m1_nr; i++) \ @@ -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 (); \ \ @@ -1930,10 +1930,10 @@ retval.change_capacity (nel); \ /* The optimal break-point as estimated from simulations */ \ /* Note that Mergesort is O(nz log(nz)) while searching all */ \ - /* values is O(nr), where nz here is non-zero per row of */ \ + /* values is O(nr), where nz here is nonzero per row of */ \ /* length nr. The test itself was then derived from the */ \ /* simulation with random square matrices and the observation */ \ - /* of the number of non-zero elements in the output matrix */ \ + /* of the number of nonzero elements in the output matrix */ \ /* it was found that the breakpoints were */ \ /* nr: 500 1000 2000 5000 10000 */ \ /* nz: 6 25 97 585 2202 */ \ @@ -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 c59745865c7f -r dcb260e7a648 liboctave/operators/Sparse-perm-op-defs.h --- a/liboctave/operators/Sparse-perm-op-defs.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/operators/Sparse-perm-op-defs.h Fri Aug 01 12:10:05 2014 -0400 @@ -67,17 +67,7 @@ return SM (); } - if (p.is_row_perm ()) - { - // Form the column permutation and then call the colpm_sm routine. - const octave_idx_type *prow = p.pvec ().data (); - OCTAVE_LOCAL_BUFFER (octave_idx_type, pcol, nr); - for (octave_idx_type i = 0; i < nr; ++i) - pcol[prow[i]] = i; - return octinternal_do_mul_colpm_sm (pcol, a); - } - else - return octinternal_do_mul_colpm_sm (p.pvec ().data (), a); + return octinternal_do_mul_colpm_sm (p.col_perm_vec ().data (), a); } template @@ -163,10 +153,7 @@ return SM (); } - if (p.is_row_perm ()) - return octinternal_do_mul_sm_rowpm (a, p.pvec ().data ()); - else - return octinternal_do_mul_sm_colpm (a, p.pvec ().data ()); + return octinternal_do_mul_sm_colpm (a, p.col_perm_vec ().data ()); } #endif // octave_Sparse_perm_op_defs_h diff -r c59745865c7f -r dcb260e7a648 liboctave/operators/mx-inlines.cc --- a/liboctave/operators/mx-inlines.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/operators/mx-inlines.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/operators/mx-op-defs.h --- a/liboctave/operators/mx-op-defs.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/operators/mx-op-defs.h Fri Aug 01 12:10:05 2014 -0400 @@ -606,13 +606,8 @@ gripe_nonconformant ("operator *", p.rows (), p.columns (), nr, nc); \ else \ { \ - if (p.is_col_perm ()) \ - { \ - result = M (nr, nc); \ - result.assign (p.pvec (), idx_vector::colon, x); \ - } \ - else \ - result = x.index (p.pvec (), idx_vector::colon); \ + result = M (nr, nc); \ + result.assign (p.col_perm_vec (), idx_vector::colon, x); \ } \ \ return result; \ @@ -627,15 +622,7 @@ if (p.rows () != nc) \ gripe_nonconformant ("operator *", nr, nc, p.rows (), p.columns ()); \ else \ - { \ - if (p.is_col_perm ()) \ - result = x.index (idx_vector::colon, p.pvec ()); \ - else \ - { \ - result = M (nr, nc); \ - result.assign (idx_vector::colon, p.pvec (), x); \ - } \ - } \ + result = x.index (idx_vector::colon, p.col_perm_vec ()); \ \ return result; \ } diff -r c59745865c7f -r dcb260e7a648 liboctave/system/module.mk --- a/liboctave/system/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/system/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/system/tempnam.c --- a/liboctave/system/tempnam.c Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 liboctave/system/tempname.c --- a/liboctave/system/tempname.c Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 liboctave/util/base-list.h --- a/liboctave/util/base-list.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/util/base-list.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/util/caseless-str.h --- a/liboctave/util/caseless-str.h Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/util/caseless-str.h Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/util/data-conv.cc --- a/liboctave/util/data-conv.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/util/data-conv.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 liboctave/util/str-vec.cc --- a/liboctave/util/str-vec.cc Fri Aug 01 09:06:21 2014 -0400 +++ b/liboctave/util/str-vec.cc Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 m4/acinclude.m4 --- a/m4/acinclude.m4 Fri Aug 01 09:06:21 2014 -0400 +++ b/m4/acinclude.m4 Fri Aug 01 12:10:05 2014 -0400 @@ -1810,6 +1810,58 @@ fi ]) dnl +dnl Check for raw_fd_ostream API +dnl +AC_DEFUN([OCTAVE_LLVM_RAW_FD_OSTREAM_API], [ + AC_CACHE_CHECK([check LLVM::raw_fd_ostream arg type is llvm::sys:fs], + [octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs], + [AC_LANG_PUSH(C++) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #include + ]], [[ + std::string str; + llvm::raw_fd_ostream fout ("", str, llvm::sys::fs::F_Binary); + ]])], + octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs=yes, + octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs=no) + AC_LANG_POP(C++) + ]) + if test $octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs = yes; then + AC_DEFINE(RAW_FD_OSTREAM_ARG_IS_LLVM_SYS_FS, 1, + [Define to 1 if LLVM::raw_fd_ostream arg type is llvm::sys:fs.]) + fi +]) +dnl +dnl Check for legacy::PassManager API +dnl +AC_DEFUN([OCTAVE_LLVM_LEGACY_PASSMANAGER_API], [ + AC_CACHE_CHECK([check for LLVM::legacy::PassManager], + [octave_cv_legacy_passmanager], + [AC_LANG_PUSH(C++) + save_LIBS="$LIBS" + LIBS="$LLVM_LIBS $LIBS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + ]], [[ + llvm::Module *module; + llvm::legacy::PassManager *module_pass_manager; + llvm::legacy::FunctionPassManager *pass_manager; + module_pass_manager = new llvm::legacy::PassManager (); + pass_manager = new llvm::legacy::FunctionPassManager (module); + ]])], + octave_cv_legacy_passmanager=yes, + octave_cv_legacy_passmanager=no) + LIBS="$save_LIBS" + AC_LANG_POP(C++) + ]) + if test $octave_cv_legacy_passmanager = yes; then + AC_DEFINE(LEGACY_PASSMANAGER, 1, + [Define to 1 if LLVM::legacy::PassManager exists.]) + fi +]) +dnl dnl Check for ar. dnl AC_DEFUN([OCTAVE_PROG_AR], [ diff -r c59745865c7f -r dcb260e7a648 scripts/deprecated/bicubic.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/deprecated/bicubic.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/deprecated/default_save_options.m --- a/scripts/deprecated/default_save_options.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 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 Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/deprecated/gen_doc_cache.m --- a/scripts/deprecated/gen_doc_cache.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/interp1q.m --- a/scripts/deprecated/interp1q.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/isequalwithequalnans.m --- a/scripts/deprecated/isequalwithequalnans.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/java_convert_matrix.m --- a/scripts/deprecated/java_convert_matrix.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/java_debug.m --- a/scripts/deprecated/java_debug.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/java_invoke.m --- a/scripts/deprecated/java_invoke.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/java_new.m --- a/scripts/deprecated/java_new.m Fri Aug 01 09:06:21 2014 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +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_new (@var{name}) -## @deftypefnx {Loadable Function} {@var{obj} =} java_new (@var{name}, @var{arg1}, @dots{}) -## Create a Java object of class @var{name}, by calling the class constructor -## with the arguments @var{arg1}, @dots{} -## -## @example -## @group -## x = java_new ("java.lang.StringBuffer") -## x = java_new ("java.lang.StringBuffer", "Initial string") -## @end group -## @end example -## -## @seealso{javaObject, javaMethod} -## @end deftypefn - -function retval = java_new (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "java_new is obsolete and will be removed from a future version of Octave; please use javaObject instead"); - endif - - if (nargin < 1) - print_usage (); - endif - - retval = javaObject (varargin{:}); - -endfunction - diff -r c59745865c7f -r dcb260e7a648 scripts/deprecated/java_unsigned_conversion.m --- a/scripts/deprecated/java_unsigned_conversion.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/javafields.m --- a/scripts/deprecated/javafields.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/javamethods.m --- a/scripts/deprecated/javamethods.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/module.mk --- a/scripts/deprecated/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/deprecated/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -1,21 +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_invoke.m \ - deprecated/java_new.m \ - deprecated/java_unsigned_conversion.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 c59745865c7f -r dcb260e7a648 scripts/deprecated/nfields.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/deprecated/nfields.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/deprecated/re_read_readline_init_file.m --- a/scripts/deprecated/re_read_readline_init_file.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/read_readline_init_file.m --- a/scripts/deprecated/read_readline_init_file.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/deprecated/saving_history.m --- a/scripts/deprecated/saving_history.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/general/bicubic.m --- a/scripts/general/bicubic.m Fri Aug 01 09:06:21 2014 -0400 +++ /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 c59745865c7f -r dcb260e7a648 scripts/general/bincoeff.m diff -r c59745865c7f -r dcb260e7a648 scripts/general/cell2mat.m --- a/scripts/general/cell2mat.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/cell2mat.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/cplxpair.m --- a/scripts/general/cplxpair.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/cplxpair.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/del2.m --- a/scripts/general/del2.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/del2.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/fieldnames.m --- a/scripts/general/fieldnames.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/fieldnames.m Fri Aug 01 12:10:05 2014 -0400 @@ -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) @@ -70,9 +70,13 @@ %! s = struct (); %! assert (fieldnames (s), cell (0, 1)); -## test Java classname -%!testif HAVE_JAVA +## test Java classname by passing classname +%!testif HAVE_JAVA %! names = fieldnames ("java.lang.Double"); -%! search = strfind (names, "java.lang.Double.MAX_VALUE"); -%! assert (! isempty ([search{:}])); +%! assert (any (strcmp (names, "MAX_VALUE"))); +## test Java classname by passing java object +%!testif HAVE_JAVA +%! names = fieldnames (javaObject ("java.lang.Double", 10)); +%! assert (any (strcmp (names, "MAX_VALUE"))); + diff -r c59745865c7f -r dcb260e7a648 scripts/general/flipdim.m --- a/scripts/general/flipdim.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/flipdim.m Fri Aug 01 12:10:05 2014 -0400 @@ -62,7 +62,7 @@ %!assert (flipdim ([1,2;3,4], 2), [2,1;4,3]) %!assert (flipdim ([1,2;3,4], 3), [1,2;3,4]) -## FIXME -- we need tests for multidimensional arrays. +## FIXME: We need tests for multidimensional arrays. %!error flipdim () %!error flipdim (1, 2, 3) diff -r c59745865c7f -r dcb260e7a648 scripts/general/interp1.m --- a/scripts/general/interp1.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/interp1.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/interp2.m --- a/scripts/general/interp2.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/interp2.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/interp3.m --- a/scripts/general/interp3.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/interp3.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/interpn.m --- a/scripts/general/interpn.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/interpn.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/iscolumn.m --- a/scripts/general/iscolumn.m Fri Aug 01 09:06:21 2014 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} iscolumn (@var{x}) -## Return true if @var{x} is a column vector. -## @seealso{isrow, isscalar, isvector, ismatrix} -## @end deftypefn - -## Author: Rik Wehbring - -function retval = iscolumn (x) - - if (nargin != 1) - print_usage (); - endif - - sz = size (x); - retval = (ndims (x) == 2 && (sz(2) == 1)); - -endfunction - - -%!assert (iscolumn ([1, 2, 3]), false) -%!assert (iscolumn ([1; 2; 3])) -%!assert (iscolumn (1)) -%!assert (iscolumn ([]), false) -%!assert (iscolumn ([1, 2; 3, 4]), false) - -%!assert (iscolumn ("t")) -%!assert (iscolumn ("test"), false) -%!assert (iscolumn (["test"; "ing"]), false) - -%!test -%! s.a = 1; -%! assert (iscolumn (s)); - -%% Test input validation -%!error iscolumn () -%!error iscolumn ([1, 2], 2) - diff -r c59745865c7f -r dcb260e7a648 scripts/general/isequal.m --- a/scripts/general/isequal.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/isequal.m Fri Aug 01 12:10:05 2014 -0400 @@ -33,53 +33,133 @@ endfunction +## test empty input +%!assert (isequal ([], []), true) +%!assert (isequal ([], [], 1), false) +%!assert (isequal ([], 1, []), false) +%!assert (isequal (1, [], []), false) +%!assert (isequal (1, [], []), false) + ## test size and shape -%!assert (isequal ([1,2,3,4],[1,2,3,4]), true) -%!assert (isequal ([1;2;3;4],[1;2;3;4]), true) -%!assert (isequal ([1,2,3,4],[1;2;3;4]), false) -%!assert (isequal ([1,2,3,4],[1,2;3,4]), false) -%!assert (isequal ([1,2,3,4],[1,3;2,4]), false) +%!assert (isequal ([1,2,3,4], [1,2,3,4]), true) +%!assert (isequal ([1;2;3;4], [1;2;3;4]), true) +%!assert (isequal ([1,2,3,4], [1;2;3;4]), false) +%!assert (isequal ([1,2,3,4], [1,2;3,4]), false) +%!assert (isequal ([1,2,3,4], [1,3;2,4]), false) %!test %! A = 1:8; %! B = reshape (A, 2, 2, 2); %! assert (isequal (A, B), false); - %!test %! A = reshape (1:8, 2, 2, 2); %! B = A; %! assert (isequal (A, B), true); - %!test %! A = reshape (1:8, 2, 4); %! B = reshape (A, 2, 2, 2); %! assert (isequal (A, B), false); -## test for equality -%!assert (isequal ([1,2,3,4],[1,2,3,4]), true) -%!assert (isequal (['a','b','c','d'],['a','b','c','d']), true) -## Test multi-line strings -%!assert (isequal (["test";"strings"],["test";"strings"],["test";"strings"]), true) -## test for inequality -%!assert (isequal ([1,2,3,4],[1;2;3;4]), false) -%!assert (isequal ({1,2,3,4},[1,2,3,4]), false) -%!assert (isequal ([1,2,3,4],{1,2,3,4}), false) -%!assert (isequal ([1,2,NaN,4],[1,2,NaN,4]), false) -%!assert (isequal (['a','b','c','d'],['a';'b';'c';'d']), false) -%!assert (isequal ({'a','b','c','d'},{'a';'b';'c';'d'}), false) -## test for equality (struct) -%!assert (isequal (struct ('a',1,'b',2),struct ('a',1,'b',2)), true) -%!assert (isequal (struct ('a',1,'b',2),struct ('a',1,'b',2),struct ('a',1,'b',2)), true) -%!assert (isequal (struct ('a',"abc",'b',2),struct ('a',"abc",'b',2)), true) -## test for inequality (struct) -%!assert (isequal (struct ('a',NaN,'b',2),struct ('a',NaN,'b',2),struct ('a',NaN,'b',2)), false) +## test all numeric built-in primitives +%!assert (isequal (false, logical (0), char (0), +%! int8 (0), int16 (0), int32 (0), int64 (0), +%! uint8 (0), uint16 (0), uint32 (0), uint64 (0), +%! double (0), single (0), +%! double (complex (0,0)), single (complex (0,0))), +%! true) +%!assert (isequal (true, logical (1), char (1), +%! int8 (1), int16 (1), int32 (1), int64 (1), +%! uint8 (1), uint16 (1), uint32 (1), uint64 (1), +%! double (1), single (1), +%! double (complex (1,0)), single (complex (1,0))), +%! true) + +## test characters and strings +%!assert (isequal ('a', "a"), true) +%!assert (isequal ("abab", ["a", "b", "a", "b"]), true) +%!assert (isequal (["a","b","c","d"], ["a","b","c","d"]), true) +%!assert (isequal (["test ";"strings"], ["test ";"strings"], +%! ["test ";"strings"]), true) +%!assert (isequal (["a","b","c","d"], ["a";"b";"c";"d"]), false) + +## test function_handle +%!test +%! fcn = @(x) x.^2; +%! assert (isequal (fcn, fcn), true); +%! assert (isequal (fcn, @(x) x.^2), false); +%! assert (isequal (@(x) x.^2, fcn), false); + +## test structures +%!assert (isequal (struct ([]),struct ([])), true) +%!assert (isequal (struct ("a",1), struct ("a",1)), true) +%!assert (isequal (struct ("a",1), struct ("a",2)), false) +%!assert (isequal (struct ("a",1), struct ("b",1)), false) +%!assert (isequal (struct ("a",1,"b",2), struct ("a",1,"b",2)), true) +%!assert (isequal (struct ("a",1,"b",2), struct ("b",2,"a",1)), true) +%!assert (isequal (struct ("a",1,"b",2), struct ("a",1,"b",2), +%! struct ("a",1,"b",2)), true) +%!assert (isequal (struct ("a","abc","b",2), struct ("a","abc","b",2)), true) + +## recursive structure +%!test +%! x.a = "a1"; +%! x.b.a = "ba1"; +%! x.b.b = "bb1"; +%! assert (isequal (x, x, x), true); +%! y = x; +%! y.b.b = "bb2"; +%! assert (isequal (x, y), false); +%! y = x; +%! y.b = rmfield (y.b, "b"); +%! y.b.b.a = "bba1"; +%! assert (isequal (x, y), false); + +## test cells +%!assert (isequal (cell (1,1), cell (1,1)), true) +%!assert (isequal (cell (1,1), cell (1,2)), false) +%!assert (isequal ({"a",1}, {"a",1}), true) +%!assert (isequal ({"a",1}, {"a",2}), false) +%!assert (isequal ({"a",1}, {"b",1}), false) +%!assert (isequal ({"a",1,"b",2}, {"a",1,"b",2}), true) +%!assert (isequal ({"a",1,"b",2}, {"b",2,"a",1}), false) +%!assert (isequal ({"a",1,"b",2}, {"a",1,"b",2}, {"a",1,"b",2}), true) +%!assert (isequal ({"a","abc","b",2}, {"a","abc","b",2}), true) +%!assert (isequal ({"a","b","c","d"}, {"a","b","c","d"}), true) +%!assert (isequal ({"a","b","c","d"}, {"a";"b";"c";"d"}), false) +%!assert (isequal (["a","b","c","d"], {"a","b","c","d"}), false) + +## recursive cell +%!test +%! x = cell (1,3); +%! x{1} = {[1], [1 2]}; +%! x{2} = true; +%! x{3} = {{"hello"}, {"world"}}; +%! assert (isequal (x, x)); +%! y = x; +%! y{3}{1}{1} = "goodbye"; +%! assert (isequal (x, y), false); ## test for sparse matrices +%!assert (isequal (sparse ([]), []), true) +%!assert (isequal ([], sparse ([])), true) %!assert (isequal (sparse (0,1), sparse (0,1)), true) +%!assert (isequal (sparse (0,1), zeros (0,1)), true) +%!assert (isequal (sparse (2,2), sparse (2,2)), true) +%!assert (isequal (zeros (2,2), sparse (2,2)), true) +%!assert (isequal (speye (1), eye (1)), true) +%!assert (isequal (eye (300), speye (300)), true) %!assert (isequal (sparse (0,1), sparse (1,0)), false) -%!assert (isequal (sparse (2, 2), sparse (2, 2)), true) -## Input validation +## test NaN +%!assert (isequal (NaN, NaN), false) +%!assert (isequal (NaN, Inf), false) +%!assert (isequal (NaN, 1.0), false) +%!assert (isequal ([1,2,NaN,4], [1,2,NaN,4]), false) +%!assert (isequal (struct ("a",NaN,"b",2), struct ("a",NaN,"b",2), +%! struct ("a",NaN,"b",2)), false) + +## test input validation %!error isequal () %!error isequal (1) +%!error isequal ([1,1]) diff -r c59745865c7f -r dcb260e7a648 scripts/general/isequaln.m --- a/scripts/general/isequaln.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/isequaln.m Fri Aug 01 12:10:05 2014 -0400 @@ -36,13 +36,14 @@ ## test for equality -%!assert (isequaln ({1,2,NaN,4},{1,2,NaN,4}), true) -%!assert (isequaln ([1,2,NaN,4],[1,2,NaN,4]), true) +%!assert (isequaln ({1,2,NaN,4}, {1,2,NaN,4}), true) +%!assert (isequaln ([1,2,NaN,4], [1,2,NaN,4]), true) ## test for inequality -%!assert (isequaln ([1,2,NaN,4],[1,NaN,3,4]), false) -%!assert (isequaln ([1,2,NaN,4],[1,2,3,4]), false) +%!assert (isequaln ([1,2,NaN,4], [1,NaN,3,4]), false) +%!assert (isequaln ([1,2,NaN,4], [1,2,3,4]), false) ## test for equality (struct) -%!assert (isequaln (struct ('a',NaN,'b',2),struct ('a',NaN,'b',2),struct ('a',NaN,'b',2)), true) +%!assert (isequaln (struct ("a",NaN,"b",2), struct ("a",NaN,"b",2), +%! struct ("a",NaN,"b",2)), true) %!assert (isequaln (1,2,1), false) ## Input validation diff -r c59745865c7f -r dcb260e7a648 scripts/general/isrow.m --- a/scripts/general/isrow.m Fri Aug 01 09:06:21 2014 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -## 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 -## . - -## -*- texinfo -*- -## @deftypefn {Function File} {} isrow (@var{x}) -## Return true if @var{x} is a row vector. -## @seealso{iscolumn, isscalar, isvector, ismatrix} -## @end deftypefn - -## Author: Rik Wehbring - -function retval = isrow (x) - - if (nargin != 1) - print_usage (); - endif - - sz = size (x); - retval = (ndims (x) == 2 && (sz(1) == 1)); - -endfunction - - -%!assert (isrow ([1, 2, 3])) -%!assert (isrow ([1; 2; 3]), false) -%!assert (isrow (1)) -%!assert (isrow ([]), false) -%!assert (isrow ([1, 2; 3, 4]), false) - -%!assert (isrow ("t")) -%!assert (isrow ("test")) -%!assert (isrow (["test"; "ing"]), false) - -%!test -%! s.a = 1; -%! assert (isrow (s)); - -%% Test input validation -%!error isrow () -%!error isrow ([1, 2], 2) - diff -r c59745865c7f -r dcb260e7a648 scripts/general/isscalar.m --- a/scripts/general/isscalar.m Fri Aug 01 09:06:21 2014 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -## Copyright (C) 1996-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 {Function File} {} isscalar (@var{x}) -## Return true if @var{x} is a scalar. -## @seealso{isvector, ismatrix} -## @end deftypefn - -## Author: jwe - -function retval = isscalar (x) - - if (nargin != 1) - print_usage (); - endif - - retval = numel (x) == 1; - -endfunction - - -%!assert (isscalar (1)) -%!assert (isscalar ([1, 2]), false) -%!assert (isscalar ([]), false) -%!assert (isscalar ([1, 2; 3, 4]), false) - -%!assert (isscalar ("t")) -%!assert (isscalar ("test"), false) -%!assert (isscalar (["test"; "ing"]), false) - -%!test -%! s.a = 1; -%! assert (isscalar (s)); - -%% Test input validation -%!error isscalar () -%!error isscalar (1, 2) - diff -r c59745865c7f -r dcb260e7a648 scripts/general/issquare.m --- a/scripts/general/issquare.m Fri Aug 01 09:06:21 2014 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -## Copyright (C) 1996-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 {Function File} {} issquare (@var{x}) -## Return true if @var{x} is a square matrix. -## @seealso{isscalar, isvector, ismatrix, size} -## @end deftypefn - -## Author: A. S. Hodel -## Created: August 1993 -## Adapted-By: jwe - -function retval = issquare (x) - - if (nargin != 1) - print_usage (); - endif - - if (ndims (x) == 2) - [r, c] = size (x); - retval = r == c; - else - retval = false; - endif - -endfunction - - -%!assert (issquare ([])) -%!assert (issquare (1)) -%!assert (! issquare ([1, 2])) -%!assert (issquare ([1, 2; 3, 4])) -%!assert (! issquare ([1, 2; 3, 4; 5, 6])) -%!assert (! issquare (ones (3,3,3))) -%!assert (issquare ("t")) -%!assert (! issquare ("test")) -%!assert (issquare (["test"; "ing"; "1"; "2"])) -%!test -%! s.a = 1; -%! assert (issquare (s)); -%!assert (issquare ({1, 2; 3, 4})) -%!assert (sparse (([1, 2; 3, 4]))) - -%% Test input validation -%!error issquare () -%!error issquare ([1, 2; 3, 4], 2) - diff -r c59745865c7f -r dcb260e7a648 scripts/general/isvector.m --- a/scripts/general/isvector.m Fri Aug 01 09:06:21 2014 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -## Copyright (C) 1996-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 {Function File} {} isvector (@var{x}) -## Return true if @var{x} is a vector. A vector is a 2-D array -## where one of the dimensions is equal to 1. As a consequence a -## 1x1 array, or scalar, is also a vector. -## @seealso{isscalar, ismatrix, size, rows, columns, length} -## @end deftypefn - -## Author: jwe - -function retval = isvector (x) - - if (nargin != 1) - print_usage (); - endif - - sz = size (x); - retval = (ndims (x) == 2 && (sz(1) == 1 || sz(2) == 1)); - -endfunction - - -%!assert (isvector (1)) -%!assert (isvector ([1; 2; 3])) -%!assert (isvector ([]), false) -%!assert (isvector ([1, 2; 3, 4]), false) - -%!assert (isvector ("t")) -%!assert (isvector ("test")) -%!assert (isvector (["test"; "ing"]), false) - -%!test -%! s.a = 1; -%! assert (isvector (s)); - -%% Test input validation -%!error isvector () -%!error isvector ([1, 2], 2) - diff -r c59745865c7f -r dcb260e7a648 scripts/general/module.mk --- a/scripts/general/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -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 \ @@ -40,14 +39,9 @@ general/interp3.m \ general/interpn.m \ general/interpft.m \ - general/iscolumn.m \ general/isdir.m \ general/isequal.m \ general/isequaln.m \ - general/isrow.m \ - general/isscalar.m \ - general/issquare.m \ - general/isvector.m \ general/loadobj.m \ general/logspace.m \ general/methods.m \ diff -r c59745865c7f -r dcb260e7a648 scripts/general/prepad.m --- a/scripts/general/prepad.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/prepad.m Fri Aug 01 12:10:05 2014 -0400 @@ -97,7 +97,7 @@ %!assert (prepad ([1,2], 2, 2, 3), reshape ([2,2,1,2], 1, 2, 2)) %!assert (prepad ([1;2], 2, 2, 3), reshape ([2;2;1;2], 2, 1, 2)) -## FIXME -- we need tests for multidimensional arrays. +## FIXME: We need tests for multidimensional arrays. %!error prepad () %!error prepad (1) diff -r c59745865c7f -r dcb260e7a648 scripts/general/private/__isequal__.m --- a/scripts/general/private/__isequal__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/private/__isequal__.m Fri Aug 01 12:10:05 2014 -0400 @@ -33,17 +33,19 @@ ## Algorithm: ## ## 1. Determine the class of x -## 2. If x is of the struct, cell, list or char class, for each -## argument after x, determine whether it has the same class -## and size as x. -## Otherwise, for each argument after x, verify that it is not -## of the struct, cell, list or char class, and that it has -## the same size as x. +## 2. If x and all other arguments have the same class, then check that the +## number of dimensions and then the size of each dimension match. +## If not all arguments share the same class, then verify that all of the +## arguments belong to a comparable "numeric" class which includes +## numeric, logical, and character arrays. Check that number of dimensions +## and size of each dimension match. ## 3. For each argument after x, compare it for equality with x: ## a. struct compare each member by name, not by order (recursive) -## b. cell/list compare each member by order (recursive) -## c. char compare each member with strcmp -## d. compare each nonzero member, and assume NaN == NaN +## b. object converted to struct, and then compared as stated above +## c. cell compare each member by order (recursive) +## d. char compare each member with strcmp +## e fcn_handle compare using overloade 'eq' operator +## f. compare each nonzero member, and assume NaN == NaN ## if nans_compare_equal is nonzero. function t = __isequal__ (nans_compare_equal, x, varargin) @@ -53,39 +55,31 @@ ## Generic tests. ## All arguments must either be of the same class or they must be - ## numeric values. + ## "numeric" values. t = (all (strcmp (class (x), cellfun ("class", varargin, "uniformoutput", false))) - || ((isnumeric (x) || islogical (x)) - && all (cellfun ("isnumeric", varargin) - | cellfun ("islogical", varargin)))); + || ((isreal (x) || isnumeric (x)) + && all (cellfun ("isreal", varargin) + | cellfun ("isnumeric", varargin)))); if (t) ## Test that everything has the same number of dimensions. - s_x = size (x); - s_v = cellfun (@size, varargin, "uniformoutput", false); - t = all (length (s_x) == cellfun ("length", s_v)); + t = all (ndims (x) == cellfun ("ndims", varargin)); endif if (t) - ## Test that everything is the same size since it has the same - ## dimensionality. - l_x = length (s_x); - s_v = reshape ([s_v{:}], length (s_x), []); - idx = 0; - while (t && idx < l_x) - idx++; - t = all (s_x(idx) == s_v(idx,:)); - endwhile + ## Test that everything is the same size since the dimensionality matches. + nd = ndims (x); + k = 1; + do + t = all (size (x,k) == cellfun ("size", varargin, k)); + until (!t || k++ == nd); endif ## From here on, compare objects as if they were structures. - if (isobject (x)) + if (t && isobject (x)) x = builtin ("struct", x); for i = 1:numel (varargin) - if (! isobject (varargin{i})) - break; - endif varargin{i} = builtin ("struct", varargin{i}); endfor endif @@ -95,9 +89,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 ("numel", fn_v)); ## Test that all the names are equal. idx = 0; @@ -112,12 +106,12 @@ while (t && idx < l_fn_x) ## Test that all field values are equal. idx++; - args = {nans_compare_equal, {x.(fn_x{idx})}}; + args = cell (1, 2+l_v); + args(1:2) = {nans_compare_equal, {x.(fn_x{idx})}}; for argn = 1:l_v args{argn+2} = {varargin{argn}.(fn_x{idx})}; endfor - ## Minimize function calls by calling for all the arguments at - ## once. + ## Minimize function calls by calling for all the arguments at once. t = __isequal__ (args{:}); endwhile @@ -127,24 +121,24 @@ idx = 0; while (t && idx < l_x) idx++; - args = {nans_compare_equal, x{idx}}; - for p = 1:l_v - args{p+2} = varargin{p}{idx}; - endfor + args = cell (1, 2+l_v); + args(1:2) = {nans_compare_equal, x{idx}}; + args(3:end) = [cellindexmat(varargin, idx){:}]; + t = __isequal__ (args{:}); endwhile - elseif (ischar (x)) - + elseif (ischar (x) && all (cellfun ("isclass", varargin, "char"))) ## Sizes are equal already, so we can just make everything into a ## row and test the rows. + n_x = numel (x); + strings = cell (1, l_v); for i = 1:l_v - strings{i} = reshape (varargin{i}, 1, []); + strings{i} = reshape (varargin{i}, 1, n_x); endfor - t = all (strcmp (reshape (x, 1, []), strings)); + t = all (strcmp (reshape (x, 1, n_x), strings)); elseif (isa (x, "function_handle")) - ## The == operator is overloaded for handles. t = all (cellfun ("eq", {x}, varargin)); @@ -179,11 +173,5 @@ endif endif - if (!t) - t = false; - else - t = true; - endif - endfunction diff -r c59745865c7f -r dcb260e7a648 scripts/general/profshow.m --- a/scripts/general/profshow.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/profshow.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/general/rotdim.m --- a/scripts/general/rotdim.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/general/rotdim.m Fri Aug 01 12:10:05 2014 -0400 @@ -152,8 +152,8 @@ %!assert (rotdim (m, 3), rotdim (m, -1)) %!assert (rotdim (m, 1), rotdim (m)) -## FIXME -- we need tests for multidimensional arrays and different -## values of PLANE. +## FIXME: We need tests for multidimensional arrays +## and different values of PLANE. %!error rotdim () %!error rotdim (1, 2, 3, 4) diff -r c59745865c7f -r dcb260e7a648 scripts/geometry/voronoi.m --- a/scripts/geometry/voronoi.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/geometry/voronoi.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/gui/errordlg.m diff -r c59745865c7f -r dcb260e7a648 scripts/gui/helpdlg.m diff -r c59745865c7f -r dcb260e7a648 scripts/gui/inputdlg.m diff -r c59745865c7f -r dcb260e7a648 scripts/gui/listdlg.m diff -r c59745865c7f -r dcb260e7a648 scripts/gui/module.mk --- a/scripts/gui/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/gui/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -3,6 +3,7 @@ gui_PRIVATE_FCN_FILES = \ gui/private/__file_filter__.m \ gui/private/__fltk_file_filter__.m \ + gui/private/__get_funcname__.m \ gui/private/__is_function__.m \ gui/private/__uigetdir_fltk__.m \ gui/private/__uigetfile_fltk__.m \ diff -r c59745865c7f -r dcb260e7a648 scripts/gui/msgbox.m diff -r c59745865c7f -r dcb260e7a648 scripts/gui/private/__get_funcname__.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/gui/private/__get_funcname__.m Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,42 @@ +## Copyright (C) 2014 Andreas Weber +## +## 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{funcname} =} __get_funcname__ (@var{basename}) +## Internal function. +## +## Build function name for the current graphics toolkit according to schema +## __[basename]_[graphics_toolkit]__, use fltk as default. +## @end deftypefn + +## Author: Andreas Weber + +function funcname = __get_funcname__ (basename) + + if (! __octave_link_enabled__ ()) + tk = graphics_toolkit (); + funcname = strcat ("__", basename, "_", tk, "__"); + if ((numel (tk) > 0) && (! strcmp(tk, "fltk")) && (! __is_function__ (funcname))) + warning ("%s: no implementation for toolkit '%s', using 'fltk' instead",basename, tk); + endif + funcname = strcat ("__", basename, "_fltk__"); + else + funcname = ""; + endif + +endfunction diff -r c59745865c7f -r dcb260e7a648 scripts/gui/private/__is_function__.m --- a/scripts/gui/private/__is_function__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/gui/private/__is_function__.m Fri Aug 01 12:10:05 2014 -0400 @@ -26,7 +26,7 @@ function result = __is_function__ (func) existval = exist (func); - result = (existval == 2 || existval == 3 || existval == 5 || existval == 6); + result = (existval == 2 || existval == 3 || existval == 5); endfunction diff -r c59745865c7f -r dcb260e7a648 scripts/gui/private/message_dialog.m diff -r c59745865c7f -r dcb260e7a648 scripts/gui/questdlg.m diff -r c59745865c7f -r dcb260e7a648 scripts/gui/uigetdir.m --- a/scripts/gui/uigetdir.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/gui/uigetdir.m Fri Aug 01 12:10:05 2014 -0400 @@ -30,20 +30,7 @@ function dirname = uigetdir (init_path = pwd, dialog_name = "Select Directory to Open") - if (! __octave_link_enabled__ ()) - defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); - funcname = ["__uigetdir_", defaulttoolkit, "__"]; - functype = exist (funcname); - if (! __is_function__ (funcname)) - funcname = "__uigetdir_fltk__"; - if (! __is_function__ (funcname)) - error ("uigetdir: fltk graphics toolkit required"); - elseif (! strcmp (defaulttoolkit, "gnuplot")) - warning ("uigetdir: no implementation for toolkit '%s', using 'fltk' instead", - defaulttoolkit); - endif - endif - endif + funcname = __get_funcname__ (mfilename ()); if (nargin > 2) print_usage (); diff -r c59745865c7f -r dcb260e7a648 scripts/gui/uigetfile.m --- a/scripts/gui/uigetfile.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/gui/uigetfile.m Fri Aug 01 12:10:05 2014 -0400 @@ -66,21 +66,8 @@ function [retfile, retpath, retindex] = uigetfile (varargin) - if (! __octave_link_enabled__ ()) - defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); - funcname = ["__uigetfile_", defaulttoolkit, "__"]; - functype = exist (funcname); - if (! __is_function__ (funcname)) - funcname = "__uigetfile_fltk__"; - if (! __is_function__ (funcname)) - error ("uigetfile: fltk graphics toolkit required"); - elseif (! strcmp (defaulttoolkit, "gnuplot")) - warning ("uigetfile: no implementation for toolkit '%s', using 'fltk' instead", - defaulttoolkit); - endif - endif - endif - + funcname = __get_funcname__ (mfilename ()); + if (nargin > 7) error ("uigetfile: number of input arguments must be less than eight"); endif diff -r c59745865c7f -r dcb260e7a648 scripts/gui/uiputfile.m --- a/scripts/gui/uiputfile.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/gui/uiputfile.m Fri Aug 01 12:10:05 2014 -0400 @@ -56,20 +56,7 @@ function [retfile, retpath, retindex] = uiputfile (varargin) - if (! __octave_link_enabled__ ()) - defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); - funcname = ["__uiputfile_", defaulttoolkit, "__"]; - functype = exist (funcname); - if (! __is_function__ (funcname)) - funcname = "__uiputfile_fltk__"; - if (! __is_function__ (funcname)) - error ("uiputfile: fltk graphics toolkit required"); - elseif (! strcmp (defaulttoolkit, "gnuplot")) - warning ("uiputfile: no implementation for toolkit '%s', using 'fltk' instead", - defaulttoolkit); - endif - endif - endif + funcname = __get_funcname__ (mfilename ()); if (nargin > 3) print_usage (); diff -r c59745865c7f -r dcb260e7a648 scripts/gui/warndlg.m diff -r c59745865c7f -r dcb260e7a648 scripts/help/__unimplemented__.m --- a/scripts/help/__unimplemented__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/help/__unimplemented__.m Fri Aug 01 12:10:05 2014 -0400 @@ -103,7 +103,7 @@ ## control system case {"absorbDelay", "allmargin", "append", "augstate", "balreal", ... - "balred", "balredOptions", "bandwidth", "bdschur", "bode", ... + "balred", "balredOptions", "bdschur", "bode", ... "bodemag", "bodeoptions", "bodeplot", "c2d", "c2dOptions", ... "canon", "care", "chgFreqUnit", "chgTimeUnit", "connect", ... "connectOptions", "covar", "ctrb", "ctrbf", "ctrlpref", "d2c", ... @@ -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", @@ -736,7 +730,6 @@ "ordqz", "ordschur", "padecoef", - "pan", "parseSoapResponse", "pathtool", "pcode", @@ -761,7 +754,6 @@ "readasync", "rng", "rotate", - "rotate3d", "scatteredInterpolant", "selectmoveresize", "sendmail", diff -r c59745865c7f -r dcb260e7a648 scripts/help/doc.m --- a/scripts/help/doc.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/help/doc.m Fri Aug 01 12:10:05 2014 -0400 @@ -42,7 +42,7 @@ if (nargin == 1) ## Get the directory where the function lives. - ## FIXME -- maybe we should have a better way of doing this. + ## FIXME: Maybe we should have a better way of doing this? if (ischar (fname)) ftype = exist (fname); @@ -86,7 +86,7 @@ endif endif - ## FIXME -- don't change the order of the arguments below because + ## FIXME: Don't change the order of the arguments below because ## the info-emacs-info script currently expects --directory DIR as ## the third and fourth arguments. Someone should fix that. diff -r c59745865c7f -r dcb260e7a648 scripts/help/get_first_help_sentence.m --- a/scripts/help/get_first_help_sentence.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/help/get_first_help_sentence.m Fri Aug 01 12:10:05 2014 -0400 @@ -28,7 +28,7 @@ ## ## The optional output argument @var{status} returns the status reported by ## @code{makeinfo}. If only one output argument is requested, and @var{status} -## is non-zero, a warning is displayed. +## is nonzero, a warning is displayed. ## ## As an example, the first sentence of this help text is ## diff -r c59745865c7f -r dcb260e7a648 scripts/help/help.m --- a/scripts/help/help.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/help/help.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/help/which.m --- a/scripts/help/which.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/help/which.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/image.m --- a/scripts/image/image.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/image.m Fri Aug 01 12:10:05 2014 -0400 @@ -111,6 +111,8 @@ hax = newplot (hax); elseif (isempty (hax)) hax = gca (); + else + hax = hax(1); endif htmp = __img__ (hax, do_new, x, y, img, varargin{chararg:end}); @@ -139,26 +141,20 @@ 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)) - x = [1, columns(img)]; + xdata = []; + else + xdata = x([1, end])(:).'; # (:).' is a hack to guarantee row vector endif if (isempty (y)) - y = [1, rows(img)]; + ydata = []; + else + ydata = y([1, end])(:).'; endif - xdata = x([1, end])(:).'; # (:).' is a hack to guarantee row vector - ydata = y([1, end])(:).'; - if (numel (x) > 2 && numel (y) > 2) ## Test data for non-linear spacing which is unsupported tol = .01; # 1% tolerance. FIXME: this value was chosen without thought. @@ -198,7 +194,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 @@ -225,4 +221,31 @@ %! h = image (-x, -y, img); %! title ("image (-x, -y, img)"); +%!test +%! ## test hidden properties x/ydatamode (bug #42121) +%! hf = figure ("visible", "off"); +%! unwind_protect +%! nx = 64; ny = 64; +%! cdata = rand (ny, nx)*127; +%! hi = image (cdata); # x/ydatamode is auto +%! assert (get (hi, "xdata"), [1 nx]) +%! assert (get (hi, "ydata"), [1 ny]) +%! set (hi, "cdata", cdata(1:2:end, 1:2:end)) +%! assert (get (hi, "xdata"), [1 nx/2]) +%! assert (get (hi, "ydata"), [1 ny/2]) +%! +%! set (hi, "xdata", [10 100]) # xdatamode is now manual +%! set (hi, "ydata", [10 1000]) # ydatamode is now manual +%! set (hi, "cdata", cdata) +%! assert (get (hi, "xdata"), [10 100]) +%! assert (get (hi, "ydata"), [10 1000]) +%! +%! set (hi, "ydata", []) # ydatamode is now auto +%! set (hi, "cdata", cdata(1:2:end, 1:2:end)) +%! assert (get (hi, "xdata"), [10 100]) +%! assert (get (hi, "ydata"), [1 ny/2]) +%! unwind_protect_cleanup +%! close (hf) +%! end_unwind_protect + ## FIXME: Need %!tests for linear diff -r c59745865c7f -r dcb260e7a648 scripts/image/imfinfo.m --- a/scripts/image/imfinfo.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/imfinfo.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/imformats.m --- a/scripts/image/imformats.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/imformats.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/imread.m --- a/scripts/image/imread.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/imread.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/imshow.m --- a/scripts/image/imshow.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/imshow.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/imwrite.m --- a/scripts/image/imwrite.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/imwrite.m Fri Aug 01 12:10:05 2014 -0400 @@ -49,7 +49,7 @@ ## ## @item DelayTime ## For formats that accept animations (such as GIF), controls for how long a -## frame is displayed until it moves to the next one. The value must be scalar +## frame is displayed until it moves to the next one. The value must be scalar ## (which will applied to all frames in @var{img}), or a vector of length ## equal to the number of frames in @var{im}. The value is in seconds, must ## be between 0 and 655.35, and defaults to 0.5. @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/ind2gray.m --- a/scripts/image/ind2gray.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/ind2gray.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/ind2rgb.m --- a/scripts/image/ind2rgb.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/ind2rgb.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/private/__imfinfo__.m --- a/scripts/image/private/__imfinfo__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/private/__imfinfo__.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/private/__imread__.m --- a/scripts/image/private/__imread__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/private/__imread__.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/private/imageIO.m --- a/scripts/image/private/imageIO.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/private/imageIO.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/image/private/ind2x.m --- a/scripts/image/private/ind2x.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/image/private/ind2x.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/io/importdata.m --- a/scripts/io/importdata.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/io/importdata.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/io/strread.m --- a/scripts/io/strread.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/io/strread.m Fri Aug 01 12:10:05 2014 -0400 @@ -249,8 +249,8 @@ elseif (iscellstr (varargin{n+1}) && numel (varargin{n+1}) == 2) [comment_start, comment_end] = deal (varargin{n+1}{:}); else - ## FIXME - a user may have numeric values specified: {'//', 7} - ## this will lead to an error in the warning message + ## FIXME: A user may have numeric values specified: {'//', 7} + ## this will lead to an error in the warning message error ("strread: unknown or unrecognized comment style '%s'", varargin{n+1}); endif @@ -690,8 +690,8 @@ endif ## Map to format - ## FIXME - add support for formats like "<%s>", "%[a-zA-Z]" - ## Someone with regexp experience is needed. + ## FIXME: Add support for formats like "<%s>", "%[a-zA-Z]" + ## Someone with regexp experience is needed. switch (fmt_words{m}(1:min (2, length (fmt_words{m})))) case "%s" if (pad_out) @@ -701,7 +701,7 @@ k++; case {"%d", "%u", "%f", "%n"} n = cellfun ("isempty", data); - ### FIXME - erroneously formatted data lead to NaN, not an error + ### FIXME: Erroneously formatted data lead to NaN, not an error data = str2double (data); if (! isempty (regexp (fmt_words{m}, "%[du]"))) ## Cast to integer @@ -722,8 +722,8 @@ switch (fmt_words{m}(ew+1)) case {"d", "u", "f", "n"} n = cellfun ("isempty", data); - ### FIXME - erroneously formatted data lead to NaN, not an error - ### => ReturnOnError can't be implemented for numeric data + ### FIXME: Erroneously formatted data lead to NaN, not an error + ### => ReturnOnError can't be implemented for numeric data data = str2double (strtrunc (data, swidth)); data(n) = numeric_fill_value; if (pad_out) diff -r c59745865c7f -r dcb260e7a648 scripts/io/textread.m --- a/scripts/io/textread.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/io/textread.m Fri Aug 01 12:10:05 2014 -0400 @@ -135,7 +135,7 @@ endif ## Now that we know what EOL looks like, we can process format_repeat_count. - ## FIXME The below isn't ML-compatible: counts lines, not format string uses + ## FIXME: The below isn't ML-compatible: counts lines, not format string uses if (isfinite (nlines) && (nlines > 0)) l_eol_char = length (eol_char); eoi = findstr (str, eol_char); diff -r c59745865c7f -r dcb260e7a648 scripts/io/textscan.m --- a/scripts/io/textscan.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/io/textscan.m Fri Aug 01 12:10:05 2014 -0400 @@ -316,13 +316,15 @@ ## See if lowermost data row must be completed pad = mod (numel (C{1}), ncols); if (pad) - ## Textscan returns NaNs for empty fields - C(1) = [C{1}; NaN(ncols - pad, 1)]; - endif - ## Replace NaNs with EmptyValue, if any - ipos = find (strcmpi (args, "emptyvalue")); - if (ipos) - C{1}(find (isnan (C{1}))) = args{ipos+1}; + ## Pad output with emptyvalues (rest has been done by stread.m) + emptv = find (strcmpi (args, "emptyvalue")); + if (isempty (emptv)) + ## By default textscan returns NaNs for empty fields + C(1) = [C{1}; NaN(ncols - pad, 1)]; + else + ## Otherwise return supplied emptyvalue. Pick last occurrence + C(1) = [C{1}; repmat(args{emptv(end)+1}, ncols - pad, 1)]; + endif endif ## Compute nr. of rows nrows = floor (numel (C{1}) / ncols); @@ -666,3 +668,12 @@ %!test %! assert (textscan ("123", "", "whitespace", " "){:}, 123); +%% Bug #42343-1, just test supplied emptyvalue (actually done by strread.m) +%!test +%! assert (textscan (",NaN", "", "delimiter", "," ,"emptyValue" ,Inf), {Inf, NaN}); + +%% Bug #42343-2, test padding with supplied emptyvalue (done by textscan.m) +%!test +%! a = textscan (",1,,4\nInf, ,NaN", "", "delimiter", ",", "emptyvalue", -10); +%! assert (cell2mat (a), [-10, 1, -10, 4; Inf, -10, NaN, -10]); + diff -r c59745865c7f -r dcb260e7a648 scripts/java/javachk.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/java/javachk.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/java/javaclasspath.m --- a/scripts/java/javaclasspath.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/java/javaclasspath.m Fri Aug 01 12:10:05 2014 -0400 @@ -54,7 +54,11 @@ ## @seealso{javaaddpath, javarmpath} ## @end deftypefn -function varargout = javaclasspath (which) +function [path1, path2] = javaclasspath (which) + + if (nargin > 1) + print_usage (); + endif ## dynamic classpath dynamic_path = javaMethod ("getClassPath", "org.octave.ClassHelper"); @@ -70,46 +74,39 @@ static_path_list = {}; endif - switch (nargin) - case 0 - switch (nargout) - case 0 - disp_path_list ("STATIC", static_path_list) - disp (""); - disp_path_list ("DYNAMIC", dynamic_path_list) + if (nargout == 0) + if (! nargin) + which = "-all"; + endif + switch (tolower (which)) + case "-dynamic", disp_path_list ("DYNAMIC", dynamic_path_list); + case "-static", disp_path_list ("STATIC", static_path_list); + case "-all" + disp_path_list ("STATIC", static_path_list); + disp (""); + disp_path_list ("DYNAMIC", dynamic_path_list); + otherwise + error ("javaclasspath: invalid value for WHAT"); + endswitch - case 1 - varargout{1} = cellstr (dynamic_path_list); - - case 2 - varargout{1} = cellstr (dynamic_path_list); - varargout{2} = cellstr (static_path_list); + else + if (! nargin) + ## This is to allow retrieval of both paths in separate variables with + ## a single call to javaclasspath(). Matlab returns only the -dynamic + ## path in this case but this won't break compatibility. + path1 = cellstr (dynamic_path_list); + path2 = cellstr (static_path_list); + else + switch (tolower (which)) + case "-all", path1 = cellstr ([static_path_list, dynamic_path_list]); + case "-dynamic", path1 = cellstr (dynamic_path_list); + case "-static", path1 = cellstr (static_path_list); + otherwise + error ("javaclasspath: invalid value for WHAT"); endswitch - - case 1 - switch (nargout) - case 0 - if (strcmp (which, "-static")) - disp_path_list ("STATIC", static_path_list) - elseif (strcmp (which, "-dynamic")) - disp_path_list ("DYNAMIC", dynamic_path_list) - elseif (strcmp (which, "-all") == 1) - disp_path_list ("STATIC", static_path_list) - disp (""); - disp_path_list ("DYNAMIC", dynamic_path_list) - endif + endif + endif - case 1 - if (strcmp (which, "-static") == 1) - varargout{1} = cellstr (static_path_list); - elseif (strcmp (which, "-dynamic") == 1) - varargout{1} = cellstr (dynamic_path_list); - elseif (strcmp (which, "-all") == 1) - varargout{1} = cellstr ([static_path_list, dynamic_path_list]); - endif - endswitch - endswitch - endfunction ## Display cell array of paths diff -r c59745865c7f -r dcb260e7a648 scripts/java/javamem.m --- a/scripts/java/javamem.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/java/javamem.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/java/module.mk --- a/scripts/java/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/java/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -5,6 +5,7 @@ java/java_set.m \ java/javaArray.m \ java/javaaddpath.m \ + java/javachk.m \ java/javaclasspath.m \ java/javamem.m \ java/javarmpath.m \ diff -r c59745865c7f -r dcb260e7a648 scripts/java/org/octave/ClassHelper.java --- a/scripts/java/org/octave/ClassHelper.java Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/java/org/octave/ClassHelper.java Fri Aug 01 12:10:05 2014 -0400 @@ -199,7 +199,7 @@ { sb.append (";"); } - sb.append (theField[i].toString ()); + sb.append (theField[i].getName ()); } return (sb.toString ()); diff -r c59745865c7f -r dcb260e7a648 scripts/java/usejava.m --- a/scripts/java/usejava.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/java/usejava.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/linear-algebra/bandwidth.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/linear-algebra/bandwidth.m Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,110 @@ +## Copyright (C) 2014 Massimiliano Fasi +## +## 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{bw} =} bandwidth (@var{A}, @var{type}) +## @deftypefnx {Function File} {[@var{lower}, @var{upper}] =} bandwidth (@var{A}) +## Compute the bandwidth of @var{A}. +## +## The @var{type} argument is the string @qcode{"lower"} for the lower +## bandwidth and @qcode{"upper"} for the upper bandwidth. +## If no @var{type} is specified return both the lower and upper bandwidth +## of @var{A}. +## +## The lower/upper bandwidth of a matrix is the number of +## subdiagonals/superdiagonals with nonzero entries. +## +## @seealso{isbanded, isdiag, istril, istriu} +## @end deftypefn + +## Author: Massimiliano Fasi + +function [lower, upper] = bandwidth (A, type) + + if (! ((nargin == 1 && nargout == 2) || (nargin == 2 && nargout <= 1))) + print_usage (); + endif + + if (! isnumeric (A) && ! islogical (A) || ndims (A) != 2) + error ("bandwidth: A must be a 2-D numeric or logical matrix"); + elseif (nargin == 2 && ! (strcmp (type, "lower") || strcmp (type, "upper"))) + error ('bandwidth: TYPE must be "lower" or "upper"'); + endif + + if (nargin == 1) + [i, j] = find (A); + if (isempty (i)) + lower = upper = 0; + else + lower = max (i - j); + upper = max (j - i); + endif + else + [i, j] = find (A); + if (isempty (i)) + lower = 0; + elseif (strcmp (type, "lower")) + lower = max (i - j); + else + lower = max (j - i); + endif + endif + +endfunction + + +%!test +%! [a,b] = bandwidth (speye (100)); +%! assert ([a,b] == [0,0]); +%! assert (bandwidth (speye (100), "upper"), 0); +%! assert (bandwidth (speye (100), "lower"), 0); + +%!test +%! A = [2 3 0 0 0; 1 2 3 0 0; 0 1 2 3 0; 0 0 1 2 3; 0 0 0 1 2]; +%! [a,b] = bandwidth (A); +%! assert ([a,b] == [1,1]); +%! assert (bandwidth (A, "lower"), 1); +%! assert (bandwidth (A, "upper"), 1); + +%!assert (bandwidth ([], "lower"), 0) +%!assert (bandwidth ([], "upper"), 0) +%!assert (bandwidth (zeros (3,3), "lower"), 0) +%!assert (bandwidth (zeros (3,3), "upper"), 0) +%!assert (bandwidth (ones (5,5), "lower"), 4) +%!assert (bandwidth (ones (5,5), "upper"), 4) + +%!test +%! [a,b] = bandwidth ([]); +%! assert ([a,b] == [0,0]); +%!test +%! [a,b] = bandwidth (zeros (3,3)); +%! assert ([a,b] == [0,0]); +%!test +%! [a,b] = bandwidth (ones (5,5)); +%! assert ([a,b] == [4,4]); + +%% Test input validation +%!error bandwidth () +%!error bandwidth (1,2,3) +%!error [a,b,c] = bandwidth (ones (2)) +%!error [a,b] = bandwidth (ones (2), "upper") +%!error bandwidth ("string", "lower") +%!error bandwidth (ones (3,3,3), "lower") +%!error bandwidth (ones (2), "uper") +%!error bandwidth (ones (2), "uppper") + diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/isbanded.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/linear-algebra/isbanded.m Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,86 @@ +## Copyright (C) 2014 Massimiliano Fasi +## +## 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} {} isbanded (@var{A}, @var{lower}, @var{upper}) +## Return true if @var{A} is a matrix with entries confined between +## @var{lower} diagonals below the main diagonal and @var{upper} diagonals +## above the main diagonal. +## +## @var{lower} and @var{upper} must be non-negative integers. +## @seealso{isdiag, istril, istriu, bandwidth} +## @end deftypefn + +## Author: Massimiliano Fasi + +function retval = isbanded (A, lower, upper) + + if (nargin != 3) + print_usage (); + endif + + if (! isreal (lower) || ! isreal (upper) || lower < 0 || upper < 0) + error ("isbanded: LOWER and UPPER must be non-negative integers"); + endif + + if (isempty (A)) + retval = []; + else + retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2; + if (retval) + [i, j] = find (A); + pupp = j >= i; + retval = all (j(pupp) - i(pupp) <= upper); + if (retval) + plow = i >= j; + retval = all (i(plow) - j(plow) <= lower); + endif + endif + endif + +endfunction + + +%!assert (! isbanded ("string", 0, 0)) +%!assert (! isbanded (zeros (2,2,2), 0, 0)) +%!assert (isbanded ([], 0, 0)) +%!assert (isbanded (1,0,0)) +%!assert (isbanded (1,10,10)) + +%!assert (isbanded ([1, 1],1,1)) +%!assert (isbanded ([1; 1],1,1)) +%!assert (isbanded (eye(10),0,0)) +%!assert (isbanded (eye(10),1,1)) +%!assert (isbanded (i*eye(10),1,1)) +%!assert (isbanded (logical (eye (10)),1,1)) + +%! A = [2 3 0 0 0; 1 2 3 0 0; 0 1 2 3 0; 0 0 1 2 3; 0 0 0 1 2]; +%! assert (isbanded (A,1,1)) +%! assert (! isbanded (A,0,1)) +%! assert (! isbanded (A,1,0)) + +%% Test input validation +%!error isbanded () +%!error isbanded (1) +%!error isbanded (1,2) +%!error isbanded (1,2,3,4) +%!error isbanded (1, -1, 1) +%!error isbanded (1, 1, -1) +%!error isbanded (1, {1}, 1) +%!error isbanded (1, 1, {1}) + diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/isdefinite.m --- a/scripts/linear-algebra/isdefinite.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/linear-algebra/isdefinite.m Fri Aug 01 12:10:05 2014 -0400 @@ -17,13 +17,13 @@ ## . ## -*- texinfo -*- -## @deftypefn {Function File} {} isdefinite (@var{x}) -## @deftypefnx {Function File} {} isdefinite (@var{x}, @var{tol}) -## Return 1 if @var{x} is symmetric positive definite within the -## tolerance specified by @var{tol} or 0 if @var{x} is symmetric +## @deftypefn {Function File} {} isdefinite (@var{A}) +## @deftypefnx {Function File} {} isdefinite (@var{A}, @var{tol}) +## Return 1 if @var{A} is symmetric positive definite within the +## tolerance specified by @var{tol} or 0 if @var{A} is symmetric ## positive semidefinite. Otherwise, return -1. If @var{tol} ## is omitted, use a tolerance of -## @code{100 * eps * norm (@var{x}, "fro")} +## @code{100 * eps * norm (@var{A}, "fro")} ## @seealso{issymmetric, ishermitian} ## @end deftypefn @@ -31,30 +31,30 @@ ## Created: November 2003 ## Adapted-By: jwe -function retval = isdefinite (x, tol) +function retval = isdefinite (A, tol) if (nargin < 1 || nargin > 2) print_usage (); endif - if (! isfloat (x)) - x = double (x); + if (! isfloat (A)) + A = double (A); endif if (nargin == 1) - tol = 100 * eps (class (x)) * norm (x, "fro"); + tol = 100 * eps (class (A)) * norm (A, "fro"); endif - if (! ishermitian (x, tol)) - error ("isdefinite: X must be a Hermitian matrix"); + if (! ishermitian (A, tol)) + error ("isdefinite: A must be a Hermitian matrix"); endif - e = tol * eye (rows (x)); - [r, p] = chol (x - e); + e = tol * eye (rows (A)); + [r, p] = chol (A - e); if (p == 0) retval = 1; else - [r, p] = chol (x + e); + [r, p] = chol (A + e); if (p == 0) retval = 0; else @@ -83,5 +83,5 @@ %!error isdefinite () %!error isdefinite (1,2,3) -%!error isdefinite ([1 2; 3 4]) +%!error isdefinite ([1 2; 3 4]) diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/isdiag.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/linear-algebra/isdiag.m Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,56 @@ +## Copyright (C) 2014 Massimiliano Fasi +## +## 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} {} isdiag (@var{A}) +## Return true if @var{A} is a diagonal matrix. +## @seealso{isbanded, istril, istriu, diag, bandwidth} +## @end deftypefn + +## Author: Massimiliano Fasi + +function retval = isdiag (A) + + if (nargin != 1) + print_usage (); + endif + + retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2; + if (retval) + [i, j] = find (A); + retval = all (i == j); + endif + +endfunction + + +%!assert (! isdiag ("string")) +%!assert (isdiag ([])) + +%!assert (isdiag (1)) +%!assert (! isdiag ([1, 1])) +%!assert (! isdiag ([1; 1])) +%!assert (isdiag (eye (10))) +%!assert (issymmetric ([i, 0; 0, 1 + i])) +%!assert (isdiag (speye (1000000))) +%!assert (isdiag (logical (eye (10)))) + +%% Test input validation +%!error isdiag () +%!error isdiag (1,2) + diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/ishermitian.m --- a/scripts/linear-algebra/ishermitian.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/linear-algebra/ishermitian.m Fri Aug 01 12:10:05 2014 -0400 @@ -18,13 +18,14 @@ ## . ## -*- texinfo -*- -## @deftypefn {Function File} {} ishermitian (@var{x}) -## @deftypefnx {Function File} {} ishermitian (@var{x}, @var{tol}) -## Return true if @var{x} is Hermitian within the tolerance specified by +## @deftypefn {Function File} {} ishermitian (@var{A}) +## @deftypefnx {Function File} {} ishermitian (@var{A}, @var{tol}) +## Return true if @var{A} is Hermitian within the tolerance specified by ## @var{tol}. +## ## The default tolerance is zero (uses faster code). -## Matrix @var{x} is considered symmetric if -## @code{norm (@var{x} - @var{x}', Inf) / norm (@var{x}, Inf) < @var{tol}}. +## Matrix @var{A} is considered symmetric if +## @code{norm (@var{A} - @var{A}', Inf) / norm (@var{A}, Inf) < @var{tol}}. ## @seealso{issymmetric, isdefinite} ## @end deftypefn @@ -32,19 +33,19 @@ ## Created: August 1993 ## Adapted-By: jwe -function retval = ishermitian (x, tol = 0) +function retval = ishermitian (A, tol = 0) if (nargin < 1 || nargin > 2) print_usage (); endif - retval = isnumeric (x) && issquare (x); + retval = isnumeric (A) && issquare (A); if (retval) if (tol == 0) - retval = all ((x == x')(:)); + retval = all ((A == A')(:)); else - norm_x = norm (x, inf); - retval = norm_x == 0 || norm (x - x', inf) / norm_x <= tol; + norm_x = norm (A, inf); + retval = norm_x == 0 || norm (A - A', inf) / norm_x <= tol; endif endif diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/issymmetric.m --- a/scripts/linear-algebra/issymmetric.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/linear-algebra/issymmetric.m Fri Aug 01 12:10:05 2014 -0400 @@ -18,12 +18,14 @@ ## . ## -*- texinfo -*- -## @deftypefn {Function File} {} issymmetric (@var{x}) -## @deftypefnx {Function File} {} issymmetric (@var{x}, @var{tol}) -## Return true if @var{x} is a symmetric matrix within the tolerance specified -## by @var{tol}. The default tolerance is zero (uses faster code). -## Matrix @var{x} is considered symmetric if -## @code{norm (@var{x} - @var{x}.', Inf) / norm (@var{x}, Inf) < @var{tol}}. +## @deftypefn {Function File} {} issymmetric (@var{A}) +## @deftypefnx {Function File} {} issymmetric (@var{A}, @var{tol}) +## Return true if @var{A} is a symmetric matrix within the tolerance specified +## by @var{tol}. +## +## The default tolerance is zero (uses faster code). +## Matrix @var{A} is considered symmetric if +## @code{norm (@var{A} - @var{A}.', Inf) / norm (@var{A}, Inf) < @var{tol}}. ## @seealso{ishermitian, isdefinite} ## @end deftypefn @@ -31,19 +33,20 @@ ## Created: August 1993 ## Adapted-By: jwe -function retval = issymmetric (x, tol = 0) +function retval = issymmetric (A, tol = 0) if (nargin < 1 || nargin > 2) print_usage (); endif - retval = isnumeric (x) && issquare (x); + retval = (isnumeric (A) || islogical (A)) && issquare (A); if (retval) if (tol == 0) - retval = all ((x == x.')(:)); + ## Handle large sparse matrices as well as full ones + retval = nnz (A != A.') == 0; else - norm_x = norm (x, inf); - retval = norm_x == 0 || norm (x - x.', inf) / norm_x <= tol; + norm_x = norm (A, inf); + retval = norm_x == 0 || norm (A - A.', inf) / norm_x <= tol; endif endif @@ -59,6 +62,8 @@ %!assert (issymmetric ([1, 2i; 2i, 1])) %!assert (! (issymmetric ("t"))) %!assert (! (issymmetric (["te"; "et"]))) +%!assert (issymmetric (speye (100000))) +%!assert (issymmetric (logical (eye (2)))) %!test %! s.a = 1; diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/istril.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/linear-algebra/istril.m Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,61 @@ +## Copyright (C) 2014 Massimiliano Fasi +## +## 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} {} istril (@var{A}) +## Return true if @var{A} is a lower triangular matrix. +## +## A lower triangular matrix has nonzero entries only on the main diagonal +## and below. +## @seealso{istriu, isbanded, isdiag, tril, bandwidth} +## @end deftypefn + +## Author: Massimiliano Fasi + +function retval = istril (A) + + if (nargin != 1) + print_usage (); + endif + + retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2; + if (retval) + [i, j] = find (A); + retval = all (i >= j); + endif + +endfunction + + +%!assert (! istril ("string")) +%!assert (istril ([])) +%!assert (! istril (zeros (2,2,2))) + +%!assert (istril (1)) +%!assert (! istril ([1, 1])) +%!assert (istril ([1; 1])) +%!assert (istril (eye (10))) +%!assert (istril (speye (100))) + +%!assert (istril (tril (randn (10)))) +%!assert (! istril (randn (10))) + +%% Test input validation +%!error istril () +%!error istril (1,2) + diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/istriu.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/linear-algebra/istriu.m Fri Aug 01 12:10:05 2014 -0400 @@ -0,0 +1,61 @@ +## Copyright (C) 2014 Massimiliano Fasi +## +## 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} {} istriu (@var{A}) +## Return true if @var{A} is an upper triangular matrix. +## +## An upper triangular matrix has nonzero entries only on the main diagonal +## and above. +## @seealso{isdiag, isbanded, istril, triu, bandwidth} +## @end deftypefn + +## Author: Massimiliano Fasi + +function retval = istriu (A) + + if (nargin != 1) + print_usage (); + endif + + retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2; + if (retval) + [i, j] = find (A); + retval = all (i <= j); + endif + +endfunction + + +%!assert (! istriu ("string")) +%!assert (istriu ([])) +%!assert (! istriu (zeros (2,2,2))) + +%!assert (istriu (1)) +%!assert (istriu ([1, 1])) +%!assert (! istriu ([1; 1])) +%!assert (istriu (eye (10))) +%!assert (istriu (speye (100))) + +%!assert (istriu (triu (randn (10)))) +%!assert (! istriu (randn (10))) + +%% Test input validation +%!error istriu () +%!error istriu (1,2) + diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/krylov.m --- a/scripts/linear-algebra/krylov.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/linear-algebra/krylov.m Fri Aug 01 12:10:05 2014 -0400 @@ -133,8 +133,8 @@ nv = columns (V); if (jj != nv) [V(:,jj), V(:,nv)] = swap (V(:,jj), V(:,nv)); - ## FIXME -- H columns should be swapped too. Not done - ## since Block Hessenberg structure is lost anyway. + ## FIXME: H columns should be swapped too. + ## Not done since Block Hessenberg structure is lost anyway. endif V = V(:,1:(nv-1)); ## One less reflection. @@ -167,7 +167,7 @@ ## Reduce V per the reflection. V(idx,:) = V(idx,:) - av*hv*(hv' * V(idx,:)); if(iter > 1) - ## FIXME -- not done correctly for block case. + ## FIXME: not done correctly for block case. H(nu,nu-1) = V(pivot_vec(nu),jj); endif diff -r c59745865c7f -r dcb260e7a648 scripts/linear-algebra/module.mk --- a/scripts/linear-algebra/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/linear-algebra/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -1,6 +1,7 @@ FCN_FILE_DIRS += linear-algebra linear_algebra_FCN_FILES = \ + linear-algebra/bandwidth.m \ linear-algebra/commutation_matrix.m \ linear-algebra/cond.m \ linear-algebra/condest.m \ @@ -8,9 +9,13 @@ linear-algebra/duplication_matrix.m \ linear-algebra/expm.m \ linear-algebra/housh.m \ + linear-algebra/isbanded.m \ linear-algebra/isdefinite.m \ + linear-algebra/isdiag.m \ linear-algebra/ishermitian.m \ linear-algebra/issymmetric.m \ + linear-algebra/istril.m \ + linear-algebra/istriu.m \ linear-algebra/krylov.m \ linear-algebra/linsolve.m \ linear-algebra/logm.m \ diff -r c59745865c7f -r dcb260e7a648 scripts/miscellaneous/cast.m --- a/scripts/miscellaneous/cast.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/cast.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/colon.m --- a/scripts/miscellaneous/colon.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/colon.m Fri Aug 01 12:10:05 2014 -0400 @@ -42,5 +42,5 @@ %!error colon (1) -## FIXME -- what does colon () mean since it doesn't set a return value? +## FIXME: What does colon () mean since it doesn't set a return value? diff -r c59745865c7f -r dcb260e7a648 scripts/miscellaneous/dump_prefs.m --- a/scripts/miscellaneous/dump_prefs.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/dump_prefs.m Fri Aug 01 12:10:05 2014 -0400 @@ -32,7 +32,7 @@ file = stdout; endif - ## FIXME -- it would be nice to be able to get the list of + ## FIXME: It would be nice to be able to get the list of ## built-in variables directly from Octave so that we wouldn't have to ## remember to update it each time the list of preference variables ## changes diff -r c59745865c7f -r dcb260e7a648 scripts/miscellaneous/edit.m --- a/scripts/miscellaneous/edit.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/edit.m Fri Aug 01 12:10:05 2014 -0400 @@ -23,7 +23,7 @@ ## Edit the named function, or change editor settings. ## ## If @code{edit} is called with the name of a file or function as -## its argument it will be opened in the text editor defined by @code{EDITOR}. +## its argument it will be opened in the text editor defined by @env{EDITOR}. ## ## @itemize @bullet ## @item @@ -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 @@ -340,12 +340,22 @@ ## If in gui-mode, create it before or editor would prompt again. fileandpath = file; idx = rindex (file, "."); - name = file(1:idx-1); - ext = file(idx+1:end); + if (idx) + name = file(1:idx-1); + ext = file(idx+1:end); + else + name = file; + ext = ""; + endif if (! any (strcmp (ext, {"cc", "m"}))) ## Some unknown file. Create and open it or just open it. + if (isempty (ext)) + fileandpath = [fileandpath ".m"]; # Add .m extension per default + endif 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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/fact.m --- a/scripts/miscellaneous/fact.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/fact.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/fileattrib.m --- a/scripts/miscellaneous/fileattrib.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/fileattrib.m Fri Aug 01 12:10:05 2014 -0400 @@ -108,7 +108,7 @@ r_s{i} = NaN; r_h{i} = NaN; r_d{i} = S_ISDIR (info.mode); - ## FIXME -- maybe we should have S_IRUSR etc. masks? + ## FIXME: Maybe we should have S_IRUSR etc. masks? modestr = info.modestr; r_u_r{i} = modestr(2) == "r"; r_u_w{i} = modestr(3) == "w"; diff -r c59745865c7f -r dcb260e7a648 scripts/miscellaneous/genvarname.m --- a/scripts/miscellaneous/genvarname.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/genvarname.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/getappdata.m --- a/scripts/miscellaneous/getappdata.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/getappdata.m Fri Aug 01 12:10:05 2014 -0400 @@ -35,8 +35,8 @@ function val = getappdata (h, name) if (all (ishandle (h)) && nargin == 2 && ischar (name)) - ## FIXME - Is there a better way to handle non-existent appdata - ## and missing fields? + ## FIXME: Is there a better way to handle non-existent appdata + ## and missing fields? val = cell (numel (h), 1); appdata = struct (); for nh = 1:numel (h) diff -r c59745865c7f -r dcb260e7a648 scripts/miscellaneous/gzip.m --- a/scripts/miscellaneous/gzip.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/gzip.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/inputname.m --- a/scripts/miscellaneous/inputname.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/inputname.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/ls.m --- a/scripts/miscellaneous/ls.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/ls.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/mex.m --- a/scripts/miscellaneous/mex.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/mex.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/private/__xzip__.m --- a/scripts/miscellaneous/private/__xzip__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/private/__xzip__.m Fri Aug 01 12:10:05 2014 -0400 @@ -83,7 +83,7 @@ movefile (cellfun (@(x) sprintf ("%s.%s", x, extension), f, "uniformoutput", false), cwd); if (nargout > 0) - ## FIXME this does not work when you try to compress directories + ## FIXME: This does not work when you try to compress directories entries = cellfun (@(x) sprintf ("%s.%s", x, extension), files, "uniformoutput", false); endif @@ -109,8 +109,7 @@ endfunction -## FIXME -- reinstate these tests if we invent a way to test private -## functions directly. +## FIXME: Reinstate tests if we invent a way to test private functions directly. ## ## %!error ## %! __xzip__ ("gzip", "", "gzip -r %s", "bla"); diff -r c59745865c7f -r dcb260e7a648 scripts/miscellaneous/run.m --- a/scripts/miscellaneous/run.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/run.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/miscellaneous/unpack.m --- a/scripts/miscellaneous/unpack.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/unpack.m Fri Aug 01 12:10:05 2014 -0400 @@ -84,10 +84,10 @@ ## If the file is a URL, download it and then work with that file. if (! isempty (strfind (file, "://"))) - ## FIXME -- the above is not a perfect test for a URL + ## FIXME: The above is not a perfect test for a URL urlfile = file; - ## FIXME -- should we name the file that we download with the - ## same file name as the URL requests? + ## FIXME: Should we name the file that we download with the + ## same file name as the URL requests? tmpfile = [tmpnam() ext]; [file, success, msg] = urlwrite (urlfile, tmpfile); if (! success) @@ -194,7 +194,7 @@ if (nargout > 0 || needmove) ## Trim the last CR if needed. - ## FIXME -- will this need to change to a check for "\r\n" for windows? + ## FIXME: Will this need to change to a check for "\r\n" for windows? if (output(end) == "\n") output(end) = []; endif diff -r c59745865c7f -r dcb260e7a648 scripts/miscellaneous/what.m --- a/scripts/miscellaneous/what.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/miscellaneous/what.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/mkdoc --- a/scripts/mkdoc Fri Aug 01 09:06:21 2014 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 1999-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 -# . - -## Expecting arguments in this order: -## -## SRCDIR SRCDIR-FILES ... -- LOCAL-FILES ... - -set -e - -PERL=${PERL:-'perl'} - -prefix="$1/" -shift - -if test -f gethelp; then - cat << EOF -### DO NOT EDIT! -### -### This file is generated automatically from the Octave sources. -### Edit those files instead and run make to update this file. - -EOF - for arg - do - if [ "$arg" = "--" ]; then - prefix="./" - else - $PERL -w -e ' - unless (@ARGV == 2) { die "Usage: $0 srcdir m_filename" ; } - ($srcdir, $m_fname) = ($ARGV[0], $ARGV[1]); - $full_fname = $srcdir . $m_fname; - exit unless ( $full_fname =~ m{(.*)/(@|)([^/]*)/(.*)\.m} ); - if ($2) { - $fcn = "$2$3/$4"; - } else { - $fcn = $4; - } - $re_srcdir = quotemeta($srcdir); - for (qx{ ./gethelp $fcn "$full_fname" < "$full_fname"} ) { - s/^\s+\@/\@/ unless $in_example; - s/^\s+\@group/\@group/; - s/^\s+\@end\s+group/\@end group/; - s|\@c $fcn $re_srcdir|\@c $fcn scripts/|o; - $in_example = (/\s*\@example\b/ .. /\s*\@end\s+example\b/); - print; - }' "$prefix" "$arg" - fi - done -else - echo "gethelp program seems to be missing!" 1>&2 - exit 1 -fi diff -r c59745865c7f -r dcb260e7a648 scripts/mkdoc.pl --- a/scripts/mkdoc.pl Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/mkdoc.pl Fri Aug 01 12:10:05 2014 -0400 @@ -1,5 +1,6 @@ -#! /usr/bin/perl -w -# +#! /usr/bin/perl +use utf8; + # Copyright (C) 2012-2013 Rik Wehbring # # This file is part of Octave. @@ -18,13 +19,18 @@ # along with Octave; see the file COPYING. If not, see # . +use strict; +use warnings; +use File::Spec; +use Cwd; + ## Expecting arguments in this order: ## ## SRCDIR SRCDIR-FILES ... -- LOCAL-FILES ... unless (@ARGV >= 2) { die "Usage: $0 srcdir m_filename1 ..." ; } -$srcdir = shift (@ARGV) . '/'; +my $srcdir = shift (@ARGV); print <<__END_OF_MSG__; ### DO NOT EDIT! @@ -34,35 +40,38 @@ __END_OF_MSG__ -MFILE: foreach $m_fname (@ARGV) +MFILE: foreach my $m_fname (@ARGV) { if ($m_fname eq "--") - { - $srcdir = "./"; - next MFILE; - } + { + $srcdir = getcwd (); + next MFILE; + } - $full_fname = $srcdir . $m_fname; - next MFILE unless ( $full_fname =~ m{(.*)/(@|)([^/]*)/(.*)\.m} ); - if ($2) - { $fcn = "$2$3/$4"; } - else - { $fcn = $4; } + my $full_fname = File::Spec->catfile ($srcdir, $m_fname); + my @paths = File::Spec->splitdir ($full_fname); + if (@paths < 3 + || $paths[-2] eq "private" # skip private directories + || $paths[-1] !~ s/\.m$//i) # skip non m-files, and remove extension + { next MFILE; } - @help_txt = gethelp ($fcn, $full_fname); - next MFILE if ($help_txt[0] eq ""); + ## @classes will have @class/method as their function name + my $fcn = $paths[-2] =~ m/^@/ ? File::Spec->catfile (@paths[-2, -1]) + : $paths[-1]; + + my @help_txt = gethelp ($fcn, $full_fname); + next MFILE unless @help_txt; print "\x{1d}$fcn\n"; - print "\@c $fcn scripts/$m_fname\n"; + print "\@c $fcn ", File::Spec->catfile ("scripts", $m_fname), "\n"; foreach $_ (@help_txt) - { - s/^\s+\@/\@/ unless $in_example; - s/^\s+\@group/\@group/; - s/^\s+\@end\s+group/\@end group/; - $in_example = (/\s*\@example\b/ .. /\s*\@end\s+example\b/); - print $_; - } + { + my $in_example = (m/\s*\@example\b/ .. m/\s*\@end\s+example\b/); + s/^\s+\@/\@/ unless $in_example; + s/^\s+(\@(?:end)\s+(group|example))/$1/; + print $_; + } } ################################################################################ @@ -70,34 +79,32 @@ ################################################################################ sub gethelp { - ($fcn, $fname) = @_[0..1]; - open (FH, $fname) or return ""; + my $fcn = shift; + my $fname = shift; + open (my $fh, "<", $fname) or return; - do - { - @help_txt = (); + my @help_txt; + while (my $line = <$fh>) + { + next if $line =~ m/^\s*$/; # skip empty lines + last if $line !~ m/^\s*(#|%)/; # out of here once code starts + + my $reading_block = sub {defined ($line = <$fh>) && $line !~ m/^\s*$/}; - ## Advance to non-blank line - while (defined ($_ = ) and /^\s*$/) {;} - - if (! /^\s*(?:#|%)/ or eof (FH)) - { - ## No comment block found. Return empty string - close (FH); - return ""; + ## Skip this block + if ($line =~ /(Copyright|Author)/) + { while (&$reading_block ()) {} } + else + { + do + { + $line =~ s/^\s*(%|#)+ ?//; + push (@help_txt, $line); + } while (&$reading_block ()); + last; + } } - ## Extract help text stopping when comment block ends - do - { - ## Remove comment characters at start of line - s/^\s*(?:#|%){1,2} ?//; - push (@help_txt, $_); - } until (! defined ($_ = ) or ! /^\s*(?:#|%)/); - - } until ($help_txt[0] !~ /^(?:Copyright|Author)/); - - close (FH); - + close ($fh); return @help_txt; } diff -r c59745865c7f -r dcb260e7a648 scripts/optimization/fminbnd.m --- a/scripts/optimization/fminbnd.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/fminbnd.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/optimization/fminunc.m --- a/scripts/optimization/fminunc.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/fminunc.m Fri Aug 01 12:10:05 2014 -0400 @@ -63,11 +63,11 @@ ## Last relative change in function value was less than @code{TolFun}. ## ## @item 0 -## Iteration limit exceeded---either maximum numer of algorithm iterations +## Iteration limit exceeded---either maximum number of algorithm iterations ## @code{MaxIter} or maximum number of function evaluations @code{MaxFunEvals}. ## ## @item -1 -## Alogrithm terminated by @code{OutputFcn}. +## Algorithm terminated by @code{OutputFcn}. ## ## @item -3 ## The trust region radius became excessively small. diff -r c59745865c7f -r dcb260e7a648 scripts/optimization/fsolve.m --- a/scripts/optimization/fsolve.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/fsolve.m Fri Aug 01 12:10:05 2014 -0400 @@ -382,7 +382,7 @@ ## iterations, so we need scaling-independent tolerances wherever ## possible. - ## FIXME -- why tolf*n*xn? If abs (e) ~ abs(x) * eps is a vector + ## FIXME: Why tolf*n*xn? If abs (e) ~ abs(x) * eps is a vector ## of perturbations of x, then norm (fjac*e) <= eps*n*xn, i.e. by ## tolf ~ eps we demand as much accuracy as we can expect. if (fn <= tolf*n*xn) diff -r c59745865c7f -r dcb260e7a648 scripts/optimization/fzero.m --- a/scripts/optimization/fzero.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/fzero.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/optimization/glpk.m --- a/scripts/optimization/glpk.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/glpk.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/optimization/optimget.m --- a/scripts/optimization/optimget.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/optimget.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/optimization/optimset.m --- a/scripts/optimization/optimset.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/optimset.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/optimization/sqp.m --- a/scripts/optimization/sqp.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/optimization/sqp.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/pkg/module.mk --- a/scripts/pkg/module.mk Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/pkg/module.mk Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/pkg/pkg.m --- a/scripts/pkg/pkg.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/pkg/pkg.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/pkg/private/configure_make.m --- a/scripts/pkg/private/configure_make.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/pkg/private/configure_make.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/pkg/private/default_prefix.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/default_prefix.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/pkg/private/getarchprefix.m --- a/scripts/pkg/private/getarchprefix.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/pkg/private/getarchprefix.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/appearance/__getlegenddata__.m --- a/scripts/plot/appearance/__getlegenddata__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/__getlegenddata__.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/appearance/axis.m --- a/scripts/plot/appearance/axis.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/axis.m Fri Aug 01 12:10:05 2014 -0400 @@ -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. ## @@ -192,7 +194,7 @@ "plotboxaspectratio", [1, 1, 1]); elseif (strcmp (ax, "equal")) if (strcmp (get (get (ca, "parent"), "__graphics_toolkit__"), "gnuplot")) - ## FIXME - gnuplot applies the aspect ratio activepostionproperty. + ## FIXME: gnuplot applies the aspect ratio activepostionproperty. set (ca, "activepositionproperty", "position"); ## The following line is a trick used to trigger the recalculation of ## aspect related magnitudes even if the aspect ratio is the same @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/appearance/datetick.m --- a/scripts/plot/appearance/datetick.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/datetick.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 @@ -64,22 +64,22 @@ %! pop = [76.094, 92.407, 106.461, 123.077 131.954, 151.868, 179.979, ... %! 203.984, 227.225, 249.623, 282.224]; %! plot (datenum (yr, 1, 1), pop); -%! title ("US population (millions)"); -%! xlabel ("Year"); -%! datetick ("x", "YYYY"); +%! title ('US population (millions)'); +%! xlabel ('Year'); +%! datetick ('x', 'YYYY'); %!demo %! clf; %! yr = 1988:2:2002; %! yr = datenum (yr,1,1); %! pr = [12.1 13.3 12.6 13.1 13.3 14.1 14.4 15.2]; -%! plot (yr, pr, "-o"); -%! xlabel ("year"); -%! ylabel ("average price"); +%! plot (yr, pr, '-o'); +%! xlabel ('year'); +%! ylabel ('average price'); %! ax = gca; -%! set (ax, "xtick", datenum (1990:5:2005,1,1)); -%! datetick (2, "keepticks"); -%! set (ax, "ytick", 12:16); +%! set (ax, 'xtick', datenum (1990:5:2005,1,1)); +%! datetick (2, 'x', 'keepticks'); +%! set (ax, 'ytick', 12:16); ## Remove from test statistics. No real tests possible. %!assert (1) diff -r c59745865c7f -r dcb260e7a648 scripts/plot/appearance/diffuse.m --- a/scripts/plot/appearance/diffuse.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/diffuse.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/appearance/grid.m --- a/scripts/plot/appearance/grid.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/grid.m Fri Aug 01 12:10:05 2014 -0400 @@ -58,13 +58,10 @@ print_usage (); endif - grid_on = ( strcmp (get (hax, "xgrid"), "on") - && strcmp (get (hax, "ygrid"), "on") - && strcmp (get (hax, "zgrid"), "on")); + grid_on = any (strcmp (get (hax, {"xgrid", "ygrid", "zgrid"}), "on")); - minor_on = ( strcmp (get (hax, "xminorgrid"), "on") - && strcmp (get (hax, "yminorgrid"), "on") - && strcmp (get (hax, "zminorgrid"), "on")); + minor_on = any (strcmp (get (hax, {"xminorgrid", "yminorgrid", "zminorgrid"}), + "on")); minor_auto = true; if (nargs == 0) @@ -102,9 +99,15 @@ endif if (grid_on) - set (hax, "xgrid", "on", "ygrid", "on", "zgrid", "on"); + set (hax, "xgrid", "on", "ygrid", "on", "zgrid", "on", + "gridlinestyle", ":"); if (minor_on) - set (hax, "xminorgrid", "on", "yminorgrid", "on", "zminorgrid", "on"); + set (hax, "xminorgrid", "on", "yminorgrid", "on", "zminorgrid", "on", + "gridlinestyle", "-", "minorgridlinestyle", ":"); + xg = ifelse (strcmp (get (hax, "xscale"), "log"), "off", "on"); + yg = ifelse (strcmp (get (hax, "yscale"), "log"), "off", "on"); + zg = ifelse (strcmp (get (hax, "zscale"), "log"), "off", "on"); + set (hax, "xgrid", xg, "ygrid", yg, "zgrid", zg); elseif (minor_auto) xmg = ifelse (strcmp (get (hax, "xscale"), "log"), "on", "off"); ymg = ifelse (strcmp (get (hax, "yscale"), "log"), "on", "off"); @@ -133,8 +136,26 @@ %! title ('grid on'); %! subplot (2,2,3); %! plot (1:100); +%! grid off; +%! title ('no grid'); +%! subplot (2,2,4); +%! plot (1:100); %! grid minor; %! title ('grid minor'); + +%!demo +%! subplot (2,2,1); +%! semilogy (1:100); +%! grid off; +%! title ('no grid'); +%! subplot (2,2,2); +%! semilogy (1:100); +%! grid on; +%! title ('grid on'); +%! subplot (2,2,3); +%! semilogy (1:100); +%! grid off; +%! title ('no grid'); %! subplot (2,2,4); %! semilogy (1:100); %! grid minor; diff -r c59745865c7f -r dcb260e7a648 scripts/plot/appearance/legend.m --- a/scripts/plot/appearance/legend.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/legend.m Fri Aug 01 12:10:05 2014 -0400 @@ -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,9 @@ set (hax, "position", position); set (hax, "outerposition", outerposition); endswitch - set (hax, "units", units); - h = legend (hax, hplots, get (h, "string")); + set (hax, {"units"}, units); + + h = legend (hax(1), hplots, get (h, "string")); unwind_protect_cleanup recursive = false; end_unwind_protect @@ -1149,6 +1174,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 +1189,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 +1224,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 @@ -1217,22 +1247,22 @@ %! plot (rand (2)); %! title ('legend called with cellstr and string inputs for labels'); %! h = legend ({'foo'}, 'bar'); -%! legend location northeastoutside +%! legend (h, 'location', 'northeastoutside'); %! set (h, 'fontsize', 20); %!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; %! x = 0:1; %! plot (x,x,';I am Blue;', x,2*x, x,3*x,';I am Red;'); -%! legend location northeastoutside +%! h = legend ('location', 'northeastoutside'); %! ## Placing legend inside should return axes to original size -%! legend location northeast +%! legend (h, 'location', 'northeast'); %! title ('Blue and Red keys, with Green missing'); %!demo @@ -1368,9 +1398,9 @@ %! rand_2x3_data2 = [0.44804, 0.84368, 0.23012; 0.72311, 0.58335, 0.90531]; %! bar (rand_2x3_data2); %! ylim ([0 1.2]); -%! title ('legend() works for bar graphs (hggroups)'); +%! title ('"left" option places text label west of colors'); %! legend ('1st Bar', '2nd Bar', '3rd Bar'); -%! legend right; +%! legend left; %!demo %! clf; @@ -1605,3 +1635,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 c59745865c7f -r dcb260e7a648 scripts/plot/appearance/private/__axis_limits__.m --- a/scripts/plot/appearance/private/__axis_limits__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/private/__axis_limits__.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/appearance/specular.m --- a/scripts/plot/appearance/specular.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/specular.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/appearance/text.m --- a/scripts/plot/appearance/text.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/appearance/text.m Fri Aug 01 12:10:05 2014 -0400 @@ -129,6 +129,8 @@ if (isempty (hax)) hax = gca (); + else + hax = hax(1); endif ## Position argument may alse be in PROP/VAL pair diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/area.m --- a/scripts/plot/draw/area.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/area.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/colorbar.m --- a/scripts/plot/draw/colorbar.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/colorbar.m Fri Aug 01 12:10:05 2014 -0400 @@ -207,11 +207,11 @@ if (mirror) set (cax, "xtick", [], "xdir", "normal", "ydir", "normal", "ylim", cext, "ylimmode", "manual", - "yaxislocation", "right", args{:}); + "yaxislocation", "right", "layer", "top", args{:}); else set (cax, "xtick", [], "xdir", "normal", "ydir", "normal", "ylim", cext, "ylimmode", "manual", - "yaxislocation", "left", args{:}); + "yaxislocation", "left", "layer", "top", args{:}); endif else hi = image (cax, "xdata", [cmin, cmax], "ydata", [0,1], @@ -219,11 +219,11 @@ if (mirror) set (cax, "ytick", [], "xdir", "normal", "ydir", "normal", "xlim", cext, "xlimmode", "manual", - "xaxislocation", "top", args{:}); + "xaxislocation", "top", "layer", "top", args{:}); else set (cax, "ytick", [], "xdir", "normal", "ydir", "normal", "xlim", cext, "xlimmode", "manual", - "xaxislocation", "bottom", args{:}); + "xaxislocation", "bottom", "layer", "top", args{:}); endif endif @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/errorbar.m --- a/scripts/plot/draw/errorbar.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/errorbar.m Fri Aug 01 12:10:05 2014 -0400 @@ -213,7 +213,7 @@ %! y1 = sin (x); %! y2 = cos (x); %! errorbar (x, y1, err, '~', x, y2, err, '>'); -%! legend ("Y errbar", "X errbar"); +%! legend ('Y errbar', 'X errbar'); %! title ('errorbar() with 2 datasets'); @@ -224,7 +224,7 @@ %! y1 = sin (x); %! y2 = cos (x); %! errorbar (x, y1, err, err, '#r', x, y2, err, err, '#~'); -%! legend ("X errbox", "Y errbox"); +%! legend ('X errbox', 'Y errbox'); %! title ('errorbar() with error boxes'); %!demo @@ -235,7 +235,7 @@ %! y2 = cos (x); %! errorbar (x, y1, err, err, err, err, '~>', ... %! x, y2, err, err, err, err, '#~>-*'); -%! legend ("X-Y errbars", "X-Y errboxes"); +%! legend ('X-Y errbars', 'X-Y errboxes'); %! title ('errorbar() with X-Y errorbars and error boxes'); ## Invisible figure used for tests diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/fill.m --- a/scripts/plot/draw/fill.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/fill.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/line.m --- a/scripts/plot/draw/line.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/line.m Fri Aug 01 12:10:05 2014 -0400 @@ -49,6 +49,8 @@ if (isempty (hax)) hax = gca (); + else + hax = hax(1); endif htmp = __line__ (hax, varargin{:}); @@ -62,6 +64,16 @@ %!demo %! clf +%! line ([0 1], [0.8 0.8], 'linestyle', '-', 'color', 'b'); +%! line ([0 1], [0.6 0.6], 'linestyle', '--', 'color', 'g'); +%! line ([0 1], [0.4 0.4], 'linestyle', ':', 'color', 'r'); +%! line ([0 1], [0.2 0.2], 'linestyle', '-.', 'color', 'k'); +%! ylim ([0 1]); +%! title ('line() with various linestyles'); +%! legend ('"-"', '"--"', '":"', '"-."', 'location', 'eastoutside'); + +%!demo +%! clf %! x = 0:0.3:10; %! y1 = cos (x); %! y2 = sin (x); diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/mesh.m --- a/scripts/plot/draw/mesh.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/mesh.m Fri Aug 01 12:10:05 2014 -0400 @@ -70,10 +70,15 @@ unwind_protect hax = newplot (hax); - htmp = surface (varargin{:}); + mesh_props = {"facecolor", "w", "edgecolor", "flat"}; + chararg = find (cellfun ("isclass", varargin, "char"), 1); + if (isempty (chararg)) + htmp = surface (varargin{:}, mesh_props{:}); + else + htmp = surface (varargin{1:chararg-1}, mesh_props{:}, + varargin{chararg:end}); + endif - set (htmp, "facecolor", "w"); - set (htmp, "edgecolor", "flat"); if (! ishold ()) set (hax, "view", [-37.5, 30], "xgrid", "on", "ygrid", "on", "zgrid", "on"); @@ -121,7 +126,21 @@ %! ylabel 'Y-axis'; %! zlabel 'log scale'; %! title ({'mesh() with color proportional to Z^2', 'Z-axis is log scale'}); -%! if (strcmp (get (gcf, '__graphics_toolkit__'), 'gnuplot')) -%! title ({'Gnuplot: mesh color is wrong', 'This is a Gnuplot bug'}); -%! endif +%! try +%! if (strcmp (get (gcf, '__graphics_toolkit__'), 'gnuplot')) +%! title ({'Gnuplot: mesh color is wrong', 'This is a Gnuplot bug'}); +%! endif +%! catch +%! end +%!demo +%! clf; +%! x = logspace (0,1,11); +%! z = x'*x; +%! mesh (x, x, z, 'facecolor', 'none', 'edgecolor', 'c'); +%! xlabel 'X-axis'; +%! ylabel 'Y-axis'; +%! zlabel 'Z-axis'; +%! title ({'mesh() default properties overriden', ... +%! 'transparent mesh with cyan color'}); + diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/meshc.m --- a/scripts/plot/draw/meshc.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/meshc.m Fri Aug 01 12:10:05 2014 -0400 @@ -68,13 +68,18 @@ unwind_protect hax = newplot (hax); - htmp = surface (varargin{:}); + ## FIXME: gnuplot does not support a filled surface and a + ## non-filled contour. 3D filled patches are also not supported. + ## Thus, the facecolor will be transparent for the gnuplot backend. + mesh_props = {"facecolor", "w", "edgecolor", "flat"}; + chararg = find (cellfun ("isclass", varargin, "char"), 1); + if (isempty (chararg)) + htmp = surface (varargin{:}, mesh_props{:}); + else + htmp = surface (varargin{1:chararg-1}, mesh_props{:}, + varargin{chararg:end}); + endif - ## FIXME - gnuplot does not support a filled surface and a - ## non-filled contour. 3D filled patches are also not supported. - ## Thus, the facecolor will be transparent for the gnuplot backend. - set (htmp, "facecolor", "w"); - set (htmp, "edgecolor", "flat"); if (! ishold ()) set (hax, "view", [-37.5, 30], "xgrid", "on", "ygrid", "on", "zgrid", "on", diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/meshz.m --- a/scripts/plot/draw/meshz.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/meshz.m Fri Aug 01 12:10:05 2014 -0400 @@ -30,7 +30,7 @@ ## over a 2-D rectangular region in the x-y plane. @var{z} determines the ## height above the plane of each vertex. If only a single @var{z} matrix is ## given, then it is plotted over the meshgrid -## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}. +## @code{@var{x} = 0:columns (@var{z}) - 1, @var{y} = 0:rows (@var{z}) - 1}. ## Thus, columns of @var{z} correspond to different @var{x} values and rows ## of @var{z} correspond to different @var{y} values. ## @@ -64,52 +64,65 @@ ## Find where property/value pairs start charidx = find (cellfun ("isclass", varargin, "char"), 1); - have_c = false; if (isempty (charidx)) - if (nargin == 2 || nargin == 4) - have_c = true; - charidx = nargin; # bundle C matrix back into varargin - else - charidx = nargin + 1; - endif + charidx = nargin + 1; endif - if (charidx == 2) + if (nargin == 1) + z = varargin{1}; + [m, n] = size (z); + x = 0:(n-1); + y = (0:(m-1)).'; + c = z; + elseif (nargin == 2) z = varargin{1}; [m, n] = size (z); - x = 1:n; - y = (1:m).'; + x = 0:(n-1); + y = (0:(m-1)).'; + c = varargin{2}; + elseif (charidx == 4) + x = varargin{1}; + y = varargin{2}; + z = varargin{3}; + c = z; else x = varargin{1}; y = varargin{2}; z = varargin{3}; + c = varargin{4}; endif + ## Create a border of one rectangle (2 points) as the curtain around + ## the data and draw it with the mean (max + min / 2) color of the data. + if (isvector (x) && isvector (y)) - x = [x(1), x(:).', x(end)]; - y = [y(1); y(:); y(end)]; + x = [x(1), x(1), x(:).', x(end), x(end)]; + y = [y(1); y(1); y(:); y(end); y(end)]; else - x = [x(1,1), x(1,:), x(1,end); - x(:,1), x, x(:,end); - x(end,1), x(end,:), x(end,end)]; - y = [y(1,1), y(1,:), y(1,end); - y(:,1), y, y(:,end); - y(end,1), y(end,:), y(end,end)]; + x = [x(1,1), x(1,1), x(1,:), x(1,end), x(1,end); + x(1,1), x(1,1), x(1,:), x(1,end), x(1,end); + x(:,1), x(:,1), x, x(:,end), x(:,end); + x(end,1), x(end,1), x(end,:), x(end,end), x(end,end); + x(end,1), x(end,1), x(end,:), x(end,end), x(end,end) ]; + y = [y(1,1), y(1,1), y(1,:), y(1,end), y(1,end); + y(1,1), y(1,1), y(1,:), y(1,end), y(1,end); + y(:,1), y(:,1), y, y(:,end), y(:,end); + y(end,1), y(end,1), y(end,:), y(end,end), y(end,end); + y(end,1), y(end,1), y(end,:), y(end,end), y(end,end) ]; endif zref = min (z(isfinite (z))); - z = [zref .* ones(1, columns(z) + 2); - zref .* ones(rows(z), 1), z, zref .* ones(rows(z), 1); - zref .* ones(1, columns(z) + 2)]; + z = [zref .* ones(1, columns(z) + 4); + zref .* ones(1, 2), z(1,:), zref .* ones(1, 2); + zref .* ones(rows(z), 1), z(:,1),z, z(:,end), zref .* ones(rows(z), 1); + zref .* ones(1, 2), z(end,:), zref .* ones(1, 2); + zref .* ones(1, columns(z) + 4)]; - if (have_c) - c = varargin{charidx}; - cref = min (c(isfinite (c))); - c = [cref .* ones(1, columns(c) + 2); - cref .* ones(rows(c), 1), c, cref .* ones(rows(c), 1); - cref .* ones(1, columns(c) + 2)]; - varargin(charidx) = c; - endif + cdat = c(isfinite (c(:))); + cref = (min (cdat) + max (cdat)) / 2; + c = [cref .* ones(2, columns(c) + 4); + cref .* ones(rows(c), 2), c, cref .* ones(rows(c), 2); + cref .* ones(2, columns(c) + 4)]; oldfig = []; if (! isempty (hax)) @@ -117,7 +130,7 @@ endif unwind_protect hax = newplot (hax); - htmp = mesh (x, y, z, varargin{charidx:end}); + htmp = mesh (x, y, z, c, varargin{charidx:end}); unwind_protect_cleanup if (! isempty (oldfig)) set (0, "currentfigure", oldfig); diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/pareto.m --- a/scripts/plot/draw/pareto.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/pareto.m Fri Aug 01 12:10:05 2014 -0400 @@ -104,7 +104,9 @@ axis (ax(1), [1 - 0.6, idx95 + 0.6, 0, maxcdf]); axis (ax(2), [1 - 0.6, idx95 + 0.6, 0, 100]); set (ax(2), "ytick", [0, 20, 40, 60, 80, 100], - "yticklabel", {"0%", "20%", "40%", "60%", "80%", "100%"}); + "yticklabel", {"0%", "20%", "40%", "60%", "80%", "100%"}, + "ycolor", get (ax(1), "ycolor")); + set (hline, "color", get (ax(1), "colororder")(1,:)); set (ax(1:2), "xtick", 1:idx95, "xticklabel", x(1:idx95)); if (nargout > 0) diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/patch.m --- a/scripts/plot/draw/patch.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/patch.m Fri Aug 01 12:10:05 2014 -0400 @@ -80,6 +80,8 @@ if (isempty (hax)) hax = gca (); + else + hax = hax(1); endif [htmp, failed] = __patch__ (hax, varargin{:}); @@ -88,6 +90,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 @@ -141,7 +152,8 @@ %! y2 = cos (t2); %! vert = [x1, y1; x2, y2]; %! fac = [1:8,NaN(1,8);9:24]; -%! patch ('Faces',fac, 'Vertices',vert, 'FaceVertexCData',[0, 1, 0; 0, 0, 1]); +%! patch ('Faces',fac, 'Vertices',vert, ... +%! 'FaceVertexCData',[0, 1, 0; 0, 0, 1], 'FaceColor', 'flat'); %!demo %! %% Property change on multiple patches @@ -223,7 +235,7 @@ %! colormap (jet (64)); %! x = [ 0 0; 1 1; 1 0 ]; %! y = [ 0 0; 0 1; 1 1 ]; -%! p = patch (x, y, 'facecolor', 'b'); +%! p = patch (x, y, 'b'); %! set (p, 'cdatamapping', 'direct', 'facecolor', 'flat', 'cdata', [1 32]); %! title ('Direct mapping of colors: Light-Green UL and Blue LR triangles'); diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/peaks.m --- a/scripts/plot/draw/peaks.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/peaks.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/pie.m --- a/scripts/plot/draw/pie.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/pie.m Fri Aug 01 12:10:05 2014 -0400 @@ -30,7 +30,7 @@ ## @code{pct = @var{x}(i) / sum (@var{x})}. ## ## The optional input @var{explode} is a vector of the same length as @var{x} -## that, if non-zero, "explodes" the slice from the pie chart. +## that, if nonzero, "explodes" the slice from the pie chart. ## ## The optional input @var{labels} is a cell array of strings of the same ## length as @var{x} specifying the label for each slice. diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/pie3.m --- a/scripts/plot/draw/pie3.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/pie3.m Fri Aug 01 12:10:05 2014 -0400 @@ -31,7 +31,7 @@ ## @code{pct = @var{x}(i) / sum (@var{x})}. ## ## The optional input @var{explode} is a vector of the same length as @var{x} -## that, if non-zero, "explodes" the slice from the pie chart. +## that, if nonzero, "explodes" the slice from the pie chart. ## ## The optional input @var{labels} is a cell array of strings of the same ## length as @var{x} specifying the label for each slice. diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/plot3.m --- a/scripts/plot/draw/plot3.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/plot3.m Fri Aug 01 12:10:05 2014 -0400 @@ -377,12 +377,14 @@ %!demo %! clf; %! z = [0:0.05:5]; -%! plot3 (cos (2*pi*z), sin (2*pi*z), z, ';helix;'); +%! plot3 (cos (2*pi*z), sin (2*pi*z), z) +%! legend ('helix'); %! title ('plot3() of a helix'); %!demo %! clf; %! z = [0:0.05:5]; -%! plot3 (z, exp (2i*pi*z), ';complex sinusoid;'); +%! plot3 (z, exp (2i*pi*z)); +%! legend ('complex sinusoid'); %! title ('plot3() with complex input'); diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/plotyy.m --- a/scripts/plot/draw/plotyy.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/plotyy.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/polar.m --- a/scripts/plot/draw/polar.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/polar.m Fri Aug 01 12:10:05 2014 -0400 @@ -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,51 @@ print_usage (); endif - set (hax, "xlim", [-maxr, maxr], "ylim", [-maxr, maxr], - "xaxislocation", "zero", "yaxislocation", "zero", - "plotboxaspectratio", [1, 1, 1]); + if (! ishold (hax)) + hg = hggroup (hax, "tag", "polar_grid", "handlevisibility", "off"); + + set (hax, "visible", "off", "plotboxaspectratio", [1, 1, 1], + "zlim", [-1 1]); + + if (! isprop (hax, "rtick")) + addproperty ("rtick", hax, "data"); + endif + + set (hax, "rtick", __calc_rtick__ (hax, maxr)); + + ## add t(heta)tick + if (! isprop (hax, "ttick")) + addproperty ("ttick", hax, "data"); + endif + + ## theta(angular) ticks in degrees + set (hax, "ttick", 0:30:330); + + __update_polar_grid__ (hax, [], hg); + + set (hg, "deletefcn", {@resetaxis, hax}); + + 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"}); + else + hg = findall (hax, "tag", "polar_grid"); + if (! isempty (hg)) + oldrtick = max (get (hax, "rtick")); + if (maxr > oldrtick) + set (hax, "rtick", __calc_rtick__ (hax, maxr)); + endif + endif + endif unwind_protect_cleanup if (! isempty (oldfig)) @@ -103,6 +153,19 @@ endfunction +function rtick = __calc_rtick__ (hax, maxr) + ## FIXME: workaround: calculate r(ho)tick from xtick + savexlim = get (hax, "xlim"); + saveylim = get (hax, "ylim"); + set (hax, "xlim", [-maxr maxr], "ylim", [-maxr maxr]); + xtick = get (hax, "xtick"); + rtick = xtick(find (xtick > 0, 1):find (xtick >= maxr, 1)); + if (isempty (rtick)) + rtick = [0.5 1]; + endif + set (hax, "xlim", savexlim, "ylim", saveylim); +endfunction + function retval = __plr1__ (h, theta, fmt) theta = theta(:); @@ -193,6 +256,133 @@ 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 + +function resetaxis (~, ~, hax) + if (isaxes (hax)) + dellistener (hax, "rtick"); + dellistener (hax, "ttick"); + dellistener (hax, "color"); + dellistener (hax, "fontangle"); + dellistener (hax, "fontname"); + dellistener (hax, "fontsize"); + dellistener (hax, "fontunits"); + dellistener (hax, "fontweight"); + dellistener (hax, "interpreter"); + dellistener (hax, "layer"); + dellistener (hax, "gridlinestyle"); + dellistener (hax, "linewidth"); + endif +endfunction + %!demo %! clf; @@ -210,8 +400,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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/private/__ezplot__.m --- a/scripts/plot/draw/private/__ezplot__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/private/__ezplot__.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/private/__patch__.m --- a/scripts/plot/draw/private/__patch__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/private/__patch__.m Fri Aug 01 12:10:05 2014 -0400 @@ -35,8 +35,7 @@ is_numeric_arg = cellfun (@isnumeric, varargin); if (isempty (varargin)) - args = {"xdata", [0; 1; 0], "ydata", [1; 1; 0], "facecolor", [0, 0, 0]}; - args = setvertexdata (args); + args = varargin; elseif (isstruct (varargin{1})) if (isfield (varargin{1}, "vertices") && isfield (varargin{1}, "faces")) args{1} = "faces"; @@ -50,7 +49,6 @@ args{6} = []; endif args = [args; varargin(2:end)]; - args = setdata (args); else failed = true; endif @@ -58,7 +56,6 @@ if (nargin < 3 || ! is_numeric_arg(2)) failed = true; else - if (nargin > 4 && all (is_numeric_arg(1:4))) x = varargin{1}; y = varargin{2}; @@ -70,7 +67,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 +80,7 @@ z = []; iarg = 3; if (rem (nargin - iarg, 2) == 1) - c = varargin {iarg}; + c = varargin{iarg}; iarg++; else c = []; @@ -127,7 +124,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 +147,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,212 +156,35 @@ 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"; args{10} = []; else args{7} = "facecolor"; - args{8} = [0, 1, 0]; + args{8} = [0, 0, 0]; args{9} = "cdata"; args{10} = []; endif args = [args, varargin(iarg:end)]; - args = setvertexdata (args); endif else args = varargin; - if (any (strcmpi (args, "faces") | strcmpi (args, "vertices"))) - args = setdata (args); - else - args = setvertexdata (args); - endif endif if (!failed) - h = __go_patch__ (p, args {:}); - - ## Setup listener functions - addlistener (h, "xdata", @update_data); - addlistener (h, "ydata", @update_data); - addlistener (h, "zdata", @update_data); - addlistener (h, "cdata", @update_data); - - addlistener (h, "faces", @update_fvc); - addlistener (h, "vertices", @update_fvc); - addlistener (h, "facevertexcdata", @update_fvc); + h = __go_patch__ (p, args{:}); endif endfunction - -function args = delfields (args, flds) - idx = cellfun ("isclass", args, "char"); - idx(idx) = ismember (args(idx), flds); - if (rows (idx) == 1) - idx |= [false, idx(1:end-1)]; - else - idx |= [false; idx(1:end-1)]; - endif - args(idx) = []; -endfunction - -function args = setdata (args) - args = delfields (args, {"xdata", "ydata", "zdata", "cdata"}); - ## Remove the readonly fields as well - args = delfields (args, {"type", "uicontextmenu"}); - nargs = length (args); - idx = find (strcmpi (args, "faces"), 1, "last") + 1; - if (idx > nargs) - faces = []; - else - faces = args {idx}; - endif - idx = find (strcmpi (args, "vertices"), 1, "last") + 1; - if (idx > nargs) - vert = []; - else - vert = args {idx}; - endif - idx = find (strcmpi (args, "facevertexcdata"), 1, "last") + 1; - if (isempty (idx) || idx > nargs) - fvc = []; - else - fvc = args {idx}; - endif - idx = find (strcmpi (args, "facecolor"), 1, "last") + 1; - if (isempty (idx) || idx > nargs) - if (!isempty (fvc)) - fc = "flat"; - else - fc = [0, 1, 0]; - endif - args = {"facecolor", fc, args{:}}; - endif - - nc = rows (faces); - idx = faces .'; - t1 = isnan (idx); - for i = find (any (t1)) - first_idx_in_column = find (t1(:,i), 1); - idx(first_idx_in_column:end,i) = idx(first_idx_in_column-1,i); - endfor - x = reshape (vert(:,1)(idx), size (idx)); - y = reshape (vert(:,2)(idx), size (idx)); - if (columns (vert) > 2) - z = reshape (vert(:,3)(idx), size (idx)); - else - z = []; - endif - - if (rows (fvc) == nc || rows (fvc) == 1) - c = reshape (fvc, [1, size(fvc)]); - 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))); - elseif (isempty (fvc)) - c = []; - else ## if (columnns (fvc) == 1) - c = permute (fvc(faces), [2, 1]); - endif - endif - args = {"xdata", x, "ydata", y, "zdata", z, "cdata", c, args{:}}; -endfunction - -function args = setvertexdata (args) - args = delfields (args, {"vertices", "faces", "facevertexcdata"}); - ## Remove the readonly fields as well - args = delfields (args, {"type", "uicontextmenu"}); - nargs = length (args); - idx = find (strcmpi (args, "xdata"), 1, "last") + 1; - if (idx > nargs) - x = []; - else - x = args {idx}; - endif - idx = find (strcmpi (args, "ydata"), 1, "last") + 1; - if (idx > nargs) - y = []; - else - y = args {idx}; - endif - idx = find (strcmpi (args, "zdata"), 1, "last") + 1; - if (isempty (idx) || idx > nargs) - z = []; - else - z = args {idx}; - endif - idx = find (strcmpi (args, "cdata"), 1, "last") + 1; - if (isempty (idx) || idx > nargs) - c = []; - else - c = args {idx}; - endif - idx = find (strcmpi (args, "facecolor"), 1, "last") + 1; - if (isempty (idx) || idx > nargs) - if (!isempty (c)) - fc = "flat"; - else - fc = [0, 1, 0]; - endif - args = {"facecolor", fc, args{:}}; - endif - - [nr, nc] = size (x); - if (nr == 1 && nc > 1) - nr = nc; - nc = 1; - endif - if (!isempty (z)) - vert = [x(:), y(:), z(:)]; - else - vert = [x(:), y(:)]; - endif - faces = reshape (1:numel (x), nr, nc); - faces = faces'; - - if (ndims (c) == 3) - fvc = reshape (c, rows (c) * columns (c), size (c, 3)); - else - fvc = c(:); - endif - - args = {"faces", faces, "vertices", vert, "facevertexcdata", fvc, args{:}}; -endfunction - -function update_data (h, d) - update_handle (h, false); -endfunction - -function update_fvc (h, d) - update_handle (h, true); -endfunction - -function update_handle (h, isfv) - persistent recursive = false; - - if (! recursive) - recursive = true; - f = get (h); - if (isfv) - set (h, setdata ([fieldnames(f), struct2cell(f)].'(:)){:}); - else - set (h, setvertexdata ([fieldnames(f), struct2cell(f)].'(:)){:}); - endif - recursive = false; - endif -endfunction - diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/private/__scatter__.m --- a/scripts/plot/draw/private/__scatter__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/private/__scatter__.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/private/__stem__.m --- a/scripts/plot/draw/private/__stem__.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/private/__stem__.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/rose.m --- a/scripts/plot/draw/rose.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/rose.m Fri Aug 01 12:10:05 2014 -0400 @@ -116,6 +116,11 @@ %!demo %! clf; +%! rose (2*randn (1e5, 1), 8); +%! title ('rose() angular histogram plot with 8 bins'); + +%!demo +%! clf; %! rose ([2*randn(1e5, 1), pi + 2*randn(1e5, 1)]); -%! title ('rose() angular histogram plot'); +%! title ('rose() angular histogram plot with 2 data series'); diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/shrinkfaces.m --- a/scripts/plot/draw/shrinkfaces.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/shrinkfaces.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/stem.m --- a/scripts/plot/draw/stem.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/stem.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/stemleaf.m --- a/scripts/plot/draw/stemleaf.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/stemleaf.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/surface.m --- a/scripts/plot/draw/surface.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/surface.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/surfc.m --- a/scripts/plot/draw/surfc.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/surfc.m Fri Aug 01 12:10:05 2014 -0400 @@ -71,9 +71,15 @@ unwind_protect hax = newplot (hax); - htmp = surface (varargin{:}); + surfc_props = {"facecolor", "flat"}; + chararg = find (cellfun ("isclass", varargin, "char"), 1); + if (isempty (chararg)) + htmp = surface (varargin{:}, surfc_props{:}); + else + htmp = surface (varargin{1:chararg-1}, surfc_props{:}, + varargin{chararg:end}); + endif - set (htmp, "facecolor", "flat"); if (! ishold ()) set (hax, "view", [-37.5, 30], "xgrid", "on", "ygrid", "on", "zgrid", "on", diff -r c59745865c7f -r dcb260e7a648 scripts/plot/draw/surfl.m --- a/scripts/plot/draw/surfl.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/surfl.m Fri Aug 01 12:10:05 2014 -0400 @@ -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 c59745865c7f -r dcb260e7a648 scripts/plot/draw/surfnorm.m --- a/scripts/plot/draw/surfnorm.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/draw/surfnorm.m Fri Aug 01 12:10:05 2014 -0400 @@ -19,49 +19,56 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} surfnorm (@var{x}, @var{y}, @var{z}) ## @deftypefnx {Function File} {} surfnorm (@var{z}) +## @deftypefnx {Function File} {} surfnorm (@dots{}, @var{prop}, @var{val}, @dots{}) +## @deftypefnx {Function File} {} surfnorm (@var{hax}, @dots{}) ## @deftypefnx {Function File} {[@var{nx}, @var{ny}, @var{nz}] =} surfnorm (@dots{}) -## @deftypefnx {Function File} {} surfnorm (@var{h}, @dots{}) -## Find the vectors normal to a meshgridded surface. The meshed gridded -## surface is defined by @var{x}, @var{y}, and @var{z}. If @var{x} and -## @var{y} are not defined, then it is assumed that they are given by +## Find the vectors normal to a meshgridded surface. ## -## @example -## @group -## [@var{x}, @var{y}] = meshgrid (1:rows (@var{z}), -## 1:columns (@var{z})); -## @end group -## @end example +## If @var{x} and @var{y} are vectors, then a typical vertex is +## (@var{x}(j), @var{y}(i), @var{z}(i,j)). Thus, columns of @var{z} correspond +## to different @var{x} values and rows of @var{z} correspond to different +## @var{y} values. If only a single input @var{z} is given then @var{x} is +## taken to be @code{1:rows (@var{z})} and @var{y} is +## @code{1:columns (@var{z})}. ## ## If no return arguments are requested, a surface plot with the normal -## vectors to the surface is plotted. Otherwise the components of the normal -## vectors at the mesh gridded points are returned in @var{nx}, @var{ny}, -## and @var{nz}. +## vectors to the surface is plotted. ## -## The normal vectors are calculated by taking the cross product of the -## diagonals of each of the quadrilaterals in the meshgrid to find the -## normal vectors of the centers of these quadrilaterals. The four nearest -## normal vectors to the meshgrid points are then averaged to obtain the -## normal to the surface at the meshgridded points. +## Any property/value input pairs are assigned to the surface object. +## +## If the first argument @var{hax} is an axes handle, then plot into this axis, +## rather than the current axes returned by @code{gca}. +## +## If output arguments are requested then the components of the normal +## vectors are returne in @var{nx}, @var{ny}, and @var{nz} and no plot is +## made. ## ## An example of the use of @code{surfnorm} is ## ## @example ## surfnorm (peaks (25)); ## @end example -## @seealso{surf, quiver3} +## +## Algorithm: The normal vectors are calculated by taking the cross product +## of the diagonals of each of the quadrilaterals in the meshgrid to find the +## normal vectors of the centers of these quadrilaterals. The four nearest +## normal vectors to the meshgrid points are then averaged to obtain the +## normal to the surface at the meshgridded points. +## +## @seealso{isonormals, quiver3, surf, meshgrid} ## @end deftypefn function [Nx, Ny, Nz] = surfnorm (varargin) [hax, varargin, nargin] = __plt_get_axis_arg__ ("surfnorm", varargin{:}); - if (nargin != 1 && nargin != 3) + if (nargin == 0 || nargin == 2) print_usage (); endif if (nargin == 1) z = varargin{1}; - [x, y] = meshgrid (1:rows (z), 1:columns (z)); + [x, y] = meshgrid (1:columns (z), 1:rows (z)); ioff = 2; else x = varargin{1}; @@ -70,22 +77,24 @@ ioff = 4; endif - if (!ismatrix (z) || isvector (z) || isscalar (z)) - error ("surfnorm: Z argument must be a matrix"); + if (iscomplex (z) || iscomplex (x) || iscomplex (y)) + error ("surfnorm: X, Y, and Z must be 2-D real matrices"); endif if (! size_equal (x, y, z)) error ("surfnorm: X, Y, and Z must have the same dimensions"); endif - ## Make life easier, and avoid having to do the extrapolation later, do - ## a simpler linear extrapolation here. This is approximative, and works - ## badly for closed surfaces like spheres. - xx = [2 .* x(:,1) - x(:,2), x, 2 .* x(:,end) - x(:,end-1)]; - xx = [2 .* xx(1,:) - xx(2,:); xx; 2 .* xx(end,:) - xx(end-1,:)]; - yy = [2 .* y(:,1) - y(:,2), y, 2 .* y(:,end) - y(:,end-1)]; - yy = [2 .* yy(1,:) - yy(2,:); yy; 2 .* yy(end,:) - yy(end-1,:)]; - zz = [2 .* z(:,1) - z(:,2), z, 2 .* z(:,end) - z(:,end-1)]; - zz = [2 .* zz(1,:) - zz(2,:); zz; 2 .* zz(end,:) - zz(end-1,:)]; + ## Do a linear extrapolation for mesh points on the boundary so that the mesh + ## is increased by 1 on each side. This allows each original meshgrid point + ## to be surrounded by four quadrilaterals and the same calculation can be + ## used for interior and boundary points. The extrapolation works badly for + ## closed surfaces like spheres. + xx = [2 * x(:,1) - x(:,2), x, 2 * x(:,end) - x(:,end-1)]; + xx = [2 * xx(1,:) - xx(2,:); xx; 2 * xx(end,:) - xx(end-1,:)]; + yy = [2 * y(:,1) - y(:,2), y, 2 * y(:,end) - y(:,end-1)]; + yy = [2 * yy(1,:) - yy(2,:); yy; 2 * yy(end,:) - yy(end-1,:)]; + zz = [2 * z(:,1) - z(:,2), z, 2 * z(:,end) - z(:,end-1)]; + zz = [2 * zz(1,:) - zz(2,:); zz; 2 * zz(end,:) - zz(end-1,:)]; u.x = xx(1:end-1,1:end-1) - xx(2:end,2:end); u.y = yy(1:end-1,1:end-1) - yy(2:end,2:end); @@ -101,17 +110,19 @@ ## Create normal vectors as mesh vectices from normals at mesh centers nx = (w.x(1:end-1,1:end-1) + w.x(1:end-1,2:end) + - w.x(2:end,1:end-1) + w.x(2:end,2:end)) ./ 4; + w.x(2:end,1:end-1) + w.x(2:end,2:end)) / 4; ny = (w.y(1:end-1,1:end-1) + w.y(1:end-1,2:end) + - w.y(2:end,1:end-1) + w.y(2:end,2:end)) ./ 4; + w.y(2:end,1:end-1) + w.y(2:end,2:end)) / 4; nz = (w.z(1:end-1,1:end-1) + w.z(1:end-1,2:end) + - w.z(2:end,1:end-1) + w.z(2:end,2:end)) ./ 4; + w.z(2:end,1:end-1) + w.z(2:end,2:end)) / 4; + ## FIXME: According to Matlab documentation the vertex normals + ## returned are not normalized. ## Normalize the normal vectors len = sqrt (nx.^2 + ny.^2 + nz.^2); - nx = nx ./ len; - ny = ny ./ len; - nz = nz ./ len; + nx ./= len; + ny ./= len; + nz ./= len; if (nargout == 0) oldfig = []; @@ -125,10 +136,26 @@ old_hold_state = get (hax, "nextplot"); unwind_protect set (hax, "nextplot", "add"); - plot3 ([x(:)'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:), - [y(:)'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:), - [z(:)'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:), - varargin{ioff:end}); + + ## FIXME: Scale unit normals by data aspect ratio in order for + ## normals to appear correct. + ##daratio = daspect (hax); + ##daspect ("manual"); + ##len = norm (daratio); + ## This assumes an even meshgrid which isn't a great assumption + ##dx = x(1,2) - x(1,1); + ##dy = y(2,1) - y(1,1); + ##nx *= daratio(1); + ##ny *= daratio(2); + ##nz *= daratio(3); + ##len = sqrt (nx.^2 + ny.^2 + nz.^2); + ##nx ./= len; + ##ny ./= len; + ##nz ./= len; + plot3 ([x(:).'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:), + [y(:).'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:), + [z(:).'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:), + "r"); unwind_protect_cleanup set (hax, "nextplot", old_hold_state); end_unwind_protect @@ -150,17 +177,25 @@ %!demo %! clf; %! colormap ('default'); -%! [x, y, z] = peaks (10); -%! surfnorm (x, y, z); +%! surfnorm (peaks (32)); +%! shading interp; +%! title ({'surfnorm() shows surface and normals at each vertex', ... +%! 'peaks() function with 32 faces'}); %!demo %! clf; %! colormap ('default'); -%! surfnorm (peaks (10)); +%! [x, y, z] = sombrero (10); +%! surfnorm (x, y, z); -%!demo -%! clf; -%! colormap ('default'); -%! surfnorm (peaks (32)); -%! shading interp; +%% Test input validation +%!error surfnorm () +%!error surfnorm (1,2) +%!error surfnorm (i) +%!error surfnorm (i, 1, 1) +%!error surfnorm (1, i, 1) +%!error surfnorm (1, 1, i) +%!error surfnorm ([1 2], 1, 1) +%!error surfnorm (1, [1 2], 1) +%!error surfnorm (1, 1, [1 2]) diff -r c59745865c7f -r dcb260e7a648 scripts/plot/util/colstyle.m --- a/scripts/plot/util/colstyle.m Fri Aug 01 09:06:21 2014 -0400 +++ b/scripts/plot/util/colstyle.m Fri Aug 01 12:10:05 2014 -0400 @@ -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